Merge "SurfaceFlinger: Fix rect out-of-bounds checks"
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 8911570..974c865 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -73,7 +73,7 @@
         }
     } else {
         if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+            if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
                 ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
                 return -1;
             }
@@ -176,6 +176,10 @@
     return 0;
 }
 
+static int lib_dir_matcher(const char* file_name, const int is_dir) {
+  return is_dir && !strcmp(file_name, "lib");
+}
+
 int delete_user_data(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
@@ -184,7 +188,7 @@
         return -1;
 
     /* delete contents, excluding "lib", but not the directory itself */
-    return delete_dir_contents(pkgdir, 0, "lib");
+    return delete_dir_contents(pkgdir, 0, &lib_dir_matcher);
 }
 
 int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
@@ -225,7 +229,7 @@
         }
     } else {
         if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+            if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
                 ALOGE("couldn't delete lib directory during install for non-primary: %s",
                         libsymlink);
                 unlink(pkgdir);
@@ -307,7 +311,7 @@
         return -1;
 
         /* delete contents, not the directory, no exceptions */
-    return delete_dir_contents(cachedir, 0, 0);
+    return delete_dir_contents(cachedir, 0, NULL);
 }
 
 /* Try to ensure free_size bytes of storage are available.
@@ -622,12 +626,11 @@
     const char* output_file_name, const char *pkgname, const char *instruction_set)
 {
     char dex2oat_flags[PROPERTY_VALUE_MAX];
-    property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, "");
+    bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0;
     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
 
-    char profiler_prop[PROPERTY_VALUE_MAX];
-    bool profiler = property_get("dalvik.vm.profiler", profiler_prop, "0")
-                    && (profiler_prop[0] == '1');
+    char prop_buf[PROPERTY_VALUE_MAX];
+    bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
@@ -642,9 +645,10 @@
     char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
     char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
     char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
-    char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
-    char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
+    char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
+    char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
+    char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
@@ -652,27 +656,49 @@
     sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
     sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
 
+    bool have_profile_file = false;
+    bool have_top_k_profile_threshold = false;
     if (profiler && (strcmp(pkgname, "*") != 0)) {
         char profile_file[PKG_PATH_MAX];
         snprintf(profile_file, sizeof(profile_file), "%s/%s",
                  DALVIK_CACHE_PREFIX "profiles", pkgname);
         struct stat st;
-        if (stat(profile_file, &st) == -1) {
-            strcpy(profile_file_arg, "--no-profile-file");
-        } else {
+        if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) {
             sprintf(profile_file_arg, "--profile-file=%s", profile_file);
+            have_profile_file = true;
+            if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) {
+                snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg),
+                         "--top-k-profile-threshold=%s", prop_buf);
+                have_top_k_profile_threshold = true;
+            }
         }
-    } else {
-        strcpy(profile_file_arg, "--no-profile-file");
     }
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
-    execl(DEX2OAT_BIN, DEX2OAT_BIN,
-          zip_fd_arg, zip_location_arg,
-          oat_fd_arg, oat_location_arg,
-          profile_file_arg, instruction_set_arg,
-          strlen(dex2oat_flags) > 0 ? dex2oat_flags : NULL,
-          (char*) NULL);
+
+    char* argv[7  // program name, mandatory arguments and the final NULL
+               + (have_profile_file ? 1 : 0)
+               + (have_top_k_profile_threshold ? 1 : 0)
+               + (have_dex2oat_flags ? 1 : 0)];
+    int i = 0;
+    argv[i++] = (char*)DEX2OAT_BIN;
+    argv[i++] = zip_fd_arg;
+    argv[i++] = zip_location_arg;
+    argv[i++] = oat_fd_arg;
+    argv[i++] = oat_location_arg;
+    argv[i++] = instruction_set_arg;
+    if (have_profile_file) {
+        argv[i++] = profile_file_arg;
+    }
+    if (have_top_k_profile_threshold) {
+        argv[i++] = top_k_profile_threshold_arg;
+    }
+    if (have_dex2oat_flags) {
+        argv[i++] = dex2oat_flags;
+    }
+    argv[i] = NULL;
+
+    execv(DEX2OAT_BIN, (char* const *)argv);
     ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
 }
 
@@ -1130,7 +1156,7 @@
         }
     } else {
         if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+            if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
                 rc = -1;
                 goto out;
             }
@@ -1355,3 +1381,30 @@
     free(userdir);
     return ret;
 }
+
+static int prune_dex_exclusion_predicate(const char *file_name, const int is_dir)
+{
+    // Don't exclude any directories, we want to inspect them
+    // recusively for files.
+    if (is_dir) {
+      return 0;
+    }
+
+
+    // Don't exclude regular files that start with the list
+    // of prefixes.
+    static const char data_app_prefix[] = "data@app@";
+    static const char data_priv_app_prefix[] = "data@priv-app@";
+    if (!strncmp(file_name, data_app_prefix, sizeof(data_app_prefix) - 1) ||
+        !strncmp(file_name, data_priv_app_prefix, sizeof(data_priv_app_prefix) - 1)) {
+      return 0;
+    }
+
+    // Exclude all regular files that don't start with the prefix "data@app@" or
+    // "data@priv-app@".
+    return 1;
+}
+
+int prune_dex_cache() {
+  return delete_dir_contents(DALVIK_CACHE_PREFIX, 0, &prune_dex_exclusion_predicate);
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index f714836..4368a9e 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -140,6 +140,12 @@
                              /* pkgName, seinfo, uid*/
 }
 
+static int do_prune_dex_cache(char **arg __attribute__((unused)),
+                              char reply[REPLY_MAX] __attribute__((unused)))
+{
+    return prune_dex_cache();
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -166,6 +172,7 @@
     { "rmuser",               1, do_rm_user },
     { "idmap",                3, do_idmap },
     { "restorecondata",       3, do_restorecon_data },
+    { "prunedexcache",        0, do_prune_dex_cache },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index ff26e49..c1e6e0f 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -159,7 +159,7 @@
 
 int delete_dir_contents(const char *pathname,
                         int also_delete_dir,
-                        const char *ignore);
+                        int (*exclusion_predicate)(const char *name, const int is_dir));
 
 int delete_dir_contents_fd(int dfd, const char *name);
 
@@ -220,3 +220,4 @@
 int linklib(const char* target, const char* source, int userId);
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
 int restorecon_data();
+int prune_dex_cache();
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 420ad5e..35172de 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -219,7 +219,8 @@
     return 0;
 }
 
-static int _delete_dir_contents(DIR *d, const char *ignore)
+static int _delete_dir_contents(DIR *d,
+                                int (*exclusion_predicate)(const char *name, const int is_dir))
 {
     int result = 0;
     struct dirent *de;
@@ -232,8 +233,10 @@
     while ((de = readdir(d))) {
         const char *name = de->d_name;
 
-            /* skip the ignore name if provided */
-        if (ignore && !strcmp(name, ignore)) continue;
+            /* check using the exclusion predicate, if provided */
+        if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
+            continue;
+        }
 
         if (de->d_type == DT_DIR) {
             int r, subfd;
@@ -258,7 +261,7 @@
                 result = -1;
                 continue;
             }
-            if (_delete_dir_contents(subdir, 0)) {
+            if (_delete_dir_contents(subdir, exclusion_predicate)) {
                 result = -1;
             }
             closedir(subdir);
@@ -279,7 +282,7 @@
 
 int delete_dir_contents(const char *pathname,
                         int also_delete_dir,
-                        const char *ignore)
+                        int (*exclusion_predicate)(const char*, const int))
 {
     int res = 0;
     DIR *d;
@@ -289,7 +292,7 @@
         ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
         return -errno;
     }
-    res = _delete_dir_contents(d, ignore);
+    res = _delete_dir_contents(d, exclusion_predicate);
     closedir(d);
     if (also_delete_dir) {
         if (rmdir(pathname)) {
@@ -1036,50 +1039,27 @@
 
 int create_profile_file(const char *pkgname, gid_t gid) {
     const char *profile_dir = DALVIK_CACHE_PREFIX "profiles";
-    struct stat profileStat;
     char profile_file[PKG_PATH_MAX];
 
-    // If we don't have a profile directory under dalvik-cache we need to create one.
-    if (stat(profile_dir, &profileStat) < 0) {
-        // Create the profile directory under dalvik-cache.
-        if (mkdir(profile_dir, 0711) < 0) {
-            ALOGE("cannot make profile dir '%s': %s\n", profile_dir, strerror(errno));
-            return -1;
-        }
-
-        // Make the profile directory write-only for group and other. Owner can rwx it.
-        if (chmod(profile_dir, 0711) < 0) {
-            ALOGE("cannot chown profile dir '%s': %s\n", profile_dir, strerror(errno));
-            rmdir(profile_dir);
-            return -1;
-        }
-
-        if (selinux_android_restorecon(profile_dir, 0) < 0) {
-            ALOGE("cannot restorecon profile dir '%s': %s\n", profile_dir, strerror(errno));
-            rmdir(profile_dir);
-            return -1;
-        }
-    }
-
     snprintf(profile_file, sizeof(profile_file), "%s/%s", profile_dir, pkgname);
 
     // The 'system' user needs to be able to read the profile to determine if dex2oat
     // needs to be run.  This is done in dalvik.system.DexFile.isDexOptNeededInternal().  So
-    // we make it world readable.  Not a problem since the dalvik cache is world
-    // readable anyway.
+    // we assign ownership to AID_SYSTEM and ensure it's not world-readable.
 
-    int fd = open(profile_file, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0664);
+    int fd = open(profile_file, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0660);
 
-    // Open will fail if the file already exists.  We want to ignore that.
+    // Always set the uid/gid/permissions. The file could have been previously created
+    // with different permissions.
     if (fd >= 0) {
-        if (fchown(fd, -1, gid) < 0) {
+        if (fchown(fd, AID_SYSTEM, gid) < 0) {
             ALOGE("cannot chown profile file '%s': %s\n", profile_file, strerror(errno));
             close(fd);
             unlink(profile_file);
             return -1;
         }
 
-        if (fchmod(fd, 0664) < 0) {
+        if (fchmod(fd, 0660) < 0) {
             ALOGE("cannot chmod profile file '%s': %s\n", profile_file, strerror(errno));
             close(fd);
             unlink(profile_file);
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index 4ab8df6..155cfc5 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -18,7 +18,7 @@
 include $(BUILD_EXECUTABLE)
 
 include $(CLEAR_VARS)
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libselinux
 LOCAL_SRC_FILES := service_manager.c binder.c
 LOCAL_CFLAGS += $(svc_c_flags)
 LOCAL_MODULE := servicemanager
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 3200012..0d0ef00 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -8,6 +8,8 @@
 
 #include <private/android_filesystem_config.h>
 
+#include <selinux/android.h>
+
 #include "binder.h"
 
 #if 0
@@ -52,6 +54,8 @@
     { AID_MEDIA, "common_time.config" },
     { AID_KEYSTORE, "android.security.keystore" },
     { AID_RADIO, "telecomm" },
+    { AID_RADIO, "isub" },
+    { AID_RADIO, "ims" },
 };
 
 uint32_t svcmgr_handle;
@@ -80,16 +84,67 @@
     return 1;
 }
 
-int svc_can_register(uid_t uid, const uint16_t *name)
+static struct selabel_handle* sehandle;
+
+static bool check_mac_perms(const char *name, pid_t spid)
+{
+    if (is_selinux_enabled() <= 0) {
+        return true;
+    }
+
+    bool allowed = false;
+
+    const char *class = "service_manager";
+    const char *perm = "add";
+
+    char *tctx = NULL;
+    char *sctx = NULL;
+
+    if (!sehandle) {
+        ALOGE("SELinux: Failed to find sehandle %s.\n", name);
+        return false;
+    }
+
+    if (getpidcon(spid, &sctx) < 0) {
+        ALOGE("SELinux: getpidcon failed to retrieve pid context.\n");
+        return false;
+    }
+
+    if (!sctx) {
+        ALOGE("SELinux: Failed to find sctx for %s.\n", name);
+        return false;
+    }
+
+    if (selabel_lookup(sehandle, &tctx, name, 1) != 0) {
+        ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name);
+        freecon(sctx);
+        return false;
+    }
+
+    if (!tctx) {
+        ALOGE("SELinux: Failed to find tctx for %s.\n", name);
+        freecon(sctx);
+        return false;
+    }
+
+    int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
+    allowed = (result == 0);
+
+    freecon(sctx);
+    freecon(tctx);
+    return allowed;
+}
+
+static int svc_can_register(uid_t uid, const uint16_t *name, pid_t spid)
 {
     size_t n;
 
     if ((uid == 0) || (uid == AID_SYSTEM))
-        return 1;
+        return check_mac_perms(str8(name), spid) ? 1 : 0;
 
     for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
         if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
-            return 1;
+            return check_mac_perms(str8(name), spid) ? 1 : 0;
 
     return 0;
 }
@@ -159,7 +214,8 @@
 
 int do_add_service(struct binder_state *bs,
                    const uint16_t *s, size_t len,
-                   uint32_t handle, uid_t uid, int allow_isolated)
+                   uint32_t handle, uid_t uid, int allow_isolated,
+                   pid_t spid)
 {
     struct svcinfo *si;
 
@@ -169,7 +225,7 @@
     if (!handle || (len == 0) || (len > 127))
         return -1;
 
-    if (!svc_can_register(uid, s)) {
+    if (!svc_can_register(uid, s, spid)) {
         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
              str8(s), handle, uid);
         return -1;
@@ -239,6 +295,14 @@
         return -1;
     }
 
+    if (sehandle && selinux_status_updated() > 0) {
+        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
+        if (tmp_sehandle) {
+            selabel_close(sehandle);
+            sehandle = tmp_sehandle;
+        }
+    }
+
     switch(txn->code) {
     case SVC_MGR_GET_SERVICE:
     case SVC_MGR_CHECK_SERVICE:
@@ -253,7 +317,8 @@
         s = bio_get_string16(msg, &len);
         handle = bio_get_ref(msg);
         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
-        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated))
+        if (do_add_service(bs, s, len, handle, txn->sender_euid,
+            allow_isolated, txn->sender_pid))
             return -1;
         break;
 
@@ -278,6 +343,13 @@
     return 0;
 }
 
+
+static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+{
+    snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
+    return 0;
+}
+
 int main(int argc, char **argv)
 {
     struct binder_state *bs;
@@ -293,6 +365,14 @@
         return -1;
     }
 
+    sehandle = selinux_android_service_context_handle();
+
+    union selinux_callback cb;
+    cb.func_audit = audit_callback;
+    selinux_set_callback(SELINUX_CB_AUDIT, cb);
+    cb.func_log = selinux_log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
     svcmgr_handle = BINDER_SERVICE_MANAGER;
     binder_loop(bs, svcmgr_handler);
 
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 878f8ff..77a5a1c 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -74,6 +74,16 @@
 };
 
 /*
+ * Sensor Reporting Modes.
+ */
+enum {
+    AREPORTING_MODE_CONTINUOUS = 0,
+    AREPORTING_MODE_ON_CHANGE = 1,
+    AREPORTING_MODE_ONE_SHOT = 2,
+    AREPORTING_MODE_SPECIAL_TRIGGER = 3
+};
+
+/*
  * A few useful constants
  */
 
@@ -306,6 +316,11 @@
  */
 const char* ASensor_getStringType(ASensor const* sensor);
 
+/*
+ * Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
+ */
+int ASensor_getReportingMode(ASensor const* sensor);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 548fbf8..2ee99f8 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -97,7 +97,6 @@
     status_t            writeInt64(int64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
-    status_t            writeIntPtr(intptr_t val);
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 1581084..9f1937b 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -104,15 +104,11 @@
     virtual bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& surface) const = 0;
 
-    /* triggers screen off and waits for it to complete
+    /* set display power mode. depending on the mode, it can either trigger
+     * screen on, off or low power mode and wait for it to complete.
      * requires ACCESS_SURFACE_FLINGER permission.
      */
-    virtual void blank(const sp<IBinder>& display) = 0;
-
-    /* triggers screen on and waits for it to complete
-     * requires ACCESS_SURFACE_FLINGER permission.
-     */
-    virtual void unblank(const sp<IBinder>& display) = 0;
+    virtual void setPowerMode(const sp<IBinder>& display, int mode) = 0;
 
     /* returns information for each configuration of the given display
      * intended to be used to get information about built-in displays */
@@ -165,15 +161,14 @@
         GET_BUILT_IN_DISPLAY,
         SET_TRANSACTION_STATE,
         AUTHENTICATE_SURFACE,
-        BLANK,
-        UNBLANK,
         GET_DISPLAY_CONFIGS,
         GET_ACTIVE_CONFIG,
         SET_ACTIVE_CONFIG,
         CONNECT_DISPLAY,
         CAPTURE_SCREEN,
         CLEAR_ANIMATION_FRAME_STATS,
-        GET_ANIMATION_FRAME_STATS
+        GET_ANIMATION_FRAME_STATS,
+        SET_POWER_MODE,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index c1c98b9..28a08e2 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -72,7 +72,9 @@
     const String8& getStringType() const;
     const String8& getRequiredPermission() const;
     int32_t getMaxDelay() const;
+    int32_t getFlags() const;
     bool isWakeUpSensor() const;
+    int32_t getReportingMode() const;
 
     // LightFlattenable protocol
     inline bool isFixedSize() const { return false; }
@@ -96,7 +98,7 @@
     String8 mStringType;
     String8 mRequiredPermission;
     int32_t mMaxDelay;
-    bool    mWakeUpSensor;
+    int32_t mFlags;
     static void flattenString8(void*& buffer, size_t& size, const String8& string8);
     static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
 };
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index e666329..65313df 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -82,11 +82,8 @@
     // returned by getDisplayInfo
     static status_t setActiveConfig(const sp<IBinder>& display, int id);
 
-    /* triggers screen off and waits for it to complete */
-    static void blankDisplay(const sp<IBinder>& display);
-
-    /* triggers screen on and waits for it to complete */
-    static void unblankDisplay(const sp<IBinder>& display);
+    /* Triggers screen on/off or low power mode and waits for it to complete */
+    static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
 
     // ------------------------------------------------------------------------
     // surface creation / destruction
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index 3b5cd6d..799944f 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <utils/Timers.h>
 
 #include <ui/PixelFormat.h>
 
@@ -33,6 +34,8 @@
     float density;
     uint8_t orientation;
     bool secure;
+    nsecs_t appVsyncOffset;
+    nsecs_t presentationDeadline;
 };
 
 /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index f0d8732..76504ce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -679,11 +679,6 @@
 
 #endif
 
-status_t Parcel::writeIntPtr(intptr_t val)
-{
-    return writeAligned(val);
-}
-
 status_t Parcel::writeCString(const char* str)
 {
     return write(str, strlen(str)+1);
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 85a7de7..0282834 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -145,7 +145,7 @@
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize),
-            "BitTube::sendObjects(count=%d, size=%d), res=%d (partial events were sent!)",
+            "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
             count, objSize, size);
 
     //ALOGE_IF(size<0, "error %d sending %d events", size, count);
@@ -160,7 +160,7 @@
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize),
-            "BitTube::recvObjects(count=%d, size=%d), res=%d (partial events were received!)",
+            "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
             count, objSize, size);
 
     //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index f1b8fa8..f19b6c7 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #define LOG_TAG "ConsumerBase"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
@@ -191,7 +193,7 @@
     mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
     mSlots[item->mBuf].mFence = item->mFence;
 
-    CB_LOGV("acquireBufferLocked: -> slot=%d/%llu",
+    CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
             item->mBuf, item->mFrameNumber);
 
     return OK;
@@ -242,7 +244,7 @@
         return OK;
     }
 
-    CB_LOGV("releaseBufferLocked: slot=%d/%llu",
+    CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
             slot, mSlots[slot].mFrameNumber);
     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
             display, eglFence, mSlots[slot].mFence);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index c6c88a9..4680168 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -205,20 +205,13 @@
         return reply.readStrongBinder();
     }
 
-    virtual void blank(const sp<IBinder>& display)
+    virtual void setPowerMode(const sp<IBinder>& display, int mode)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::BLANK, data, &reply);
-    }
-
-    virtual void unblank(const sp<IBinder>& display)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
+        data.writeInt32(mode);
+        remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply);
     }
 
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
@@ -378,18 +371,6 @@
             reply->writeStrongBinder(display);
             return NO_ERROR;
         }
-        case BLANK: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            blank(display);
-            return NO_ERROR;
-        }
-        case UNBLANK: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            unblank(display);
-            return NO_ERROR;
-        }
         case GET_DISPLAY_CONFIGS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             Vector<DisplayInfo> configs;
@@ -434,6 +415,13 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case SET_POWER_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = data.readStrongBinder();
+            int32_t mode = data.readInt32();
+            setPowerMode(display, mode);
+            return NO_ERROR;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index f161aeb..1c0f303 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -36,7 +36,7 @@
     : mHandle(0), mType(0),
       mMinValue(0), mMaxValue(0), mResolution(0),
       mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0),
-      mMaxDelay(0), mWakeUpSensor(false)
+      mMaxDelay(0), mFlags(0)
 {
 }
 
@@ -52,7 +52,7 @@
     mResolution = hwSensor->resolution;
     mPower = hwSensor->power;
     mMinDelay = hwSensor->minDelay;
-    mWakeUpSensor = false;
+    mFlags = 0;
 
     // Set fifo event count zero for older devices which do not support batching. Fused
     // sensors also have their fifo counts set to zero.
@@ -79,154 +79,177 @@
         mMaxDelay = 0;
     }
 
-    // Ensure existing sensors have correct string type and required
-    // permissions.
+    // Ensure existing sensors have correct string type, required permissions and reporting mode.
     switch (mType) {
     case SENSOR_TYPE_ACCELEROMETER:
         mStringType = SENSOR_STRING_TYPE_ACCELEROMETER;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_AMBIENT_TEMPERATURE:
         mStringType = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_GAME_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_GRAVITY:
         mStringType = SENSOR_STRING_TYPE_GRAVITY;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_GYROSCOPE:
         mStringType = SENSOR_STRING_TYPE_GYROSCOPE;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
         mStringType = SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_HEART_RATE:
         mStringType = SENSOR_STRING_TYPE_HEART_RATE;
         mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_LIGHT:
         mStringType = SENSOR_STRING_TYPE_LIGHT;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_LINEAR_ACCELERATION:
         mStringType = SENSOR_STRING_TYPE_LINEAR_ACCELERATION;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_MAGNETIC_FIELD:
         mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
         mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_ORIENTATION:
         mStringType = SENSOR_STRING_TYPE_ORIENTATION;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_PRESSURE:
         mStringType = SENSOR_STRING_TYPE_PRESSURE;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_PROXIMITY:
         mStringType = SENSOR_STRING_TYPE_PROXIMITY;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_RELATIVE_HUMIDITY:
         mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_ROTATION_VECTOR;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
         break;
     case SENSOR_TYPE_SIGNIFICANT_MOTION:
         mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_STEP_COUNTER:
         mStringType = SENSOR_STRING_TYPE_STEP_COUNTER;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_STEP_DETECTOR:
         mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR;
+        mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
         break;
     case SENSOR_TYPE_TEMPERATURE:
         mStringType = SENSOR_STRING_TYPE_TEMPERATURE;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR:
         mStringType = SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
         break;
     case SENSOR_TYPE_WAKE_UP_ACCELEROMETER:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_ORIENTATION:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_GYROSCOPE:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_LIGHT:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_LIGHT;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_PRESSURE:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_PRESSURE;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_GRAVITY:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_GRAVITY;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_STEP_DETECTOR:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_STEP_COUNTER:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_UP_HEART_RATE:
         mStringType = SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE;
         mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP);
+        break;
+    case SENSOR_TYPE_WAKE_UP_TILT_DETECTOR:
+        mStringType = SENSOR_STRING_TYPE_WAKE_UP_TILT_DETECTOR;
+        mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     case SENSOR_TYPE_WAKE_GESTURE:
         mStringType = SENSOR_STRING_TYPE_WAKE_GESTURE;
-        mWakeUpSensor = true;
+        mFlags |= (SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP);
         break;
     default:
         // Only pipe the stringType, requiredPermission and flags for custom sensors.
@@ -236,8 +259,19 @@
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) {
             mRequiredPermission = hwSensor->requiredPermission;
         }
+
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-            mWakeUpSensor = hwSensor->flags & SENSOR_FLAG_WAKE_UP;
+            mFlags = (int32_t) hwSensor->flags;
+        } else {
+            // This is an OEM defined sensor on an older HAL. Use minDelay to determine the
+            // reporting mode of the sensor.
+            if (mMinDelay > 0) {
+                mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+            } else if (mMinDelay == 0) {
+                mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+            } else if (mMinDelay < 0) {
+                mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+            }
         }
         break;
     }
@@ -311,8 +345,16 @@
     return mMaxDelay;
 }
 
+int32_t Sensor::getFlags() const {
+    return mFlags;
+}
+
 bool Sensor::isWakeUpSensor() const {
-    return mWakeUpSensor;
+    return mFlags & SENSOR_FLAG_WAKE_UP;
+}
+
+int32_t Sensor::getReportingMode() const {
+    return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
 }
 
 size_t Sensor::getFlattenedSize() const
@@ -320,8 +362,7 @@
     size_t fixedSize =
             sizeof(int32_t) * 3 +
             sizeof(float) * 4 +
-            sizeof(int32_t) * 4 +
-            sizeof(bool) * 1;
+            sizeof(int32_t) * 5;
 
     size_t variableSize =
             sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) +
@@ -352,7 +393,7 @@
     flattenString8(buffer, size, mStringType);
     flattenString8(buffer, size, mRequiredPermission);
     FlattenableUtils::write(buffer, size, mMaxDelay);
-    FlattenableUtils::write(buffer, size, mWakeUpSensor);
+    FlattenableUtils::write(buffer, size, mFlags);
     return NO_ERROR;
 }
 
@@ -367,8 +408,7 @@
     size_t fixedSize =
             sizeof(int32_t) * 3 +
             sizeof(float) * 4 +
-            sizeof(int32_t) * 4 +
-            sizeof(bool) * 1;
+            sizeof(int32_t) * 5;
     if (size < fixedSize) {
         return NO_MEMORY;
     }
@@ -391,7 +431,7 @@
         return NO_MEMORY;
     }
     FlattenableUtils::read(buffer, size, mMaxDelay);
-    FlattenableUtils::read(buffer, size, mWakeUpSensor);
+    FlattenableUtils::read(buffer, size, mFlags);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index eedeca1..3bee3fc 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -655,12 +655,9 @@
     return ComposerService::getComposerService()->setActiveConfig(display, id);
 }
 
-void SurfaceComposerClient::blankDisplay(const sp<IBinder>& token) {
-    ComposerService::getComposerService()->blank(token);
-}
-
-void SurfaceComposerClient::unblankDisplay(const sp<IBinder>& token) {
-    ComposerService::getComposerService()->unblank(token);
+void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
+        int mode) {
+    ComposerService::getComposerService()->setPowerMode(token, mode);
 }
 
 status_t SurfaceComposerClient::clearAnimationFrameStats() {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 21fd443..090ee53 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -301,7 +301,7 @@
             "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
             "xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
-            "pointerCount=%d",
+            "pointerCount=%" PRIu32,
             mChannel->getName().string(), seq,
             deviceId, source, action, flags, edgeFlags, metaState, buttonState,
             xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
@@ -313,7 +313,7 @@
     }
 
     if (pointerCount > MAX_POINTERS || pointerCount < 1) {
-        ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %"PRIu32".",
+        ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".",
                 mChannel->getName().string(), pointerCount);
         return BAD_VALUE;
     }
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 2fdfcf8..86e1d46 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -57,7 +57,6 @@
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 LOCAL_MODULE:= hwcStress
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
 
 LOCAL_MODULE_TAGS := tests
 
@@ -88,7 +87,6 @@
 	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcRects
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
 
 LOCAL_MODULE_TAGS := tests
 
@@ -119,7 +117,6 @@
 	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcColorEquiv
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
 
 LOCAL_MODULE_TAGS := tests
 
@@ -150,7 +147,6 @@
 	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcCommit
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index ac73c1f..f274631 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -14,6 +14,24 @@
  * limitations under the License.
  */
 
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <memory.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/limits.h>
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+#include <sys/sha1.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
 #define LOG_TAG "EventHub"
 
 // #define LOG_NDEBUG 0
@@ -28,29 +46,10 @@
 #include <utils/threads.h>
 #include <utils/Errors.h>
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
 #include <input/KeyLayoutMap.h>
 #include <input/KeyCharacterMap.h>
 #include <input/VirtualKeyMap.h>
 
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-
-#include <sys/inotify.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/limits.h>
-#include <sys/sha1.h>
-#include <sys/utsname.h>
-
 /* this macro is used to tell if "bit" is set in "array"
  * it selects a byte from the array, and does a boolean AND
  * operation with a byte that only has the relevant bit set.
@@ -812,8 +811,8 @@
                         sizeof(struct input_event) * capacity);
                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                     // Device was removed before INotify noticed.
-                    ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
-                            "capacity: %zu errno: %d)\n",
+                    ALOGW("could not get event, removed? (fd: %d size: %" PRId32
+                            " bufferSize: %zu capacity: %zu errno: %d)\n",
                             device->fd, readSize, bufferSize, capacity, errno);
                     deviceChanged = true;
                     closeDeviceLocked(device);
@@ -873,7 +872,7 @@
                         // system call that also queries ktime_get_ts().
                         event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
                                 + nsecs_t(iev.time.tv_usec) * 1000LL;
-                        ALOGV("event time %lld, now %lld", event->when, now);
+                        ALOGV("event time %" PRId64 ", now %" PRId64, event->when, now);
 
                         // Bug 7291243: Add a guard in case the kernel generates timestamps
                         // that appear to be far into the future because they were generated
@@ -897,14 +896,16 @@
                                 ALOGW("An input event from %s has a timestamp that appears to "
                                         "have been generated using the wrong clock source "
                                         "(expected CLOCK_MONOTONIC): "
-                                        "event time %lld, current time %lld, call time %lld.  "
+                                        "event time %" PRId64 ", current time %" PRId64
+                                        ", call time %" PRId64 ".  "
                                         "Using current time instead.",
                                         device->path.string(), event->when, time, now);
                                 event->when = time;
                             } else {
                                 ALOGV("Event time is ok but failed the fast path and required "
                                         "an extra call to systemTime: "
-                                        "event time %lld, current time %lld, call time %lld.",
+                                        "event time %" PRId64 ", current time %" PRId64
+                                        ", call time %" PRId64 ".",
                                         event->when, time, now);
                             }
                         }
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 01dbdfb..3934509 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
+#include <inttypes.h>
 #include <math.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Atomic.h>
@@ -134,11 +135,11 @@
     Info& info( mActivationCount.editValueFor(handle) );
 
     ALOGD_IF(DEBUG_CONNECTIONS,
-             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
+             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
              ident, handle, enabled, info.batchParams.size());
 
     if (enabled) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%d", info.batchParams.indexOfKey(ident));
+        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
 
         if (info.batchParams.indexOfKey(ident) >= 0) {
           if (info.batchParams.size() == 1) {
@@ -150,7 +151,7 @@
             ALOGE("\t >>>ERROR: activate called without batch");
         }
     } else {
-        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%d", info.batchParams.indexOfKey(ident));
+        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
 
         if (info.removeBatchParamsForIdent(ident) >= 0) {
             if (info.batchParams.size() == 0) {
@@ -163,7 +164,7 @@
                     // batch_rate and timeout. One of the apps has unregistered for sensor
                     // events, and the best effort batch parameters might have changed.
                     ALOGD_IF(DEBUG_CONNECTIONS,
-                             "\t>>> actuating h/w batch %d %d %lld %lld ", handle,
+                             "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
                              info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                              info.bestBatchParams.batchTimeout);
                     mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags,
@@ -191,7 +192,7 @@
 
     // On older devices which do not support batch, call setDelay().
     if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %lld ", handle,
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
                  info.bestBatchParams.batchDelay);
         mSensorDevice->setDelay(
                 reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
@@ -231,7 +232,7 @@
     }
 
     ALOGD_IF(DEBUG_CONNECTIONS,
-             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%lld timeout=%lld",
+             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
              ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
 
     Mutex::Autolock _l(mLock);
@@ -250,7 +251,8 @@
     info.selectBatchParams();
 
     ALOGD_IF(DEBUG_CONNECTIONS,
-             "\t>>> curr_period=%lld min_period=%lld curr_timeout=%lld min_timeout=%lld",
+             "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
+             " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
              prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
              prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
 
@@ -258,7 +260,7 @@
     // If the min period or min timeout has changed since the last batch call, call batch.
     if (prevBestBatchParams != info.bestBatchParams) {
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %lld %lld ", handle,
+            ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
                      info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                      info.bestBatchParams.batchTimeout);
             err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
@@ -270,7 +272,8 @@
             // call setDelay in SensorDevice::activate() method.
         }
         if (err != NO_ERROR) {
-            ALOGE("sensor batch failed %p %d %d %lld %lld err=%s", mSensorDevice, handle,
+            ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
+                  mSensorDevice, handle,
                   info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                   info.bestBatchParams.batchTimeout, strerror(-err));
             info.removeBatchParamsForIdent(ident);
@@ -324,7 +327,7 @@
                                                     int64_t maxBatchReportLatencyNs) {
     ssize_t index = batchParams.indexOfKey(ident);
     if (index < 0) {
-        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%lld timeout=%lld) failed (%s)",
+        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
               ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
         return BAD_INDEX;
     }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 1bee04f..f5dba38 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -223,14 +223,23 @@
                     s.getHandle(),
                     s.getRequiredPermission().string());
 
-            if (s.getMinDelay() > 0) {
-                result.appendFormat(
-                        "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay());
+            const int reportingMode = s.getReportingMode();
+            if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+                result.append("continuous      |");
+            } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+                result.append("on-change       | ");
+            } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+                result.append("one-shot        | ");
             } else {
-                result.append(s.getMinDelay() == 0
-                        ? "on-demand         | "
-                        : "one-shot          | ");
+                result.append("special-trigger | ");
             }
+
+            if (s.getMinDelay() > 0) {
+                result.appendFormat("maxRate=%7.2fHz | ", 1e6f / s.getMinDelay());
+            } else {
+                result.appendFormat("minDelay=%5dus |", s.getMinDelay());
+            }
+
             if (s.getFifoMaxEventCount() > 0) {
                 result.appendFormat("FifoMax=%d events | ",
                         s.getFifoMaxEventCount());
@@ -301,17 +310,15 @@
 
 void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
         sensors_event_t const* buffer, const int count) {
-    SensorInterface* sensor;
-    status_t err = NO_ERROR;
     for (int i=0 ; i<count ; i++) {
         int handle = buffer[i].sensor;
-        int type = buffer[i].type;
-        if (type == SENSOR_TYPE_SIGNIFICANT_MOTION) {
-            if (connection->hasSensor(handle)) {
-                sensor = mSensorMap.valueFor(handle);
-                if (sensor != NULL) {
-                    sensor->autoDisable(connection.get(), handle);
-                }
+        if (connection->hasSensor(handle)) {
+            SensorInterface* sensor = mSensorMap.valueFor(handle);
+            // If this buffer has an event from a one_shot sensor and this connection is registered
+            // for this particular one_shot sensor, try cleaning up the connection.
+            if (sensor != NULL &&
+                sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+                sensor->autoDisable(connection.get(), handle);
                 cleanupWithoutDisableLocked(connection, handle);
             }
         }
@@ -378,7 +385,7 @@
                     for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
                         if (count + k >= minBufferSize) {
                             ALOGE("buffer too small to hold all events: "
-                                    "count=%u, k=%u, size=%u",
+                                    "count=%zd, k=%zu, size=%zu",
                                     count, k, minBufferSize);
                             break;
                         }
@@ -522,11 +529,11 @@
     Mutex::Autolock _l(mLock);
     const wp<SensorEventConnection> connection(c);
     size_t size = mActiveSensors.size();
-    ALOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size);
+    ALOGD_IF(DEBUG_CONNECTIONS, "%zu active sensors", size);
     for (size_t i=0 ; i<size ; ) {
         int handle = mActiveSensors.keyAt(i);
         if (c->hasSensor(handle)) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle);
+            ALOGD_IF(DEBUG_CONNECTIONS, "%zu: disabling handle=0x%08x", i, handle);
             SensorInterface* sensor = mSensorMap.valueFor( handle );
             ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
             if (sensor) {
@@ -534,9 +541,9 @@
             }
         }
         SensorRecord* rec = mActiveSensors.valueAt(i);
-        ALOGE_IF(!rec, "mActiveSensors[%d] is null (handle=0x%08x)!", i, handle);
+        ALOGE_IF(!rec, "mActiveSensors[%zu] is null (handle=0x%08x)!", i, handle);
         ALOGD_IF(DEBUG_CONNECTIONS,
-                "removing connection %p for sensor[%d].handle=0x%08x",
+                "removing connection %p for sensor[%zu].handle=0x%08x",
                 c, i, handle);
 
         if (rec && rec->removeConnection(connection)) {
@@ -588,7 +595,7 @@
             // this sensor is already activated, but we are adding a connection that uses it.
             // Immediately send down the last known value of the requested sensor if it's not a
             // "continuous" sensor.
-            if (sensor->getSensor().getMinDelay() == 0) {
+            if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
                 // NOTE: The wake_up flag of this event may get set to
                 // WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
                 sensors_event_t& event(mLastEventSeen.editValueFor(handle));
@@ -625,7 +632,7 @@
         samplingPeriodNs = minDelayNs;
     }
 
-    ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%lld timeout== %lld",
+    ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%" PRId64 " timeout== %" PRId64,
              handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
 
     status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
@@ -732,8 +739,8 @@
         return BAD_VALUE;
     }
 
-    if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) {
-        ALOGE("flush called on Significant Motion sensor");
+    if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+        ALOGE("flush called on a one-shot sensor");
         return INVALID_OPERATION;
     }
     return sensor->flush(connection.get(), handle);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 0834c80..56c539f 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -37,9 +37,6 @@
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
-ifeq ($(TARGET_BOARD_PLATFORM),omap3)
-	LOCAL_CFLAGS += -DNO_RGBX_8888
-endif
 ifeq ($(TARGET_BOARD_PLATFORM),omap4)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
 endif
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index d771e2c..12da9a5 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -37,34 +37,23 @@
 
 // Setting this to true enables verbose tracing that can be used to debug
 // vsync event model or phase issues.
-static const bool traceDetailedInfo = false;
+static const bool kTraceDetailedInfo = false;
 
 // This is the threshold used to determine when hardware vsync events are
 // needed to re-synchronize the software vsync model with the hardware.  The
 // error metric used is the mean of the squared difference between each
 // present time and the nearest software-predicted vsync.
-static const nsecs_t errorThreshold = 160000000000;
-
-// This works around the lack of support for the sync framework on some
-// devices.
-#ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK
-static const bool runningWithoutSyncFramework = true;
-#else
-static const bool runningWithoutSyncFramework = false;
-#endif
+static const nsecs_t kErrorThreshold = 160000000000;    // 400 usec squared
 
 // This is the offset from the present fence timestamps to the corresponding
 // vsync event.
-static const int64_t presentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
+static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
 
 class DispSyncThread: public Thread {
 public:
 
     DispSyncThread():
-            mLowPowerMode(false),
             mStop(false),
-            mLastVsyncSent(false),
-            mLastBufferFull(false),
             mPeriod(0),
             mPhase(0),
             mWakeupLatency(0) {
@@ -138,7 +127,7 @@
                         // Don't correct by more than 500 us
                         mWakeupLatency = 500000;
                     }
-                    if (traceDetailedInfo) {
+                    if (kTraceDetailedInfo) {
                         ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
                         ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
                     }
@@ -148,18 +137,7 @@
             }
 
             if (callbackInvocations.size() > 0) {
-                if (mLowPowerMode) {
-                    if (!mLastVsyncSent || !mLastBufferFull) {
-                        fireCallbackInvocations(callbackInvocations);
-                        mLastVsyncSent = true;
-                    } else
-                        mLastVsyncSent = false;
-                } else {
-                    fireCallbackInvocations(callbackInvocations);
-                }
-                mLastBufferFull = true;
-            } else {
-                mLastBufferFull = false;
+                fireCallbackInvocations(callbackInvocations);
             }
         }
 
@@ -207,14 +185,12 @@
         return BAD_VALUE;
     }
 
-    // This method is only here to handle the runningWithoutSyncFramework
-    // case.
+    // This method is only here to handle the kIgnorePresentFences case.
     bool hasAnyEventListeners() {
         Mutex::Autolock lock(mMutex);
         return !mEventListeners.empty();
     }
 
-    bool mLowPowerMode;
 private:
 
     struct EventListener {
@@ -287,8 +263,6 @@
     }
 
     bool mStop;
-    bool mLastVsyncSent;
-    bool mLastBufferFull;
 
     nsecs_t mPeriod;
     nsecs_t mPhase;
@@ -313,19 +287,22 @@
     bool mParity;
 };
 
-DispSync::DispSync() {
-    mThread = new DispSyncThread();
+DispSync::DispSync() :
+        mRefreshSkipCount(0),
+        mThread(new DispSyncThread()) {
+
     mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
 
     reset();
     beginResync();
 
-    if (traceDetailedInfo) {
-        // If runningWithoutSyncFramework is true then the ZeroPhaseTracer
+    if (kTraceDetailedInfo) {
+        // If we're not getting present fences then the ZeroPhaseTracer
         // would prevent HW vsync event from ever being turned off.
-        // Furthermore the zero-phase tracing is not needed because any time
-        // there is an event registered we will turn on the HW vsync events.
-        if (!runningWithoutSyncFramework) {
+        // Even if we're just ignoring the fences, the zero-phase tracing is
+        // not needed because any time there is an event registered we will
+        // turn on the HW vsync events.
+        if (!kIgnorePresentFences) {
             addEventListener(0, new ZeroPhaseTracer());
         }
     }
@@ -356,14 +333,14 @@
             nsecs_t t = f->getSignalTime();
             if (t < INT64_MAX) {
                 mPresentFences[i].clear();
-                mPresentTimes[i] = t + presentTimeOffset;
+                mPresentTimes[i] = t + kPresentTimeOffset;
             }
         }
     }
 
     updateErrorLocked();
 
-    return mPeriod == 0 || mError > errorThreshold;
+    return mPeriod == 0 || mError > kErrorThreshold;
 }
 
 void DispSync::beginResync() {
@@ -390,7 +367,7 @@
         resetErrorLocked();
     }
 
-    if (runningWithoutSyncFramework) {
+    if (kIgnorePresentFences) {
         // If we don't have the sync framework we will never have
         // addPresentFence called.  This means we have no way to know whether
         // or not we're synchronized with the HW vsyncs, so we just request
@@ -399,7 +376,7 @@
         return mThread->hasAnyEventListeners();
     }
 
-    return mPeriod == 0 || mError > errorThreshold;
+    return mPeriod == 0 || mError > kErrorThreshold;
 }
 
 void DispSync::endResync() {
@@ -412,8 +389,11 @@
     return mThread->addEventListener(phase, callback);
 }
 
-void DispSync::setLowPowerMode(bool enabled) {
-    mThread->mLowPowerMode = enabled;
+void DispSync::setRefreshSkipCount(int count) {
+    Mutex::Autolock lock(mMutex);
+    ALOGD("setRefreshSkipCount(%d)", count);
+    mRefreshSkipCount = count;
+    updateModelLocked();
 }
 
 status_t DispSync::removeEventListener(const sp<Callback>& callback) {
@@ -459,11 +439,14 @@
             mPhase += mPeriod;
         }
 
-        if (traceDetailedInfo) {
+        if (kTraceDetailedInfo) {
             ATRACE_INT64("DispSync:Period", mPeriod);
             ATRACE_INT64("DispSync:Phase", mPhase);
         }
 
+        // Artificially inflate the period if requested.
+        mPeriod += mPeriod * mRefreshSkipCount;
+
         mThread->updateModel(mPeriod, mPhase);
     }
 }
@@ -473,15 +456,19 @@
         return;
     }
 
+    // Need to compare present fences against the un-adjusted refresh period,
+    // since they might arrive between two events.
+    nsecs_t period = mPeriod / (1 + mRefreshSkipCount);
+
     int numErrSamples = 0;
     nsecs_t sqErrSum = 0;
 
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
         nsecs_t sample = mPresentTimes[i];
         if (sample > mPhase) {
-            nsecs_t sampleErr = (sample - mPhase) % mPeriod;
-            if (sampleErr > mPeriod / 2) {
-                sampleErr -= mPeriod;
+            nsecs_t sampleErr = (sample - mPhase) % period;
+            if (sampleErr > period / 2) {
+                sampleErr -= period;
             }
             sqErrSum += sampleErr * sampleErr;
             numErrSamples++;
@@ -494,7 +481,7 @@
         mError = 0;
     }
 
-    if (traceDetailedInfo) {
+    if (kTraceDetailedInfo) {
         ATRACE_INT64("DispSync:Error", mError);
     }
 }
@@ -516,13 +503,16 @@
 
 void DispSync::dump(String8& result) const {
     Mutex::Autolock lock(mMutex);
-    result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod);
-    result.appendFormat("mPhase: %"PRId64" ns\n", mPhase);
-    result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n",
+    result.appendFormat("present fences are %s\n",
+            kIgnorePresentFences ? "ignored" : "used");
+    result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
+            mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
+    result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
+    result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n",
             mError, sqrt(mError));
-    result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n",
+    result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n",
             mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
-    result.appendFormat("mNumResyncSamples: %d (max %d)\n",
+    result.appendFormat("mNumResyncSamples: %zd (max %d)\n",
             mNumResyncSamples, MAX_RESYNC_SAMPLES);
 
     result.appendFormat("mResyncSamples:\n");
@@ -531,9 +521,9 @@
         size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
         nsecs_t sampleTime = mResyncSamples[idx];
         if (i == 0) {
-            result.appendFormat("  %"PRId64"\n", sampleTime);
+            result.appendFormat("  %" PRId64 "\n", sampleTime);
         } else {
-            result.appendFormat("  %"PRId64" (+%"PRId64")\n",
+            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n",
                     sampleTime, sampleTime - previous);
         }
         previous = sampleTime;
@@ -541,6 +531,7 @@
 
     result.appendFormat("mPresentFences / mPresentTimes [%d]:\n",
             NUM_PRESENT_SAMPLES);
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     previous = 0;
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
         size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
@@ -548,15 +539,21 @@
         nsecs_t presentTime = mPresentTimes[idx];
         if (!signaled) {
             result.appendFormat("  [unsignaled fence]\n");
+        } else if (presentTime == 0) {
+            result.appendFormat("  0\n");
         } else if (previous == 0) {
-            result.appendFormat("  %"PRId64"\n", presentTime);
+            result.appendFormat("  %" PRId64 "  (%.3f ms ago)\n", presentTime,
+                    (now - presentTime) / 1000000.0);
         } else {
-            result.appendFormat("  %"PRId64" (+%"PRId64" / %.3f)\n",
+            result.appendFormat("  %" PRId64 " (+%" PRId64 " / %.3f)  (%.3f ms ago)\n",
                     presentTime, presentTime - previous,
-                    (presentTime - previous) / (double) mPeriod);
+                    (presentTime - previous) / (double) mPeriod,
+                    (now - presentTime) / 1000000.0);
         }
         previous = presentTime;
     }
+
+    result.appendFormat("current monotonic time: %" PRId64 "\n", now);
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a33ce5d..7a26df3 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -25,6 +25,18 @@
 
 namespace android {
 
+// Ignore present (retire) fences if the device doesn't have support for the
+// sync framework, or if all phase offsets are zero.  The latter is useful
+// because it allows us to avoid resync bursts on devices that don't need
+// phase-offset VSYNC events.
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
+        (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+static const bool kIgnorePresentFences = true;
+#else
+static const bool kIgnorePresentFences = false;
+#endif
+
+
 class String8;
 class Fence;
 class DispSyncThread;
@@ -55,6 +67,7 @@
     DispSync();
     ~DispSync();
 
+    // reset clears the resync samples and error value.
     void reset();
 
     // addPresentFence adds a fence for use in validating the current vsync
@@ -88,8 +101,11 @@
     // turned on.  It should NOT be used after that.
     void setPeriod(nsecs_t period);
 
-    // Setting the low power mode reduces the frame rate to half of the default
-    void setLowPowerMode(bool enabled);
+    // setRefreshSkipCount specifies an additional number of refresh
+    // cycles to skip.  For example, on a 60Hz display, a skip count of 1
+    // will result in events happening at 30Hz.  Default is zero.  The idea
+    // is to sacrifice smoothness for battery life.
+    void setRefreshSkipCount(int count);
 
     // addEventListener registers a callback to be called repeatedly at the
     // given phase offset from the hardware vsync events.  The callback is
@@ -149,6 +165,8 @@
     nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES];
     size_t mPresentSampleOffset;
 
+    int mRefreshSkipCount;
+
     // mThread is the thread from which all the callbacks are called.
     sp<DispSyncThread> mThread;
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4ebe291..71377ed 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,9 +70,9 @@
       mPageFlipCount(),
       mIsSecure(isSecure),
       mSecureLayerVisible(false),
-      mScreenAcquired(false),
       mLayerStack(NO_LAYER_STACK),
-      mOrientation()
+      mOrientation(),
+      mPowerMode(HWC_POWER_MODE_OFF)
 {
     mNativeWindow = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
@@ -109,7 +109,8 @@
     mFrame.makeInvalid();
 
     // virtual displays are always considered enabled
-    mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
+    mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
+                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
 
     // Name the display.  The name will be replaced shortly if the display
     // was created with createDisplay().
@@ -322,21 +323,16 @@
 }
 
 // ----------------------------------------------------------------------------
-
-bool DisplayDevice::canDraw() const {
-    return mScreenAcquired;
+void DisplayDevice::setPowerMode(int mode) {
+    mPowerMode = mode;
 }
 
-void DisplayDevice::releaseScreen() const {
-    mScreenAcquired = false;
+int DisplayDevice::getPowerMode()  const {
+    return mPowerMode;
 }
 
-void DisplayDevice::acquireScreen() const {
-    mScreenAcquired = true;
-}
-
-bool DisplayDevice::isScreenAcquired() const {
-    return mScreenAcquired;
+bool DisplayDevice::isDisplayOn() const {
+    return (mPowerMode != HWC_POWER_MODE_OFF);
 }
 
 // ----------------------------------------------------------------------------
@@ -465,13 +461,13 @@
     result.appendFormat(
         "+ DisplayDevice: %s\n"
         "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
-        "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%zu\n"
+        "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, numLayers=%zu\n"
         "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
         mDisplayName.string(), mType, mHwcDisplayId,
         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
         mOrientation, tr.getType(), getPageFlipCount(),
-        mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
+        mIsSecure, mSecureLayerVisible, mPowerMode, mVisibleLayersSortedByZ.size(),
         mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
         mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
         mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index f750c6c..4c8ef02 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -147,12 +147,11 @@
     void setViewportAndProjection() const;
 
     /* ------------------------------------------------------------------------
-     * blank / unblank management
+     * Display power mode management.
      */
-    void releaseScreen() const;
-    void acquireScreen() const;
-    bool isScreenAcquired() const;
-    bool canDraw() const;
+    int getPowerMode() const;
+    void setPowerMode(int mode);
+    bool isDisplayOn() const;
 
     // release HWC resources (if any) for removable displays
     void disconnect(HWComposer& hwc);
@@ -197,9 +196,6 @@
     // Whether we have a visible secure layer on this display
     bool mSecureLayerVisible;
 
-    // Whether the screen is blanked;
-    mutable int mScreenAcquired;
-
 
     /*
      * Transaction state
@@ -217,6 +213,8 @@
     Rect mScissor;
     Transform mGlobalTransform;
     bool mNeedsFiltering;
+    // Current power mode
+    int mPowerMode;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c3b2159..185dab2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -759,19 +759,18 @@
     return (status_t)err;
 }
 
-status_t HWComposer::release(int disp) {
+status_t HWComposer::setPowerMode(int disp, int mode) {
     LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
     if (mHwc) {
-        eventControl(disp, HWC_EVENT_VSYNC, 0);
-        return (status_t)mHwc->blank(mHwc, disp, 1);
-    }
-    return NO_ERROR;
-}
-
-status_t HWComposer::acquire(int disp) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    if (mHwc) {
-        return (status_t)mHwc->blank(mHwc, disp, 0);
+        if (mode == HWC_POWER_MODE_OFF) {
+            eventControl(disp, HWC_EVENT_VSYNC, 0);
+        }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+        } else {
+            return (status_t)mHwc->blank(mHwc, disp,
+                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
+        }
     }
     return NO_ERROR;
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 2f92672..c62b924 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -97,11 +97,8 @@
     // commits the list
     status_t commit();
 
-    // release hardware resources and blank screen
-    status_t release(int disp);
-
-    // acquire hardware resources and unblank screen
-    status_t acquire(int disp);
+    // set power mode
+    status_t setPowerMode(int disp, int mode);
 
     // reset state when an external, non-virtual display is disconnected
     void disconnectDisplay(int disp);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cd5fe6b..4238ef8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -88,14 +88,6 @@
 
 namespace android {
 
-// This works around the lack of support for the sync framework on some
-// devices.
-#ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK
-static const bool runningWithoutSyncFramework = true;
-#else
-static const bool runningWithoutSyncFramework = false;
-#endif
-
 // This is the phase offset in nanoseconds of the software vsync event
 // relative to the vsync event reported by HWComposer.  The software vsync
 // event is when SurfaceFlinger and Choreographer-based applications run each
@@ -322,10 +314,13 @@
 
 class DispSyncSource : public VSyncSource, private DispSync::Callback {
 public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) :
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+        const char* label) :
             mValue(0),
             mPhaseOffset(phaseOffset),
             mTraceVsync(traceVsync),
+            mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
+            mVsyncEventLabel(String8::format("VSYNC-%s", label)),
             mDispSync(dispSync) {}
 
     virtual ~DispSyncSource() {}
@@ -340,7 +335,7 @@
                 ALOGE("error registering vsync callback: %s (%d)",
                         strerror(-err), err);
             }
-            ATRACE_INT("VsyncOn", 1);
+            //ATRACE_INT(mVsyncOnLabel.string(), 1);
         } else {
             status_t err = mDispSync->removeEventListener(
                     static_cast<DispSync::Callback*>(this));
@@ -348,7 +343,7 @@
                 ALOGE("error unregistering vsync callback: %s (%d)",
                         strerror(-err), err);
             }
-            ATRACE_INT("VsyncOn", 0);
+            //ATRACE_INT(mVsyncOnLabel.string(), 0);
         }
     }
 
@@ -366,7 +361,7 @@
 
             if (mTraceVsync) {
                 mValue = (mValue + 1) % 2;
-                ATRACE_INT("VSYNC", mValue);
+                ATRACE_INT(mVsyncEventLabel.string(), mValue);
             }
         }
 
@@ -379,6 +374,8 @@
 
     const nsecs_t mPhaseOffset;
     const bool mTraceVsync;
+    const String8 mVsyncOnLabel;
+    const String8 mVsyncEventLabel;
 
     DispSync* mDispSync;
     sp<VSyncSource::Callback> mCallback;
@@ -437,7 +434,7 @@
                 // for displays other than the main display, so we always
                 // assume a connected display is unblanked.
                 ALOGD("marking display %zu as acquired/unblanked", i);
-                hw->acquireScreen();
+                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
             }
             mDisplays.add(token, hw);
         }
@@ -449,10 +446,10 @@
 
     // start the EventThread
     sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            vsyncPhaseOffsetNs, true);
+            vsyncPhaseOffsetNs, true, "app");
     mEventThread = new EventThread(vsyncSrc);
     sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            sfVsyncPhaseOffsetNs, false);
+            sfVsyncPhaseOffsetNs, true, "sf");
     mSFEventThread = new EventThread(sfVsyncSrc);
     mEventQueue.setEventThread(mSFEventThread);
 
@@ -579,6 +576,22 @@
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = float(1e9 / hwConfig.refresh);
+        info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
+
+        // This is how far in advance a buffer must be queued for
+        // presentation at a given time.  If you want a buffer to appear
+        // on the screen at time N, you must submit the buffer before
+        // (N - presentationDeadline).
+        //
+        // Normally it's one full refresh period (to give SF a chance to
+        // latch the buffer), but this can be reduced by configuring a
+        // DispSync offset.  Any additional delays introduced by the hardware
+        // composer or panel must be accounted for here.
+        //
+        // We add an additional 1ms to allow for processing time and
+        // differences between the ideal and actual refresh rate.
+        info.presentationDeadline =
+                hwConfig.refresh - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
 
         // All non-virtual displays are currently considered secure.
         info.secure = true;
@@ -589,11 +602,11 @@
     return NO_ERROR;
 }
 
-int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
+int SurfaceFlinger::getActiveConfig(const sp<IBinder>&) {
     return 0;
 }
 
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int id) {
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>&, int) {
     return NO_ERROR;
 }
 
@@ -793,7 +806,7 @@
     const bool repaintEverything = mRepaintEverything;
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->canDraw()) {
+        if (hw->isDisplayOn()) {
             // transform the dirty region into this screen's coordinate space
             const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
             if (!dirtyRegion.isEmpty()) {
@@ -858,9 +871,9 @@
         }
     }
 
-    if (runningWithoutSyncFramework) {
+    if (kIgnorePresentFences) {
         const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-        if (hw->isScreenAcquired()) {
+        if (hw->isDisplayOn()) {
             enableHardwareVsync();
         }
     }
@@ -895,7 +908,7 @@
             const sp<DisplayDevice>& hw(mDisplays[dpy]);
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
-            if (hw->canDraw()) {
+            if (hw->isDisplayOn()) {
                 SurfaceFlinger::computeVisibleRegions(layers,
                         hw->getLayerStack(), dirtyRegion, opaqueRegion);
 
@@ -991,7 +1004,7 @@
     const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->canDraw()) {
+        if (hw->isDisplayOn()) {
             // transform the dirty region into this screen's coordinate space
             const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
 
@@ -2005,19 +2018,10 @@
         format = PIXEL_FORMAT_RGBA_8888;
         break;
     case PIXEL_FORMAT_OPAQUE:
-#ifdef NO_RGBX_8888
-        format = PIXEL_FORMAT_RGB_565;
-#else
         format = PIXEL_FORMAT_RGBX_8888;
-#endif
         break;
     }
 
-#ifdef NO_RGBX_8888
-    if (format == PIXEL_FORMAT_RGBX_8888)
-        format = PIXEL_FORMAT_RGBA_8888;
-#endif
-
     *outLayer = new Layer(this, client, name, w, h, flags);
     status_t err = (*outLayer)->setBuffers(w, h, format, flags);
     if (err == NO_ERROR) {
@@ -2082,7 +2086,7 @@
     d.viewport.makeInvalid();
     displays.add(d);
     setTransactionState(state, displays, 0);
-    onScreenAcquired(getDefaultDisplayDevice());
+    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
 
     const nsecs_t period =
             getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
@@ -2103,42 +2107,35 @@
     postMessageAsync(msg);  // we may be called from main thread, use async message
 }
 
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
+        int mode) {
+    ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+            this);
+    int32_t type = hw->getDisplayType();
+    int currentMode = hw->getPowerMode();
 
-void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
-    ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this);
-    if (hw->isScreenAcquired()) {
-        // this is expected, e.g. when power manager wakes up during boot
-        ALOGD(" screen was previously acquired");
+    if (mode == currentMode) {
+        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
         return;
     }
 
-    hw->acquireScreen();
-    int32_t type = hw->getDisplayType();
-    if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        // built-in display, tell the HWC
-        getHwComposer().acquire(type);
+    hw->setPowerMode(mode);
+    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGW("Trying to set power mode for virtual display");
+        return;
+    }
 
+    if (currentMode == HWC_POWER_MODE_OFF) {
+        getHwComposer().setPowerMode(type, mode);
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
-
             resyncToHardwareVsync(true);
         }
-    }
-    mVisibleRegionsDirty = true;
-    repaintEverything();
-}
 
-void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
-    ALOGD("Screen released, type=%d flinger=%p", hw->getDisplayType(), this);
-    if (!hw->isScreenAcquired()) {
-        ALOGD(" screen was previously released");
-        return;
-    }
-
-    hw->releaseScreen();
-    int32_t type = hw->getDisplayType();
-    if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        mVisibleRegionsDirty = true;
+        repaintEverything();
+    } else if (mode == HWC_POWER_MODE_OFF) {
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
             disableHardwareVsync(true); // also cancels any in-progress resync
 
@@ -2146,56 +2143,38 @@
             mEventThread->onScreenReleased();
         }
 
-        // built-in display, tell the HWC
-        getHwComposer().release(type);
+        getHwComposer().setPowerMode(type, mode);
+        mVisibleRegionsDirty = true;
+        // from this point on, SF will stop drawing on this display
+    } else {
+        getHwComposer().setPowerMode(type, mode);
     }
-    mVisibleRegionsDirty = true;
-    // from this point on, SF will stop drawing on this display
 }
 
-void SurfaceFlinger::unblank(const sp<IBinder>& display) {
-    class MessageScreenAcquired : public MessageBase {
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
+    class MessageSetPowerMode: public MessageBase {
         SurfaceFlinger& mFlinger;
         sp<IBinder> mDisplay;
+        int mMode;
     public:
-        MessageScreenAcquired(SurfaceFlinger& flinger,
-                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
+        MessageSetPowerMode(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp, int mode) : mFlinger(flinger),
+                    mDisplay(disp) { mMode = mode; }
         virtual bool handler() {
-            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
             if (hw == NULL) {
-                ALOGE("Attempt to unblank null display %p", mDisplay.get());
+                ALOGE("Attempt to set power mode = %d for null display %p",
+                        mDisplay.get(), mMode);
             } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to unblank virtual display");
+                ALOGW("Attempt to set power mode = %d for virtual display",
+                        mMode);
             } else {
-                mFlinger.onScreenAcquired(hw);
+                mFlinger.setPowerModeInternal(hw, mMode);
             }
             return true;
         }
     };
-    sp<MessageBase> msg = new MessageScreenAcquired(*this, display);
-    postMessageSync(msg);
-}
-
-void SurfaceFlinger::blank(const sp<IBinder>& display) {
-    class MessageScreenReleased : public MessageBase {
-        SurfaceFlinger& mFlinger;
-        sp<IBinder> mDisplay;
-    public:
-        MessageScreenReleased(SurfaceFlinger& flinger,
-                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
-        virtual bool handler() {
-            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
-            if (hw == NULL) {
-                ALOGE("Attempt to blank null display %p", mDisplay.get());
-            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to blank virtual display");
-            } else {
-                mFlinger.onScreenReleased(hw);
-            }
-            return true;
-        }
-    };
-    sp<MessageBase> msg = new MessageScreenReleased(*this, display);
+    sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
     postMessageSync(msg);
 }
 
@@ -2348,9 +2327,6 @@
 {
     static const char* config =
             " [sf"
-#ifdef NO_RGBX_8888
-            " NO_RGBX_8888"
-#endif
 #ifdef HAS_CONTEXT_PRIORITY
             " HAS_CONTEXT_PRIORITY"
 #endif
@@ -2456,8 +2432,8 @@
     mRenderEngine->dump(result);
 
     hw->undefinedRegion.dump(result, "undefinedRegion");
-    result.appendFormat("  orientation=%d, canDraw=%d\n",
-            hw->getOrientation(), hw->canDraw());
+    result.appendFormat("  orientation=%d, isDisplayOn=%d\n",
+            hw->getOrientation(), hw->isDisplayOn());
     result.appendFormat(
             "  last eglSwapBuffers() time: %f us\n"
             "  last transaction time     : %f us\n"
@@ -2549,10 +2525,9 @@
         case CREATE_DISPLAY:
         case SET_TRANSACTION_STATE:
         case BOOT_FINISHED:
-        case BLANK:
-        case UNBLANK:
         case CLEAR_ANIMATION_FRAME_STATS:
         case GET_ANIMATION_FRAME_STATS:
+        case SET_POWER_MODE:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -2685,11 +2660,8 @@
             // This is an experimental interface
             // Needs to be shifted to proper binder interface when we productize
             case 1016: {
-                mPrimaryDispSync.setLowPowerMode(true);
-                return NO_ERROR;
-            }
-            case 1017: {
-                mPrimaryDispSync.setLowPowerMode(false);
+                n = data.readInt32();
+                mPrimaryDispSync.setRefreshSkipCount(n);
                 return NO_ERROR;
             }
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index cc01eb3..996a795 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -205,13 +205,10 @@
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);
-    // called when screen needs to turn off
-    virtual void blank(const sp<IBinder>& display);
-    // called when screen is turning back on
-    virtual void unblank(const sp<IBinder>& display);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
+    virtual void setPowerMode(const sp<IBinder>& display, int mode);
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
     virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
@@ -242,10 +239,8 @@
 
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays();
-    // called on the main thread in response to blank()
-    void onScreenReleased(const sp<const DisplayDevice>& hw);
-    // called on the main thread in response to unblank()
-    void onScreenAcquired(const sp<const DisplayDevice>& hw);
+    // called on the main thread in response to setPowerMode()
+    void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
 
     void handleMessageTransaction();
     void handleMessageInvalidate();