Merge "init: Set perms for interactive cpufreq governor boostpulse" into jb-dev
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
index f672336..323a09d 100644
--- a/cpio/mkbootfs.c
+++ b/cpio/mkbootfs.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -34,12 +35,51 @@
exit(1);
}
+struct fs_config_entry {
+ char* name;
+ int uid, gid, mode;
+};
+
+static struct fs_config_entry* canned_config = NULL;
+
+/* Each line in the canned file should be a path plus three ints (uid,
+ * gid, mode). */
+#ifdef PATH_MAX
+#define CANNED_LINE_LENGTH (PATH_MAX+100)
+#else
+#define CANNED_LINE_LENGTH (1024)
+#endif
+
static int verbose = 0;
static int total_size = 0;
static void fix_stat(const char *path, struct stat *s)
{
- fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode);
+ if (canned_config) {
+ // Use the list of file uid/gid/modes loaded from the file
+ // given with -f.
+
+ struct fs_config_entry* empty_path_config = NULL;
+ struct fs_config_entry* p;
+ for (p = canned_config; p->name; ++p) {
+ if (!p->name[0]) {
+ empty_path_config = p;
+ }
+ if (strcmp(p->name, path) == 0) {
+ s->st_uid = p->uid;
+ s->st_gid = p->gid;
+ s->st_mode = p->mode | (s->st_mode & ~07777);
+ return;
+ }
+ }
+ s->st_uid = empty_path_config->uid;
+ s->st_gid = empty_path_config->gid;
+ s->st_mode = empty_path_config->mode | (s->st_mode & ~07777);
+ } else {
+ // Use the compiled-in fs_config() function.
+
+ fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode);
+ }
}
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
@@ -79,7 +119,7 @@
total_size += 6 + 8*13 + olen + 1;
- if(strlen(out) != olen) die("ACK!");
+ if(strlen(out) != (unsigned int)olen) die("ACK!");
while(total_size & 3) {
total_size++;
@@ -235,11 +275,61 @@
_archive_dir(in, out, strlen(in), strlen(out));
}
+static void read_canned_config(char* filename)
+{
+ int allocated = 8;
+ int used = 0;
+
+ canned_config =
+ (struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry));
+
+ char line[CANNED_LINE_LENGTH];
+ FILE* f = fopen(filename, "r");
+ if (f == NULL) die("failed to open canned file");
+
+ while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) {
+ if (!line[0]) break;
+ if (used >= allocated) {
+ allocated *= 2;
+ canned_config = (struct fs_config_entry*)realloc(
+ canned_config, allocated * sizeof(struct fs_config_entry));
+ }
+
+ struct fs_config_entry* cc = canned_config + used;
+
+ if (isspace(line[0])) {
+ cc->name = strdup("");
+ cc->uid = atoi(strtok(line, " \n"));
+ } else {
+ cc->name = strdup(strtok(line, " \n"));
+ cc->uid = atoi(strtok(NULL, " \n"));
+ }
+ cc->gid = atoi(strtok(NULL, " \n"));
+ cc->mode = strtol(strtok(NULL, " \n"), NULL, 8);
+ ++used;
+ }
+ if (used >= allocated) {
+ ++allocated;
+ canned_config = (struct fs_config_entry*)realloc(
+ canned_config, allocated * sizeof(struct fs_config_entry));
+ }
+ canned_config[used].name = NULL;
+
+ fclose(f);
+}
+
+
int main(int argc, char *argv[])
{
argc--;
argv++;
+ if (argc > 1 && strcmp(argv[0], "-f") == 0) {
+ read_canned_config(argv[1]);
+ argc -= 2;
+ argv += 2;
+ }
+
if(argc == 0) die("no directories to process?!");
while(argc-- > 0){
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 994eeae..46b0828 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -255,6 +255,7 @@
#else
fd = fileno(tmpfile());
#endif
+ /* reset ext4fs info so we can be called multiple times */
reset_ext4fs_info();
info.len = image->partition_size;
make_ext4fs_internal(fd, NULL, NULL, NULL, 0, 1, 0, 0, 0, NULL);
@@ -266,7 +267,7 @@
close(fd);
}
-int fb_format(Action *a, usb_handle *usb)
+int fb_format(Action *a, usb_handle *usb, int skip_if_not_supported)
{
const char *partition = a->cmd;
char response[FB_RESPONSE_SZ+1];
@@ -281,6 +282,13 @@
snprintf(cmd, sizeof(cmd), "getvar:partition-type:%s", partition);
status = fb_command_response(usb, cmd, response);
if (status) {
+ if (skip_if_not_supported) {
+ fprintf(stderr,
+ "Erase successful, but not automatically formatting.\n");
+ fprintf(stderr,
+ "Can't determine partition type.\n");
+ return 0;
+ }
fprintf(stderr,"FAILED (%s)\n", fb_get_error());
return status;
}
@@ -292,6 +300,13 @@
}
}
if (!generator) {
+ if (skip_if_not_supported) {
+ fprintf(stderr,
+ "Erase successful, but not automatically formatting.\n");
+ fprintf(stderr,
+ "File system type %s not supported.\n", response);
+ return 0;
+ }
fprintf(stderr,"Formatting is not supported for filesystem with type '%s'.\n",
response);
return -1;
@@ -301,6 +316,12 @@
snprintf(cmd, sizeof(cmd), "getvar:partition-size:%s", partition);
status = fb_command_response(usb, cmd, response);
if (status) {
+ if (skip_if_not_supported) {
+ fprintf(stderr,
+ "Erase successful, but not automatically formatting.\n");
+ fprintf(stderr, "Unable to get partition size\n.");
+ return 0;
+ }
fprintf(stderr,"FAILED (%s)\n", fb_get_error());
return status;
}
@@ -329,11 +350,12 @@
return status;
}
-void fb_queue_format(const char *partition)
+void fb_queue_format(const char *partition, int skip_if_not_supported)
{
Action *a;
a = queue_action(OP_FORMAT, partition);
+ a->data = (void*)skip_if_not_supported;
a->msg = mkmsg("formatting '%s' partition", partition);
}
@@ -545,7 +567,7 @@
} else if (a->op == OP_NOTICE) {
fprintf(stderr,"%s\n",(char*)a->data);
} else if (a->op == OP_FORMAT) {
- status = fb_format(a, usb);
+ status = fb_format(a, usb, (int)a->data);
status = a->func(a, status, status ? fb_get_error() : "");
if (status) break;
} else {
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index af61f88..848cea3 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -640,7 +640,7 @@
skip(2);
} else if(!strcmp(*argv, "format")) {
require(2);
- fb_queue_format(argv[1]);
+ fb_queue_format(argv[1], 0);
skip(2);
} else if(!strcmp(*argv, "signature")) {
require(2);
@@ -727,7 +727,9 @@
if (wants_wipe) {
fb_queue_erase("userdata");
+ fb_queue_format("userdata", 1);
fb_queue_erase("cache");
+ fb_queue_format("cache", 1);
}
if (wants_reboot) {
fb_queue_reboot();
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 7d56ecb..1d3e2b8 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -43,7 +43,7 @@
/* engine.c - high level command queue engine */
void fb_queue_flash(const char *ptn, void *data, unsigned sz);;
void fb_queue_erase(const char *ptn);
-void fb_queue_format(const char *ptn);
+void fb_queue_format(const char *ptn, int skip_if_not_supported);
void fb_queue_require(const char *prod, const char *var, int invert,
unsigned nvalues, const char **value);
void fb_queue_display(const char *var, const char *prettyname);
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 68928eb..6521cbe 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -138,7 +138,7 @@
#define android_id_count \
(sizeof(android_ids) / sizeof(android_ids[0]))
-
+
struct fs_path_config {
unsigned mode;
unsigned uid;
@@ -234,7 +234,7 @@
{
struct fs_path_config *pc;
int plen;
-
+
pc = dir ? android_dirs : android_files;
plen = strlen(path);
for(; pc->prefix; pc++){
@@ -254,9 +254,9 @@
*uid = pc->uid;
*gid = pc->gid;
*mode = (*mode & (~07777)) | pc->mode;
-
+
#if 0
- fprintf(stderr,"< '%s' '%s' %d %d %o >\n",
+ fprintf(stderr,"< '%s' '%s' %d %d %o >\n",
path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode);
#endif
}
diff --git a/include/system/camera.h b/include/system/camera.h
index b8389b1..e4cacc5 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -137,7 +137,8 @@
* KEY_FOCUS_AREAS and KEY_METERING_AREAS have no effect.
*
* arg1 is the face detection type. It can be CAMERA_FACE_DETECTION_HW or
- * CAMERA_FACE_DETECTION_SW.
+ * CAMERA_FACE_DETECTION_SW. If the type of face detection requested is not
+ * supported, the HAL must return BAD_VALUE.
*/
CAMERA_CMD_START_FACE_DETECTION = 6,
diff --git a/include/system/window.h b/include/system/window.h
index 1a036df..8e00bcd 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -248,7 +248,7 @@
NATIVE_WINDOW_API_CONNECT = 13, /* private */
NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
- NATIVE_WINDOW_SET_ACTIVE_RECT = 16, /* private */
+ NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */
};
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -298,6 +298,11 @@
* of the buffer matches the window size (cropping in the process)
*/
NATIVE_WINDOW_SCALING_MODE_SCALE_CROP = 2,
+ /* the window is clipped to the size of the buffer's crop rectangle; pixels
+ * outside the crop rectangle are treated as if they are completely
+ * transparent.
+ */
+ NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP = 3,
};
/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
@@ -440,7 +445,7 @@
* NATIVE_WINDOW_API_CONNECT (private)
* NATIVE_WINDOW_API_DISCONNECT (private)
* NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS (private)
- * NATIVE_WINDOW_SET_ACTIVE_RECT (private)
+ * NATIVE_WINDOW_SET_POST_TRANSFORM_CROP (private)
*
*/
@@ -504,14 +509,16 @@
/*
* native_window_set_crop(..., crop)
* Sets which region of the next queued buffers needs to be considered.
- * A buffer's crop region is scaled to match the surface's size.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size. This function sets the crop in
+ * pre-transformed buffer pixel coordinates.
*
* The specified crop region applies to all buffers queued after it is called.
*
- * if 'crop' is NULL, subsequently queued buffers won't be cropped.
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
*
- * An error is returned if for instance the crop region is invalid,
- * out of the buffer's bound or if the window is invalid.
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
*/
static inline int native_window_set_crop(
struct ANativeWindow* window,
@@ -521,23 +528,38 @@
}
/*
+ * native_window_set_post_transform_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * Depending on the scaling mode, a buffer's crop region is scaled and/or
+ * cropped to match the surface's size. This function sets the crop in
+ * post-transformed pixel coordinates.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * If 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid, out of the
+ * buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_post_transform_crop(
+ struct ANativeWindow* window,
+ android_native_rect_t const * crop)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
+}
+
+/*
* native_window_set_active_rect(..., active_rect)
- * Sets the region of future queued buffers that are 'active'. Pixels outside
- * this 'active' region are considered to be completely transparent regardless
- * of the pixel values in the buffer. The active_rect argument specifies the
- * active rectangle in buffer pixel coordinates.
*
- * The specified active rectangle applies to all buffers queued after it is
- * called.
- *
- * An error is returned if for instance the crop region is invalid,
- * out of the buffer's bound or if the window is invalid.
+ * This function is deprectated and will be removed soon. For now it simply
+ * sets the post-transform crop for compatibility while multi-project commits
+ * get checked.
*/
static inline int native_window_set_active_rect(
struct ANativeWindow* window,
android_native_rect_t const * active_rect)
{
- return window->perform(window, NATIVE_WINDOW_SET_ACTIVE_RECT, active_rect);
+ return native_window_set_post_transform_crop(window, active_rect);
}
/*
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 20771c0..e03ce00 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -16,24 +16,31 @@
** limitations under the License.
*/
+#define LOG_TAG "SchedPolicy"
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <cutils/sched_policy.h>
+#include <cutils/log.h>
-#define LOG_TAG "SchedPolicy"
-#include "cutils/log.h"
+/* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
+ * Call this any place a SchedPolicy is used as an input parameter.
+ * Returns the possibly re-mapped policy.
+ */
+static inline SchedPolicy _policy(SchedPolicy p)
+{
+ return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
+}
-#ifdef HAVE_SCHED_H
-#ifdef HAVE_PTHREADS
+#if defined(HAVE_ANDROID_OS) && defined(HAVE_SCHED_H) && defined(HAVE_PTHREADS)
#include <sched.h>
#include <pthread.h>
-#include <cutils/sched_policy.h>
-
#ifndef SCHED_NORMAL
#define SCHED_NORMAL 0
#endif
@@ -124,32 +131,32 @@
#if CAN_SET_SP_SYSTEM
filename = "/dev/cpuctl/tasks";
- system_cgroup_fd = open(filename, O_WRONLY);
+ system_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (system_cgroup_fd < 0) {
SLOGV("open of %s failed: %s\n", filename, strerror(errno));
}
#endif
filename = "/dev/cpuctl/foreground/tasks";
- fg_cgroup_fd = open(filename, O_WRONLY);
+ fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (fg_cgroup_fd < 0) {
SLOGE("open of %s failed: %s\n", filename, strerror(errno));
}
filename = "/dev/cpuctl/bg_non_interactive/tasks";
- bg_cgroup_fd = open(filename, O_WRONLY);
+ bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (bg_cgroup_fd < 0) {
SLOGE("open of %s failed: %s\n", filename, strerror(errno));
}
filename = "/dev/cpuctl/audio_app/tasks";
- audio_app_cgroup_fd = open(filename, O_WRONLY);
+ audio_app_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (audio_app_cgroup_fd < 0) {
SLOGV("open of %s failed: %s\n", filename, strerror(errno));
}
filename = "/dev/cpuctl/audio_sys/tasks";
- audio_sys_cgroup_fd = open(filename, O_WRONLY);
+ audio_sys_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
if (audio_sys_cgroup_fd < 0) {
SLOGV("open of %s failed: %s\n", filename, strerror(errno));
}
@@ -274,15 +281,6 @@
return 0;
}
-/* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
- * Call this any place a SchedPolicy is used as an input parameter.
- * Returns the possibly re-mapped policy.
- */
-static inline SchedPolicy _policy(SchedPolicy p)
-{
- return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
-}
-
int set_sched_policy(int tid, SchedPolicy policy)
{
#ifdef HAVE_GETTID
@@ -356,6 +354,23 @@
return 0;
}
+#else
+
+/* Stubs for non-Android targets. */
+
+int set_sched_policy(int tid, SchedPolicy policy)
+{
+ return 0;
+}
+
+int get_sched_policy(int tid, SchedPolicy *policy)
+{
+ *policy = SP_SYSTEM_DEFAULT;
+ return 0;
+}
+
+#endif
+
const char *get_sched_policy_name(SchedPolicy policy)
{
policy = _policy(policy);
@@ -372,5 +387,3 @@
return "error";
}
-#endif /* HAVE_PTHREADS */
-#endif /* HAVE_SCHED_H */
diff --git a/liblog/Android.mk b/liblog/Android.mk
index bd2590e..be5cec2 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -41,7 +41,7 @@
liblog_host_sources := $(liblog_sources) fake_log_device.c
-# Static library for host
+# Shared and static library for host
# ========================================================
LOCAL_MODULE := liblog
LOCAL_SRC_FILES := $(liblog_host_sources)
@@ -49,6 +49,11 @@
LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1
include $(BUILD_HOST_STATIC_LIBRARY)
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblog
+LOCAL_WHOLE_STATIC_LIBRARIES := liblog
+include $(BUILD_HOST_SHARED_LIBRARY)
+
# Static library for host, 64-bit
# ========================================================
diff --git a/libsuspend/Android.mk b/libsuspend/Android.mk
new file mode 100644
index 0000000..45cb701
--- /dev/null
+++ b/libsuspend/Android.mk
@@ -0,0 +1,23 @@
+# Copyright 2012 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+
+libsuspend_src_files := \
+ autosuspend.c \
+ autosuspend_autosleep.c \
+ autosuspend_earlysuspend.c \
+ autosuspend_wakeup_count.c \
+
+libsuspend_libraries := \
+ liblog libcutils
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(libsuspend_src_files)
+LOCAL_MODULE := libsuspend
+LOCAL_MODULE_TAGS := optional
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := $(libsuspend_libraries)
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libsuspend/autosuspend.c b/libsuspend/autosuspend.c
new file mode 100644
index 0000000..7d1d973
--- /dev/null
+++ b/libsuspend/autosuspend.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+
+#define LOG_TAG "libsuspend"
+#include <cutils/log.h>
+
+#include <suspend/autosuspend.h>
+
+#include "autosuspend_ops.h"
+
+static struct autosuspend_ops *autosuspend_ops;
+static bool autosuspend_enabled;
+static bool autosuspend_inited;
+
+static int autosuspend_init(void)
+{
+ if (autosuspend_inited) {
+ return 0;
+ }
+
+ autosuspend_inited = true;
+
+ autosuspend_ops = autosuspend_earlysuspend_init();
+ if (autosuspend_ops) {
+ goto out;
+ }
+
+ autosuspend_ops = autosuspend_autosleep_init();
+ if (autosuspend_ops) {
+ goto out;
+ }
+
+ autosuspend_ops = autosuspend_wakeup_count_init();
+ if (autosuspend_ops) {
+ goto out;
+ }
+
+ if (!autosuspend_ops) {
+ ALOGE("failed to initialize autosuspend\n");
+ return -1;
+ }
+
+out:
+ ALOGV("autosuspend initialized\n");
+ return 0;
+}
+
+int autosuspend_enable(void)
+{
+ int ret;
+
+ ret = autosuspend_init();
+ if (ret) {
+ return ret;
+ }
+
+ ALOGV("autosuspend_enable\n");
+
+ if (autosuspend_enabled) {
+ return 0;
+ }
+
+ ret = autosuspend_ops->enable();
+ if (ret) {
+ return ret;
+ }
+
+ autosuspend_enabled = true;
+ return 0;
+}
+
+int autosuspend_disable(void)
+{
+ int ret;
+
+ ret = autosuspend_init();
+ if (ret) {
+ return ret;
+ }
+
+ ALOGV("autosuspend_disable\n");
+
+ if (!autosuspend_enabled) {
+ return 0;
+ }
+
+ ret = autosuspend_ops->disable();
+ if (ret) {
+ return ret;
+ }
+
+ autosuspend_enabled = false;
+ return 0;
+}
diff --git a/libsuspend/autosuspend_autosleep.c b/libsuspend/autosuspend_autosleep.c
new file mode 100644
index 0000000..dd0dfef
--- /dev/null
+++ b/libsuspend/autosuspend_autosleep.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define LOG_TAG "libsuspend"
+#include <cutils/log.h>
+
+#include "autosuspend_ops.h"
+
+#define SYS_POWER_AUTOSLEEP "/sys/power/autosleep"
+
+static int autosleep_fd;
+static const char *sleep_state = "mem";
+static const char *on_state = "off";
+
+static int autosuspend_autosleep_enable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_autosleep_enable\n");
+
+ ret = write(autosleep_fd, sleep_state, strlen(sleep_state));
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", SYS_POWER_AUTOSLEEP, buf);
+ goto err;
+ }
+
+ ALOGV("autosuspend_autosleep_enable done\n");
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static int autosuspend_autosleep_disable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_autosleep_disable\n");
+
+ ret = write(autosleep_fd, on_state, strlen(on_state));
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", SYS_POWER_AUTOSLEEP, buf);
+ goto err;
+ }
+
+ ALOGV("autosuspend_autosleep_disable done\n");
+
+ return 0;
+
+err:
+ return ret;
+}
+
+struct autosuspend_ops autosuspend_autosleep_ops = {
+ .enable = autosuspend_autosleep_enable,
+ .disable = autosuspend_autosleep_disable,
+};
+
+struct autosuspend_ops *autosuspend_autosleep_init(void)
+{
+ int ret;
+ char buf[80];
+
+ autosleep_fd = open(SYS_POWER_AUTOSLEEP, O_WRONLY);
+ if (autosleep_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", SYS_POWER_AUTOSLEEP, buf);
+ return NULL;
+ }
+
+ ALOGI("Selected autosleep\n");
+ return &autosuspend_autosleep_ops;
+}
diff --git a/libsuspend/autosuspend_earlysuspend.c b/libsuspend/autosuspend_earlysuspend.c
new file mode 100644
index 0000000..2c2aa36
--- /dev/null
+++ b/libsuspend/autosuspend_earlysuspend.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define LOG_TAG "libsuspend"
+#include <cutils/log.h>
+
+#include "autosuspend_ops.h"
+
+#define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state"
+#define EARLYSUSPEND_WAIT_FOR_FB_SLEEP "/sys/power/wait_for_fb_sleep"
+#define EARLYSUSPEND_WAIT_FOR_FB_WAKE "/sys/power/wait_for_fb_wake"
+
+
+static int sPowerStatefd;
+static const char *pwr_state_mem = "mem";
+static const char *pwr_state_on = "on";
+
+static int autosuspend_earlysuspend_enable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_earlysuspend_enable\n");
+
+ ret = write(sPowerStatefd, pwr_state_mem, strlen(pwr_state_mem));
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);
+ goto err;
+ }
+
+ ALOGV("autosuspend_earlysuspend_enable done\n");
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static int autosuspend_earlysuspend_disable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_earlysuspend_disable\n");
+
+ ret = write(sPowerStatefd, pwr_state_on, strlen(pwr_state_on));
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);
+ goto err;
+ }
+
+ ALOGV("autosuspend_earlysuspend_disable done\n");
+
+ return 0;
+
+err:
+ return ret;
+}
+
+struct autosuspend_ops autosuspend_earlysuspend_ops = {
+ .enable = autosuspend_earlysuspend_enable,
+ .disable = autosuspend_earlysuspend_disable,
+};
+
+struct autosuspend_ops *autosuspend_earlysuspend_init(void)
+{
+ char buf[80];
+ int ret;
+
+ ret = access(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, F_OK);
+ if (ret < 0) {
+ return NULL;
+ }
+
+ ret = access(EARLYSUSPEND_WAIT_FOR_FB_WAKE, F_OK);
+ if (ret < 0) {
+ return NULL;
+ }
+
+ sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR);
+
+ if (sPowerStatefd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf);
+ return NULL;
+ }
+
+ ALOGI("Selected early suspend\n");
+ return &autosuspend_earlysuspend_ops;
+}
diff --git a/libsuspend/autosuspend_ops.h b/libsuspend/autosuspend_ops.h
new file mode 100644
index 0000000..698e25b
--- /dev/null
+++ b/libsuspend/autosuspend_ops.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+#define _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+
+struct autosuspend_ops {
+ int (*enable)(void);
+ int (*disable)(void);
+};
+
+struct autosuspend_ops *autosuspend_autosleep_init(void);
+struct autosuspend_ops *autosuspend_earlysuspend_init(void);
+struct autosuspend_ops *autosuspend_wakeup_count_init(void);
+
+#endif
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
new file mode 100644
index 0000000..b038e20
--- /dev/null
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define LOG_TAG "libsuspend"
+#include <cutils/log.h>
+
+#include "autosuspend_ops.h"
+
+#define SYS_POWER_STATE "/sys/power/state"
+#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
+
+static int state_fd;
+static int wakeup_count_fd;
+static pthread_t suspend_thread;
+static sem_t suspend_lockout;
+static const char *sleep_state = "mem";
+
+static void *suspend_thread_func(void *arg)
+{
+ char buf[80];
+ char wakeup_count[20];
+ int wakeup_count_len;
+ int ret;
+
+ while (1) {
+ usleep(100000);
+ ALOGV("%s: read wakeup_count\n", __func__);
+ lseek(wakeup_count_fd, 0, SEEK_SET);
+ wakeup_count_len = read(wakeup_count_fd, wakeup_count, sizeof(wakeup_count));
+ if (wakeup_count_len < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error reading from %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+ wakeup_count_len = 0;
+ continue;
+ }
+ if (!wakeup_count_len) {
+ ALOGE("Empty wakeup count\n");
+ continue;
+ }
+
+ ALOGV("%s: wait\n", __func__);
+ ret = sem_wait(&suspend_lockout);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error waiting on semaphore: %s\n", buf);
+ continue;
+ }
+
+ ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
+ ret = write(wakeup_count_fd, wakeup_count, wakeup_count_len);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+ } else {
+ ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
+ ret = write(state_fd, sleep_state, strlen(sleep_state));
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", SYS_POWER_STATE, buf);
+ }
+ }
+
+ ALOGV("%s: release sem\n", __func__);
+ ret = sem_post(&suspend_lockout);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error releasing semaphore: %s\n", buf);
+ }
+ }
+ return NULL;
+}
+
+static int autosuspend_wakeup_count_enable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_wakeup_count_enable\n");
+
+ ret = sem_post(&suspend_lockout);
+
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error changing semaphore: %s\n", buf);
+ }
+
+ ALOGV("autosuspend_wakeup_count_enable done\n");
+
+ return ret;
+}
+
+static int autosuspend_wakeup_count_disable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGV("autosuspend_wakeup_count_disable\n");
+
+ ret = sem_wait(&suspend_lockout);
+
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error changing semaphore: %s\n", buf);
+ }
+
+ ALOGV("autosuspend_wakeup_count_disable done\n");
+
+ return ret;
+}
+
+struct autosuspend_ops autosuspend_wakeup_count_ops = {
+ .enable = autosuspend_wakeup_count_enable,
+ .disable = autosuspend_wakeup_count_disable,
+};
+
+struct autosuspend_ops *autosuspend_wakeup_count_init(void)
+{
+ int ret;
+ char buf[80];
+
+ state_fd = open(SYS_POWER_STATE, O_RDWR);
+ if (state_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", SYS_POWER_STATE, buf);
+ goto err_open_state;
+ }
+
+ wakeup_count_fd = open(SYS_POWER_WAKEUP_COUNT, O_RDWR);
+ if (wakeup_count_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+ goto err_open_wakeup_count;
+ }
+
+ ret = sem_init(&suspend_lockout, 0, 0);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error creating semaphore: %s\n", buf);
+ goto err_sem_init;
+ }
+ ret = pthread_create(&suspend_thread, NULL, suspend_thread_func, NULL);
+ if (ret) {
+ strerror_r(ret, buf, sizeof(buf));
+ ALOGE("Error creating thread: %s\n", buf);
+ goto err_pthread_create;
+ }
+
+ ALOGI("Selected wakeup count\n");
+ return &autosuspend_wakeup_count_ops;
+
+err_pthread_create:
+ sem_destroy(&suspend_lockout);
+err_sem_init:
+ close(wakeup_count_fd);
+err_open_wakeup_count:
+ close(state_fd);
+err_open_state:
+ return NULL;
+}
diff --git a/libsuspend/include/suspend/autosuspend.h b/libsuspend/include/suspend/autosuspend.h
new file mode 100644
index 0000000..f56fc6a
--- /dev/null
+++ b/libsuspend/include/suspend/autosuspend.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBSUSPEND_AUTOSUSPEND_H_
+#define _LIBSUSPEND_AUTOSUSPEND_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/*
+ * autosuspend_enable
+ *
+ * Turn on autosuspend in the kernel, allowing it to enter suspend if no
+ * wakelocks/wakeup_sources are held.
+ *
+ *
+ *
+ * Returns 0 on success, -1 if autosuspend was not enabled.
+ */
+int autosuspend_enable(void);
+
+/*
+ * autosuspend_disable
+ *
+ * Turn off autosuspend in the kernel, preventing suspend and synchronizing
+ * with any in-progress resume.
+ *
+ * Returns 0 on success, -1 if autosuspend was not disabled.
+ */
+int autosuspend_disable(void);
+
+__END_DECLS
+
+#endif
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 7924a44..05b7621 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -97,7 +97,7 @@
chown system system /dev/cpuctl/foreground/tasks
chmod 0666 /dev/cpuctl/foreground/tasks
write /dev/cpuctl/foreground/cpu.shares 1024
- write /dev/cpuctl/foreground/cpu.rt_runtime_us 0
+ write /dev/cpuctl/foreground/cpu.rt_runtime_us 1000
write /dev/cpuctl/foreground/cpu.rt_period_us 1000000
mkdir /dev/cpuctl/bg_non_interactive
@@ -105,7 +105,7 @@
chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
# 5.0 %
write /dev/cpuctl/bg_non_interactive/cpu.shares 52
- write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 0
+ write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 1000
write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
mkdir /dev/cpuctl/audio_app