Merge "Add Voice Assist key." into lmp-dev
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 0b182af..94e4792 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -101,6 +101,11 @@
     EXPECT_EQ(0, validate_apk_path(internal1))
             << internal1 << " should be allowed as a valid path";
 
+    // b/16888084
+    const char *path2 = TEST_APP_DIR "example.com/example.apk";
+    EXPECT_EQ(0, validate_apk_path(path2))
+            << path2 << " should be allowed as a valid path";
+
     const char *badint1 = TEST_APP_DIR "../example.apk";
     EXPECT_EQ(-1, validate_apk_path(badint1))
             << badint1 << " should be rejected as a invalid path";
@@ -109,9 +114,18 @@
     EXPECT_EQ(-1, validate_apk_path(badint2))
             << badint2 << " should be rejected as a invalid path";
 
-    const char *badint3 = TEST_APP_DIR "example.com/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badint3))
-            << badint3 << " should be rejected as a invalid path";
+    // Only one subdir should be allowed.
+    const char *bad_path3 = TEST_APP_DIR "example.com/subdir/pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path3))
+            << bad_path3 << " should be rejected as a invalid path";
+
+    const char *bad_path4 = TEST_APP_DIR "example.com/subdir/../pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path4))
+            << bad_path4 << " should be rejected as a invalid path";
+
+    const char *bad_path5 = TEST_APP_DIR "example.com1/../example.com2/pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path5))
+            << bad_path5 << " should be rejected as a invalid path";
 }
 
 TEST_F(UtilsTest, IsValidApkPath_Private) {
@@ -120,6 +134,11 @@
     EXPECT_EQ(0, validate_apk_path(private1))
             << private1 << " should be allowed as a valid path";
 
+    // b/16888084
+    const char *path2 = TEST_APP_DIR "example.com/example.apk";
+    EXPECT_EQ(0, validate_apk_path(path2))
+            << path2 << " should be allowed as a valid path";
+
     const char *badpriv1 = TEST_APP_PRIVATE_DIR "../example.apk";
     EXPECT_EQ(-1, validate_apk_path(badpriv1))
             << badpriv1 << " should be rejected as a invalid path";
@@ -128,9 +147,18 @@
     EXPECT_EQ(-1, validate_apk_path(badpriv2))
             << badpriv2 << " should be rejected as a invalid path";
 
-    const char *badpriv3 = TEST_APP_PRIVATE_DIR "example.com/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badpriv3))
-            << badpriv3 << " should be rejected as a invalid path";
+    // Only one subdir should be allowed.
+    const char *bad_path3 = TEST_APP_PRIVATE_DIR "example.com/subdir/pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path3))
+            << bad_path3 << " should be rejected as a invalid path";
+
+    const char *bad_path4 = TEST_APP_PRIVATE_DIR "example.com/subdir/../pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path4))
+            << bad_path4 << " should be rejected as a invalid path";
+
+    const char *bad_path5 = TEST_APP_PRIVATE_DIR "example.com1/../example.com2/pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(bad_path5))
+            << bad_path5 << " should be rejected as a invalid path";
 }
 
 
@@ -218,6 +246,24 @@
             << badapp3 << " should be rejected not a system path";
 }
 
+TEST_F(UtilsTest, CheckSystemApp_Subdir) {
+    const char *sysapp = TEST_SYSTEM_DIR1 "com.example/com.example.apk";
+    EXPECT_EQ(0, validate_system_app_path(sysapp))
+            << sysapp << " should be allowed as a system path";
+
+    const char *badapp = TEST_SYSTEM_DIR1 "com.example/subdir/com.example.apk";
+    EXPECT_EQ(-1, validate_system_app_path(badapp))
+            << badapp << " should be rejected not a system path";
+
+    const char *badapp1 = TEST_SYSTEM_DIR1 "com.example/subdir/../com.example.apk";
+    EXPECT_EQ(-1, validate_system_app_path(badapp1))
+            << badapp1 << " should be rejected not a system path";
+
+    const char *badapp2 = TEST_SYSTEM_DIR1 "com.example1/../com.example2/com.example.apk";
+    EXPECT_EQ(-1, validate_system_app_path(badapp2))
+            << badapp2 << " should be rejected not a system path";
+}
+
 TEST_F(UtilsTest, GetPathFromString_NullPathFail) {
     dir_rec_t test1;
     EXPECT_EQ(-1, get_path_from_string(&test1, (const char *) NULL))
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 35172de..8cd1168 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -808,6 +808,33 @@
 }
 
 /**
+ * Validate that the path is valid in the context of the provided directory.
+ * The path is allowed to have at most one subdirectory and no indirections
+ * to top level directories (i.e. have "..").
+ */
+static int validate_path(const dir_rec_t* dir, const char* path) {
+    size_t dir_len = dir->len;
+    const char* subdir = strchr(path + dir_len, '/');
+
+    // Only allow the path to have at most one subdirectory.
+    if (subdir != NULL) {
+        ++subdir;
+        if (strchr(subdir, '/') != NULL) {
+            ALOGE("invalid apk path '%s' (subdir?)\n", path);
+            return -1;
+        }
+    }
+
+    // Directories can't have a period directly after the directory markers to prevent "..".
+    if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) {
+        ALOGE("invalid apk path '%s' (trickery)\n", path);
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
  * Checks whether a path points to a system app (.apk file). Returns 0
  * if it is a system app or -1 if it is not.
  */
@@ -817,11 +844,7 @@
     for (i = 0; i < android_system_dirs.count; i++) {
         const size_t dir_len = android_system_dirs.dirs[i].len;
         if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
-            if (path[dir_len] == '.' || strchr(path + dir_len, '/') != NULL) {
-                ALOGE("invalid system apk path '%s' (trickery)\n", path);
-                return -1;
-            }
-            return 0;
+            return validate_path(android_system_dirs.dirs + i, path);
         }
     }
 
@@ -914,54 +937,26 @@
 }
 
 /**
- * Check whether path points to a valid path for an APK file. An ASEC
- * directory is allowed to have one level of subdirectory names. Returns -1
- * when an invalid path is encountered and 0 when a valid path is encountered.
+ * Check whether path points to a valid path for an APK file. Only one level of
+ * subdirectory names is allowed. Returns -1 when an invalid path is encountered
+ * and 0 when a valid path is encountered.
  */
 int validate_apk_path(const char *path)
 {
-    int allowsubdir = 0;
-    char *subdir = NULL;
-    size_t dir_len;
-    size_t path_len;
+    const dir_rec_t* dir = NULL;
 
     if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
-        dir_len = android_app_dir.len;
+        dir = &android_app_dir;
     } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
-        dir_len = android_app_private_dir.len;
+        dir = &android_app_private_dir;
     } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
-        dir_len = android_asec_dir.len;
-        allowsubdir = 1;
+        dir = &android_asec_dir;
     } else {
         ALOGE("invalid apk path '%s' (bad prefix)\n", path);
         return -1;
     }
 
-    path_len = strlen(path);
-
-    /*
-     * Only allow the path to have a subdirectory if it's been marked as being allowed.
-     */
-    if ((subdir = strchr(path + dir_len, '/')) != NULL) {
-        ++subdir;
-        if (!allowsubdir
-                || (path_len > (size_t) (subdir - path) && (strchr(subdir, '/') != NULL))) {
-            ALOGE("invalid apk path '%s' (subdir?)\n", path);
-            return -1;
-        }
-    }
-
-    /*
-     *  Directories can't have a period directly after the directory markers
-     *  to prevent ".."
-     */
-    if (path[dir_len] == '.'
-            || (subdir != NULL && ((*subdir == '.') || (strchr(subdir, '/') != NULL)))) {
-        ALOGE("invalid apk path '%s' (trickery)\n", path);
-        return -1;
-    }
-
-    return 0;
+    return validate_path(dir, path);
 }
 
 int append_and_increment(char** dst, const char* src, size_t* dst_size) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index bee5062..84d3b0f 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -924,6 +924,7 @@
     }
 #if DEBUG_CONNECTIONS
     mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
+    mTotalAcksNeeded = mTotalAcksReceived = 0;
 #endif
 }
 
@@ -960,12 +961,15 @@
                             mCacheSize,
                             mMaxCacheSize);
 #if DEBUG_CONNECTIONS
-        result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d\n",
+        result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d |"
+                                  " total_acks_needed %d | total_acks_recvd %d\n",
                                         mEventsReceived,
                                         mEventsSent,
                                         mEventsSentFromCache,
-                                        mEventsReceived - (mEventsSentFromCache
-                                                           mEventsSent + mCacheSize));
+                                        mEventsReceived - (mEventsSentFromCache +
+                                                           mEventsSent + mCacheSize),
+                                        mTotalAcksNeeded,
+                                        mTotalAcksReceived);
 #endif
 
     }
@@ -1125,6 +1129,9 @@
     if (index_wake_up_event >= 0) {
         scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
         ++mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+        ++mTotalAcksNeeded;
+#endif
     }
 
     // NOTE: ASensorEvent and sensors_event_t are the same type.
@@ -1136,6 +1143,9 @@
             // If there was a wake_up sensor_event, reset the flag.
             scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
             --mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+            --mTotalAcksNeeded;
+#endif
         }
         if (mEventCache == NULL) {
             mMaxCacheSize = computeMaxCacheSizeLocked();
@@ -1214,6 +1224,9 @@
             mEventCache[index_wake_up_event + numEventsSent].flags |=
                     WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
             ++mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+            ++mTotalAcksNeeded;
+#endif
         }
 
         ssize_t size = SensorEventQueue::write(mChannel,
@@ -1225,6 +1238,9 @@
                 mEventCache[index_wake_up_event + numEventsSent].flags  &=
                         ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
                 --mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+                --mTotalAcksNeeded;
+#endif
             }
             memmove(mEventCache, &mEventCache[numEventsSent],
                                  (mCacheSize - numEventsSent) * sizeof(sensors_event_t));
@@ -1333,6 +1349,9 @@
         {
            Mutex::Autolock _l(mConnectionLock);
            --mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+           ++mTotalAcksReceived;
+#endif
         }
         // Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
         // here as checkWakeLockState() will need it.
@@ -1380,7 +1399,7 @@
    if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
        // It is extremely unlikely that there is a write failure in non batch mode. Return a cache
        // size that is equal to that of the batch mode.
-       ALOGI("Write failure in non-batch mode");
+       // ALOGW("Write failure in non-batch mode");
        return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
    }
    return fifoWakeUpSensors + fifoNonWakeUpSensors;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 15759ae..77f6f6a 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -142,6 +142,7 @@
 
 #if DEBUG_CONNECTIONS
         int mEventsReceived, mEventsSent, mEventsSentFromCache;
+        int mTotalAcksNeeded, mTotalAcksReceived;
 #endif
 
     public:
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index bd07d24..a8dcf98 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -780,6 +780,8 @@
 
 status_t HWComposer::setActiveConfig(int disp, int mode) {
     LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+    DisplayData& dd(mDisplayData[disp]);
+    dd.currentConfig = mode;
     if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
         return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
     } else {