Merge "Hide QS customizer correctly" am: 03e4eb32fe
am: fb56958223

Change-Id: I62095e8b8c5bea7627e59cf166abce1cfa4ce2f1
diff --git a/Android.mk b/Android.mk
index 491c8be..7a21023f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -857,6 +857,7 @@
     -since $(SRC_API_DIR)/22.txt 22 \
     -since $(SRC_API_DIR)/23.txt 23 \
     -since $(SRC_API_DIR)/24.txt 24 \
+    -since $(SRC_API_DIR)/25.txt 25 \
 		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index d2e0327..5cc064e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -839,19 +839,22 @@
                             tmpConfig = new Configuration();
                         }
                         tmpConfig.setTo(config);
+
+                        // Get new DisplayMetrics based on the DisplayAdjustments given
+                        // to the ResourcesImpl. Update a copy if the CompatibilityInfo
+                        // changed, because the ResourcesImpl object will handle the
+                        // update internally.
+                        DisplayAdjustments daj = r.getDisplayAdjustments();
+                        if (compat != null) {
+                            daj = new DisplayAdjustments(daj);
+                            daj.setCompatibilityInfo(compat);
+                        }
+                        dm = getDisplayMetrics(displayId, daj);
+
                         if (!isDefaultDisplay) {
-                            // Get new DisplayMetrics based on the DisplayAdjustments given
-                            // to the ResourcesImpl. Udate a copy if the CompatibilityInfo
-                            // changed, because the ResourcesImpl object will handle the
-                            // update internally.
-                            DisplayAdjustments daj = r.getDisplayAdjustments();
-                            if (compat != null) {
-                                daj = new DisplayAdjustments(daj);
-                                daj.setCompatibilityInfo(compat);
-                            }
-                            dm = getDisplayMetrics(displayId, daj);
                             applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
                         }
+
                         if (hasOverrideConfiguration) {
                             tmpConfig.updateFrom(key.mOverrideConfiguration);
                         }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 246a752..b93a557 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1498,6 +1498,36 @@
     }
 
     /**
+     * Gets the currently supported profiles by the adapter.
+     *
+     *<p> This can be used to check whether a profile is supported before attempting
+     * to connect to its respective proxy.
+     *
+     * @return a list of integers indicating the ids of supported profiles as defined in
+     * {@link BluetoothProfile}.
+     * @hide
+     */
+    public List<Integer> getSupportedProfiles() {
+        final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
+
+        try {
+            synchronized (mManagerCallback) {
+                if (mService != null) {
+                    final long supportedProfilesBitMask = mService.getSupportedProfiles();
+
+                    for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
+                        if ((supportedProfilesBitMask & (1 << i)) != 0) {
+                            supportedProfiles.add(i);
+                        }
+                    }
+                }
+            }
+        } catch (RemoteException e) {Log.e(TAG, "getSupportedProfiles:", e);}
+
+        return supportedProfiles;
+    }
+
+    /**
      * Get the current connection state of the local Bluetooth adapter.
      * This can be used to check whether the local Bluetooth adapter is connected
      * to any profile of any other remote Bluetooth Device.
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index eee66d1..20d95cc 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -137,6 +137,13 @@
     public static final int PBAP_CLIENT = 17;
 
     /**
+     * Max profile ID. This value should be updated whenever a new profile is added to match
+     * the largest value assigned to a profile.
+     * @hide
+     */
+    public static final int MAX_PROFILE_ID = 17;
+
+    /**
      * Default priority for devices that we try to auto-connect to and
      * and allow incoming connections for the profile
      * @hide
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 8c98536..96a1ae8 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -63,6 +63,7 @@
     boolean removeBond(in BluetoothDevice device);
     int getBondState(in BluetoothDevice device);
     boolean isBondingInitiatedLocally(in BluetoothDevice device);
+    long getSupportedProfiles();
     int getConnectionState(in BluetoothDevice device);
 
     String getRemoteName(in BluetoothDevice device);
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index f4db4d6..b7099b6 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -268,6 +268,10 @@
     }
     
     public void setTo(DisplayMetrics o) {
+        if (this == o) {
+            return;
+        }
+
         widthPixels = o.widthPixels;
         heightPixels = o.heightPixels;
         density = o.density;
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
new file mode 100644
index 0000000..cf1bf62
--- /dev/null
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.hardware;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+public class AmbientDisplayConfiguration {
+
+    private final Context mContext;
+
+    public AmbientDisplayConfiguration(Context context) {
+        mContext = context;
+    }
+    
+    public boolean enabled(int user) {
+        return pulseOnNotificationEnabled(user)
+                || pulseOnPickupEnabled(user)
+                || pulseOnDoubleTapEnabled(user);
+    }
+    
+    public boolean available() {
+        return pulseOnNotificationAvailable() || pulseOnPickupAvailable()
+                || pulseOnDoubleTapAvailable();
+    }
+    
+    public boolean pulseOnNotificationEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
+    }
+
+    public boolean pulseOnNotificationAvailable() {
+        return ambientDisplayAvailable();
+    }
+
+    public boolean pulseOnPickupEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_PULSE_ON_PICK_UP, user)
+                && pulseOnPickupAvailable();
+    }
+    
+    public boolean pulseOnPickupAvailable() {
+        return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup)
+                && ambientDisplayAvailable();
+    }
+    
+    public boolean pulseOnDoubleTapEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, user)
+                && pulseOnDoubleTapAvailable();
+    }
+
+    public boolean pulseOnDoubleTapAvailable() {
+        return !TextUtils.isEmpty(doubleTapSensorType()) && ambientDisplayAvailable();
+    }
+
+    public String doubleTapSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
+    }
+
+    public String ambientDisplayComponent() {
+        return mContext.getResources().getString(R.string.config_dozeComponent);
+    }
+
+    private boolean ambientDisplayAvailable() {
+        return !TextUtils.isEmpty(ambientDisplayComponent());
+    }
+
+    private boolean boolSetting(String name, int user) {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, 1, user) != 0;
+    }
+
+}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 644c7e9..4f7b106 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -580,7 +580,13 @@
                         return;
                     }
                     if (grantUriPermission) {
-                        inputContentInfo.requestPermission();
+                        try {
+                            inputContentInfo.requestPermission();
+                        } catch (Exception e) {
+                            Log.e(TAG, "InputConnectionInfo.requestPermission() failed", e);
+                            args.callback.setCommitContentResult(false, args.seq);
+                            return;
+                        }
                     }
                     final boolean result =
                             ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 428159a..ee48264f 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -187,18 +187,17 @@
                 argv[argc++] = AssetManager::IDMAP_DIR;
 
                 // Directories to scan for overlays: if OVERLAY_SKU_DIR_PROPERTY is defined,
-                // use OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> if exists, otherwise
-                // use OVERLAY_DIR if exists.
+                // use OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> in addition to OVERLAY_DIR.
                 char subdir[PROP_VALUE_MAX];
                 int len = __system_property_get(AssetManager::OVERLAY_SKU_DIR_PROPERTY, subdir);
-                String8 overlayPath;
                 if (len > 0) {
-                    overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
-                } else {
-                    overlayPath = String8(AssetManager::OVERLAY_DIR);
+                    String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
+                    if (stat(overlayPath.string(), &st) == 0) {
+                        argv[argc++] = overlayPath.string();
+                    }
                 }
-                if (stat(overlayPath.string(), &st) == 0) {
-                    argv[argc++] = overlayPath.string();
+                if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+                    argv[argc++] = AssetManager::OVERLAY_DIR;
                 }
 
                 // Finally, invoke idmap (if any overlay directory exists)
diff --git a/core/res/res/layout-notround-watch/alert_dialog_title_material.xml b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
index 307c6db..0ab56f9 100644
--- a/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
+++ b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
@@ -22,6 +22,7 @@
         android:gravity="top|center_horizontal"
         android:minHeight="@dimen/alert_dialog_title_height">
     <ImageView android:id="@+id/icon"
+            android:adjustViewBounds="true"
             android:maxHeight="24dp"
             android:maxWidth="24dp"
             android:layout_marginTop="8dp"
diff --git a/core/res/res/layout-round-watch/alert_dialog_title_material.xml b/core/res/res/layout-round-watch/alert_dialog_title_material.xml
index 7e71e41..e543c9b 100644
--- a/core/res/res/layout-round-watch/alert_dialog_title_material.xml
+++ b/core/res/res/layout-round-watch/alert_dialog_title_material.xml
@@ -21,6 +21,7 @@
         android:gravity="top|center_horizontal"
         android:minHeight="@dimen/alert_dialog_title_height">
     <ImageView android:id="@+id/icon"
+            android:adjustViewBounds="true"
             android:maxHeight="24dp"
             android:maxWidth="24dp"
             android:layout_marginTop="12dp"
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index 8a080d9c..af4207e 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -95,7 +95,7 @@
     </style>
 
     <style name="DialogWindowTitle.Material">
-        <item name="maxLines">3</item>
+        <item name="maxLines">@empty</item>
         <item name="scrollHorizontally">false</item>
         <item name="textAppearance">@style/TextAppearance.Material.DialogWindowTitle</item>
         <item name="gravity">@integer/config_dialogTextGravity</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b75d638..aa39930 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1739,6 +1739,12 @@
          turned off and the screen off animation has been performed. -->
     <bool name="config_dozeAfterScreenOff">false</bool>
 
+    <!-- Doze: should the TYPE_PICK_UP_GESTURE sensor be used as a pulse signal. -->
+    <bool name="config_dozePulsePickup">false</bool>
+
+    <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
+    <string name="config_dozeDoubleTapSensorType" translatable="false"></string>
+
     <!-- Power Management: Specifies whether to decouple the auto-suspend state of the
          device from the display on/off state.
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c794351..bbe5ebe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2679,6 +2679,9 @@
   <java-symbol type="string" name="config_emergency_call_number" />
   <java-symbol type="array" name="config_emergency_mcc_codes" />
 
+  <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
+  <java-symbol type="bool" name="config_dozePulsePickup" />
+
   <!-- Used for MimeIconUtils. -->
   <java-symbol type="drawable" name="ic_doc_apk" />
   <java-symbol type="drawable" name="ic_doc_audio" />
diff --git a/docs/html/about/versions/nougat/android-7.0-samples.jd b/docs/html/about/versions/nougat/android-7.0-samples.jd
index e283a7a..ff63bef 100644
--- a/docs/html/about/versions/nougat/android-7.0-samples.jd
+++ b/docs/html/about/versions/nougat/android-7.0-samples.jd
@@ -6,7 +6,7 @@
 
 <p>
   Use the code samples below to learn about Android 7.0 capabilities and APIs. To
-  download the samples in Android Studio, select the <b>File &gt; Import
+  download the samples in Android Studio, select the <b>File &gt; New &gt; Import
   Samples</b> menu option.
 </p>
 
diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd
index ce6ad55..046e99e 100644
--- a/docs/html/training/location/geofencing.jd
+++ b/docs/html/training/location/geofencing.jd
@@ -332,22 +332,39 @@
 <p>This section outlines recommendations for using geofencing with the location
 APIs for Android.</p>
 
-<h3>Reduce power consumption</h3>
+<h3>
+  Reduce power consumption
+</h3>
 
-<p>You can use the following techniques to optimize power consumption in your apps that use geofencing:</p>
+<p>
+  You can use the following techniques to optimize power consumption in your
+  apps that use geofencing:
+</p>
 
 <ul>
-<li><p>Set the <a href="{@docRoot}android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)">
-notification responsiveness</a> to a higher value. Doing so improves power consumption by
-increasing the latency of geofence alerts. For example, if you set a responsiveness value of five
-minutes your app only checks for an entrance or exit alert once every five minutes.
-Setting lower values does not necessarily mean that users will be notified within that time period
-(for example, if you set a value of 5 seconds it may take a bit longer than that to receive the
-alert).</p></li>
-<li><p>Use a larger geofence radius for locations where a user spends a significant amount of time,
-such as home or work. While a larger radius doesn't directly reduce power consumption, it reduces
-the frequency at which the app checks for entrance or exit, effectively lowering overall power
-consumption.</p></li>
+  <li>
+    <p>
+      Set the <a href=
+      "https://developers.google.com/android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)">
+      notification responsiveness</a> to a higher value. Doing so improves
+      power consumption by increasing the latency of geofence alerts. For
+      example, if you set a responsiveness value of five minutes your app only
+      checks for an entrance or exit alert once every five minutes. Setting
+      lower values does not necessarily mean that users will be notified
+      within that time period (for example, if you set a value of 5 seconds it
+      may take a bit longer than that to receive the alert).
+    </p>
+  </li>
+
+  <li>
+    <p>
+      Use a larger geofence radius for locations where a user spends a
+      significant amount of time, such as home or work. While a larger radius
+      doesn't directly reduce power consumption, it reduces the frequency at
+      which the app checks for entrance or exit, effectively lowering overall
+      power consumption.
+    </p>
+  </li>
 </ul>
 
 <h3>Choose the optimal radius for your geofence</h3>
diff --git a/include/androidfw/Asset.h b/include/androidfw/Asset.h
index ee77e97..52c8637 100644
--- a/include/androidfw/Asset.h
+++ b/include/androidfw/Asset.h
@@ -44,7 +44,7 @@
  */
 class Asset {
 public:
-    virtual ~Asset(void);
+    virtual ~Asset(void) = default;
 
     static int32_t getGlobalCount();
     static String8 getAssetAllocations();
@@ -119,6 +119,19 @@
     const char* getAssetSource(void) const { return mAssetSource.string(); }
 
 protected:
+    /*
+     * Adds this Asset to the global Asset list for debugging and
+     * accounting.
+     * Concrete subclasses must call this in their constructor.
+     */
+    static void registerAsset(Asset* asset);
+
+    /*
+     * Removes this Asset from the global Asset list.
+     * Concrete subclasses must call this in their destructor.
+     */
+    static void unregisterAsset(Asset* asset);
+
     Asset(void);        // constructor; only invoked indirectly
 
     /* handle common seek() housekeeping */
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index 099d82e..31b692d 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -74,7 +74,7 @@
     static const char* OVERLAY_DIR;
     /*
      * If OVERLAY_SKU_DIR_PROPERTY is set, search for runtime resource overlay
-     * APKs in OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> rather than in
+     * APKs in OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> in addition to
      * OVERLAY_DIR.
      */
     static const char* OVERLAY_SKU_DIR_PROPERTY;
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 2cfa666..8e8c6a2 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -52,6 +52,47 @@
 static Asset* gHead = NULL;
 static Asset* gTail = NULL;
 
+void Asset::registerAsset(Asset* asset)
+{
+    AutoMutex _l(gAssetLock);
+    gCount++;
+    asset->mNext = asset->mPrev = NULL;
+    if (gTail == NULL) {
+        gHead = gTail = asset;
+    } else {
+        asset->mPrev = gTail;
+        gTail->mNext = asset;
+        gTail = asset;
+    }
+
+    if (kIsDebug) {
+        ALOGI("Creating Asset %p #%d\n", asset, gCount);
+    }
+}
+
+void Asset::unregisterAsset(Asset* asset)
+{
+    AutoMutex _l(gAssetLock);
+    gCount--;
+    if (gHead == asset) {
+        gHead = asset->mNext;
+    }
+    if (gTail == asset) {
+        gTail = asset->mPrev;
+    }
+    if (asset->mNext != NULL) {
+        asset->mNext->mPrev = asset->mPrev;
+    }
+    if (asset->mPrev != NULL) {
+        asset->mPrev->mNext = asset->mNext;
+    }
+    asset->mNext = asset->mPrev = NULL;
+
+    if (kIsDebug) {
+        ALOGI("Destroying Asset in %p #%d\n", asset, gCount);
+    }
+}
+
 int32_t Asset::getGlobalCount()
 {
     AutoMutex _l(gAssetLock);
@@ -79,43 +120,8 @@
 }
 
 Asset::Asset(void)
-    : mAccessMode(ACCESS_UNKNOWN)
+    : mAccessMode(ACCESS_UNKNOWN), mNext(NULL), mPrev(NULL)
 {
-    AutoMutex _l(gAssetLock);
-    gCount++;
-    mNext = mPrev = NULL;
-    if (gTail == NULL) {
-        gHead = gTail = this;
-    } else {
-        mPrev = gTail;
-        gTail->mNext = this;
-        gTail = this;
-    }
-    if (kIsDebug) {
-        ALOGI("Creating Asset %p #%d\n", this, gCount);
-    }
-}
-
-Asset::~Asset(void)
-{
-    AutoMutex _l(gAssetLock);
-    gCount--;
-    if (gHead == this) {
-        gHead = mNext;
-    }
-    if (gTail == this) {
-        gTail = mPrev;
-    }
-    if (mNext != NULL) {
-        mNext->mPrev = mPrev;
-    }
-    if (mPrev != NULL) {
-        mPrev->mNext = mNext;
-    }
-    mNext = mPrev = NULL;
-    if (kIsDebug) {
-        ALOGI("Destroying Asset in %p #%d\n", this, gCount);
-    }
 }
 
 /*
@@ -361,6 +367,9 @@
 _FileAsset::_FileAsset(void)
     : mStart(0), mLength(0), mOffset(0), mFp(NULL), mFileName(NULL), mMap(NULL), mBuf(NULL)
 {
+    // Register the Asset with the global list here after it is fully constructed and its
+    // vtable pointer points to this concrete type. b/31113965
+    registerAsset(this);
 }
 
 /*
@@ -369,6 +378,10 @@
 _FileAsset::~_FileAsset(void)
 {
     close();
+
+    // Unregister the Asset from the global list here before it is destructed and while its vtable
+    // pointer still points to this concrete type. b/31113965
+    unregisterAsset(this);
 }
 
 /*
@@ -685,6 +698,9 @@
     : mStart(0), mCompressedLen(0), mUncompressedLen(0), mOffset(0),
       mMap(NULL), mFd(-1), mZipInflater(NULL), mBuf(NULL)
 {
+    // Register the Asset with the global list here after it is fully constructed and its
+    // vtable pointer points to this concrete type. b/31113965
+    registerAsset(this);
 }
 
 /*
@@ -693,6 +709,10 @@
 _CompressedAsset::~_CompressedAsset(void)
 {
     close();
+
+    // Unregister the Asset from the global list here before it is destructed and while its vtable
+    // pointer still points to this concrete type. b/31113965
+    unregisterAsset(this);
 }
 
 /*
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 2bc026b7..1fe1773 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -22,6 +22,7 @@
 
 testFiles := \
     AppAsLib_test.cpp \
+    Asset_test.cpp \
     AttributeFinder_test.cpp \
     ByteBucketArray_test.cpp \
     Config_test.cpp \
diff --git a/libs/androidfw/tests/Asset_test.cpp b/libs/androidfw/tests/Asset_test.cpp
new file mode 100644
index 0000000..45c8cef
--- /dev/null
+++ b/libs/androidfw/tests/Asset_test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/Asset.h>
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+TEST(AssetTest, FileAssetRegistersItself) {
+    const int32_t count = Asset::getGlobalCount();
+    Asset* asset = new _FileAsset();
+    EXPECT_EQ(count + 1, Asset::getGlobalCount());
+    delete asset;
+    EXPECT_EQ(count, Asset::getGlobalCount());
+}
+
+TEST(AssetTest, CompressedAssetRegistersItself) {
+    const int32_t count = Asset::getGlobalCount();
+    Asset* asset = new _CompressedAsset();
+    EXPECT_EQ(count + 1, Asset::getGlobalCount());
+    delete asset;
+    EXPECT_EQ(count, Asset::getGlobalCount());
+}
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 37d9d0e7..7524ba0 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -591,7 +591,7 @@
 }
 
 static bool hasMergeableClip(const BakedOpState& state) {
-    return state.computedState.clipState
+    return !state.computedState.clipState
             || state.computedState.clipState->mode == ClipMode::Rectangle;
 }
 
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 53dbede..e2dc3a0 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -477,6 +477,35 @@
     EXPECT_EQ(4, renderer.getIndex());
 }
 
+RENDERTHREAD_TEST(FrameBuilder, regionClipStopsMerge) {
+    class RegionClipStopsMergeTestRenderer : public TestRendererBase {
+    public:
+        void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; }
+    };
+    auto node = TestUtils::createNode(0, 0, 400, 400,
+            [](RenderProperties& props, TestCanvas& canvas) {
+        SkPath path;
+        path.addCircle(200, 200, 200, SkPath::kCW_Direction);
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.clipPath(&path, SkRegion::kIntersect_Op);
+        SkPaint paint;
+        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        paint.setAntiAlias(true);
+        paint.setTextSize(50);
+        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
+        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
+        canvas.restore();
+    });
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
+
+    RegionClipStopsMergeTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
+}
+
 RENDERTHREAD_TEST(FrameBuilder, textMerging) {
     class TextMergingTestRenderer : public TestRendererBase {
     public:
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 6658e88..00bdc69 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -470,9 +470,7 @@
             synchronized (sActiveRingtones) {
                 sActiveRingtones.remove(Ringtone.this);
             }
-            if (mLocalPlayer != null) {
-                mLocalPlayer.setOnCompletionListener(null);
-            }
+            mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
         }
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index db326ba..012041f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -416,7 +416,7 @@
             in = getContext().getAssets().open(imageFile.getName());
             ExifInterface exifInterface = new ExifInterface(in);
             exifInterface.saveAttributes();
-        } catch (UnsupportedOperationException e) {
+        } catch (IOException e) {
             // Expected. saveAttributes is not supported with an ExifInterface object which was
             // created with InputStream.
             return;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 90dd440..8f254e9 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -282,8 +282,8 @@
             }
             final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
             if (info != null) {
-                operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
-                eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
+                operationsSupported = info.getOperationsSupported();
+                eventsSupported = info.getEventsSupported();
             }
         } else {
             roots = new MtpRoot[0];
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 3a16a75..6bc1d12 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -373,7 +373,11 @@
     }
 
     public DetailedState getDetailedState() {
-        return mNetworkInfo != null ? mNetworkInfo.getDetailedState() : null;
+        if (mNetworkInfo != null) {
+            return mNetworkInfo.getDetailedState();
+        }
+        Log.w(TAG, "NetworkInfo is null, cannot return detailed state");
+        return null;
     }
 
     public String getSavedNetworkSummary() {
@@ -813,7 +817,10 @@
                 return context.getString(R.string.wifi_connected_no_internet);
             }
         }
-
+        if (state == null) {
+            Log.w(TAG, "state is null, returning empty summary");
+            return "";
+        }
         String[] formats = context.getResources().getStringArray((ssid == null)
                 ? R.array.wifi_status : R.array.wifi_status_with_ssid);
         int index = state.ordinal();
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index eb1a1eb..9eea375 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -209,9 +209,6 @@
     <!-- Doze: should the significant motion sensor be used as a pulse signal? -->
     <bool name="doze_pulse_on_significant_motion">false</bool>
 
-    <!-- Doze: should the pickup sensor be used as a pulse signal? -->
-    <bool name="doze_pulse_on_pick_up">false</bool>
-
     <!-- Doze: check proximity sensor before pulsing? -->
     <bool name="doze_proximity_check_before_pulse">true</bool>
 
@@ -240,9 +237,6 @@
     -->
     <string name="doze_pickup_subtype_performs_proximity_check"></string>
 
-    <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
-    <string name="doze_double_tap_sensor_type" translatable="false"></string>
-
     <!-- Doze: pulse parameter - how long does it take to fade in? -->
     <integer name="doze_pulse_duration_in">900</integer>
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 56f6b8d..6c35243 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.view.Display;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.SystemUIApplication;
@@ -85,6 +86,8 @@
     private boolean mCarMode;
     private long mNotificationPulseTime;
 
+    private AmbientDisplayConfiguration mConfig;
+
     public DozeService() {
         if (DEBUG) Log.d(mTag, "new DozeService()");
         setDebug(DEBUG);
@@ -125,6 +128,7 @@
         setWindowless(true);
 
         mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+        mConfig = new AmbientDisplayConfiguration(mContext);
         mSensors = new TriggerSensor[] {
                 new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
@@ -135,12 +139,12 @@
                 mPickupSensor = new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
                         Settings.Secure.DOZE_PULSE_ON_PICK_UP,
-                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        mConfig.pulseOnPickupAvailable(), mDozeParameters.getVibrateOnPickup(),
                         DozeLog.PULSE_REASON_SENSOR_PICKUP),
                 new TriggerSensor(
-                        findSensorWithType(mDozeParameters.getDoubleTapSensorType()),
-                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
-                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        findSensorWithType(mConfig.doubleTapSensorType()),
+                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true,
+                        mDozeParameters.getVibrateOnPickup(),
                         DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
         };
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -359,7 +363,7 @@
 
     private void requestNotificationPulse() {
         if (DEBUG) Log.d(mTag, "requestNotificationPulse");
-        if (!mDozeParameters.getPulseOnNotifications()) return;
+        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
         mNotificationPulseTime = SystemClock.elapsedRealtime();
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index d5bf499..9e9bdd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -18,11 +18,13 @@
 
 import android.content.Context;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.R;
 
 import java.io.PrintWriter;
@@ -31,9 +33,6 @@
 import java.util.regex.Pattern;
 
 public class DozeParameters {
-    private static final String TAG = "DozeParameters";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
     private static final int MAX_DURATION = 60 * 1000;
 
     private final Context mContext;
@@ -55,10 +54,8 @@
         pw.print("    getPulseOutDuration(): "); pw.println(getPulseOutDuration());
         pw.print("    getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
         pw.print("    getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
-        pw.print("    getPulseOnPickup(): "); pw.println(getPulseOnPickup());
         pw.print("    getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
         pw.print("    getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
-        pw.print("    getPulseOnNotifications(): "); pw.println(getPulseOnNotifications());
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
         pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
                 dumpPickupSubtypePerformsProxCheck());
@@ -106,26 +103,14 @@
         return SystemProperties.getBoolean("doze.vibrate.sigmotion", false);
     }
 
-    public boolean getPulseOnPickup() {
-        return getBoolean("doze.pulse.pickup", R.bool.doze_pulse_on_pick_up);
-    }
-
     public boolean getVibrateOnPickup() {
         return SystemProperties.getBoolean("doze.vibrate.pickup", false);
     }
 
-    public String getDoubleTapSensorType() {
-        return mContext.getString(R.string.doze_double_tap_sensor_type);
-    }
-
     public boolean getProxCheckBeforePulse() {
         return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
     }
 
-    public boolean getPulseOnNotifications() {
-        return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications);
-    }
-
     public int getPickupVibrationThreshold() {
         return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f6447f6..498fae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -4231,7 +4231,7 @@
         }
         updateKeyguardState(staying, false /* fromShadeLocked */);
 
-        if (viewToClick != null) {
+        if (viewToClick != null && viewToClick.isAttachedToWindow()) {
             viewToClick.callOnClick();
         }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 4e236d1..0727629 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -838,7 +838,7 @@
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
                 return syncManager.computeSyncable(
-                        account, userId, providerName);
+                        account, userId, providerName, false);
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -854,6 +854,8 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
 
+        syncable = normalizeSyncable(syncable);
+
         int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
@@ -1156,6 +1158,15 @@
         }
     }
 
+    private static int normalizeSyncable(int syncable) {
+        if (syncable > 0) {
+            return SyncStorageEngine.AuthorityInfo.SYNCABLE;
+        } else if (syncable == 0) {
+            return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE;
+        }
+        return SyncStorageEngine.AuthorityInfo.UNDEFINED;
+    }
+
     /**
      * Hide this class since it is not part of api,
      * but current unittest framework requires it to be public
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 131da0b..653d241 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1001,7 +1001,12 @@
         }
     }
 
-    public int computeSyncable(Account account, int userId, String authority) {
+    private int computeSyncable(Account account, int userId, String authority) {
+        return computeSyncable(account, userId, authority, true);
+    }
+
+    public int computeSyncable(Account account, int userId, String authority,
+            boolean checkAccountAccess) {
         final int status = getIsSyncable(account, userId, authority);
         if (status == AuthorityInfo.NOT_SYNCABLE) {
             return AuthorityInfo.NOT_SYNCABLE;
@@ -1025,7 +1030,7 @@
         } catch (RemoteException e) {
             /* ignore - local call */
         }
-        if (!canAccessAccount(account, owningPackage, owningUid)) {
+        if (checkAccountAccess && !canAccessAccount(account, owningPackage, owningUid)) {
             Log.w(TAG, "Access to " + account + " denied for package "
                     + owningPackage + " in UID " + syncAdapterInfo.uid);
             return AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 935fa13..a1e3d62 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -321,7 +321,6 @@
                 mLightSensorEnabled = false;
                 mRecentLightSamples = 0;
                 mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
-                Slog.d(TAG, "disabling light sensor");
                 mSensorManager.unregisterListener(mLightSensorListener);
             }
         }
@@ -349,7 +348,6 @@
         }
         mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
         mAmbientLightRingBuffer.push(time, lux);
-        Slog.d(TAG, "pushing lux: " + lux);
 
         // Remember this sample value.
         mLastObservedLux = lux;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 20bccf1..1991c00 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.BIND_DREAM_SERVICE;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.DumpUtils;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -88,6 +89,8 @@
     private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
     private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
 
+    private AmbientDisplayConfiguration mDozeConfig;
+
     public DreamManagerService(Context context) {
         super(context);
         mContext = context;
@@ -97,6 +100,7 @@
         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
         mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
+        mDozeConfig = new AmbientDisplayConfiguration(mContext);
     }
 
     @Override
@@ -121,7 +125,7 @@
                 }
             }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.DOZE_ENABLED), false,
+                    Settings.Secure.getUriFor(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP), false,
                     mDozeEnabledObserver, UserHandle.USER_ALL);
             writePulseGestureEnabled();
         }
@@ -326,19 +330,12 @@
     }
 
     private ComponentName getDozeComponent(int userId) {
-        // Read the component from a system property to facilitate debugging.
-        // Note that for production devices, the dream should actually be declared in
-        // a config.xml resource.
-        String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
-        if (TextUtils.isEmpty(name)) {
-            // Read the component from a config.xml resource.
-            // The value should be specified in a resource overlay for the product.
-            name = mContext.getResources().getString(
-                    com.android.internal.R.string.config_dozeComponent);
+        if (mDozeConfig.enabled(userId)) {
+            return ComponentName.unflattenFromString(mDozeConfig.ambientDisplayComponent());
+        } else {
+            return null;
         }
-        boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.DOZE_ENABLED, 1, userId) != 0;
-        return TextUtils.isEmpty(name) || !enabled ? null : ComponentName.unflattenFromString(name);
+
     }
 
     private ServiceInfo getServiceInfo(ComponentName name) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 5dc9d02..72ee218 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2011,6 +2011,9 @@
     @ServiceThreadOnly
     void standby() {
         assertRunOnServiceThread();
+        if (!canGoToStandby()) {
+            return;
+        }
         mStandbyMessageReceived = true;
         mPowerManager.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
         // PowerManger will send the broadcast Intent.ACTION_SCREEN_OFF and after this gets
@@ -2038,10 +2041,13 @@
     @ServiceThreadOnly
     private void onStandby(final int standbyAction) {
         assertRunOnServiceThread();
-        if (!canGoToStandby()) return;
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
         invokeVendorCommandListenersOnControlStateChanged(false,
                 HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
+        if (!canGoToStandby()) {
+            mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+            return;
+        }
 
         final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
         disableDevices(new PendingActionClearedCallback() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 56a0173..f1bdde0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -464,8 +464,8 @@
 
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
     /**
-     * If VENDOR_OVERLAY_SKU_PROPERTY is set, search for runtime resource overlay APKs in
-     * VENDOR_OVERLAY_DIR/<value of VENDOR_OVERLAY_SKU_PROPERTY> rather than in
+     * If VENDOR_OVERLAY_SKU_PROPERTY is set, search for runtime resource overlay APKs also in
+     * VENDOR_OVERLAY_DIR/<value of VENDOR_OVERLAY_SKU_PROPERTY> in addition to
      * VENDOR_OVERLAY_DIR.
      */
     private static final String VENDOR_OVERLAY_SKU_PROPERTY = "ro.boot.vendor.overlay.sku";
@@ -2271,18 +2271,17 @@
                 }
             }
 
-            // Collect vendor overlay packages.
-            // (Do this before scanning any apps.)
+            // Collect vendor overlay packages. (Do this before scanning any apps.)
             // For security and version matching reason, only consider
             // overlay packages if they reside in the right directory.
-            File vendorOverlayDir;
             String overlaySkuDir = SystemProperties.get(VENDOR_OVERLAY_SKU_PROPERTY);
             if (!overlaySkuDir.isEmpty()) {
-                vendorOverlayDir = new File(VENDOR_OVERLAY_DIR, overlaySkuDir);
-            } else {
-                vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
+                scanDirTracedLI(new File(VENDOR_OVERLAY_DIR, overlaySkuDir), mDefParseFlags
+                        | PackageParser.PARSE_IS_SYSTEM
+                        | PackageParser.PARSE_IS_SYSTEM_DIR
+                        | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
             }
-            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
+            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index ae41541..0a9b334 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -85,12 +86,115 @@
         mSurfaceControl = ctrl;
         mDrawNeeded = true;
         mPaint = new Paint();
-        mPaint.setAntiAlias(true);
-        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
         mScreenOffset = screenOffset;
         mMaskThickness = maskThickness;
     }
 
+    static private double distanceFromCenterSquared(double x, double y) {
+        return x*x + y*y;
+    }
+
+    static private double distanceFromCenter(double x, double y) {
+        return Math.sqrt(distanceFromCenterSquared(x, y));
+    }
+
+    static private double verticalLineIntersectsCircle(double x, double radius) {
+        return Math.sqrt(radius*radius - x*x);
+    }
+
+    static private double  horizontalLineIntersectsCircle(double y, double radius) {
+        return Math.sqrt(radius*radius - y*y);
+    }
+
+    static private double triangleArea(double width, double height) {
+        return width * height / 2.0;
+    }
+
+    static private double trapezoidArea(double width, double height1, double height2) {
+        return width * (height1 + height2) / 2.0;
+    }
+
+    static private double areaUnderChord(double radius, double chordLength) {
+        double isocelesHeight = Math.sqrt(radius*radius - chordLength * chordLength / 4.0);
+        double areaUnderIsoceles = isocelesHeight * chordLength / 2.0;
+        double halfAngle = Math.asin(chordLength / (2.0 * radius));
+        double areaUnderArc = halfAngle * radius * radius;
+
+        return areaUnderArc - triangleArea(chordLength, isocelesHeight);
+    }
+
+    // Returns the fraction of the pixel at (px, py) covered by
+    // the circle with center (cx, cy) and radius 'radius'
+    static private double calcPixelShading(double cx, double cy, double px,
+            double py, double radius) {
+        // Translate so the center is at the origin
+        px -= cx;
+        py -= cy;
+
+        // Reflect across the axis so the point is in the first quadrant
+        px = Math.abs(px);
+        py = Math.abs(py);
+
+        // One more transformation which simplifies the logic later
+        if (py > px) {
+            double temp;
+
+            temp = px;
+            px = py;
+            py = temp;
+        }
+
+        double left = px - 0.5;
+        double right = px + 0.5;
+        double bottom = py - 0.5;
+        double top = py + 0.5;
+
+        if (distanceFromCenterSquared(left, bottom) > radius*radius) {
+            return 0.0;
+        }
+
+        if (distanceFromCenterSquared(right, top) < radius*radius) {
+            return 1.0;
+        }
+
+        // Check if only the bottom-left corner of the pixel is inside the circle
+        if (distanceFromCenterSquared(left, top) > radius*radius) {
+            double triangleWidth = horizontalLineIntersectsCircle(bottom, radius) - left;
+            double triangleHeight = verticalLineIntersectsCircle(left, radius) - bottom;
+            double chordLength = distanceFromCenter(triangleWidth, triangleHeight);
+
+            return triangleArea(triangleWidth, triangleHeight)
+                   + areaUnderChord(radius, chordLength);
+
+        }
+
+        // Check if only the top-right corner of the pixel is outside the circle
+        if (distanceFromCenterSquared(right, bottom) < radius*radius) {
+            double triangleWidth = right - horizontalLineIntersectsCircle(top, radius);
+            double triangleHeight = top - verticalLineIntersectsCircle(right, radius);
+            double chordLength = distanceFromCenter(triangleWidth, triangleHeight);
+
+            return 1 - triangleArea(triangleWidth, triangleHeight)
+                   + areaUnderChord(radius, chordLength);
+        }
+
+        // It must be that the top-left and bottom-left corners are inside the circle
+        double trapezoidWidth1 = horizontalLineIntersectsCircle(top, radius) - left;
+        double trapezoidWidth2 = horizontalLineIntersectsCircle(bottom, radius) - left;
+        double chordLength = distanceFromCenter(1, trapezoidWidth2 - trapezoidWidth1);
+        double shading = trapezoidArea(1.0, trapezoidWidth1, trapezoidWidth2)
+                         + areaUnderChord(radius, chordLength);
+
+        // When top >= 0 and bottom <= 0 it's possible for the circle to intersect the pixel 4 times.
+        // If so, remove the area of the section which crosses the right-hand edge.
+        if (top >= 0 && bottom <= 0 && radius > right) {
+            shading -= areaUnderChord(radius, 2 * verticalLineIntersectsCircle(right, radius));
+        }
+
+        return shading;
+    }
+
     private void drawIfNeeded() {
         if (!mDrawNeeded || !mVisible || mDimensionsUnequal) {
             return;
@@ -123,11 +227,41 @@
             break;
         }
 
-        int circleRadius = mScreenSize.x / 2;
         c.drawColor(Color.BLACK);
 
-        // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the display edges.
-        c.drawCircle(circleRadius, circleRadius, circleRadius - mMaskThickness, mPaint);
+        int maskWidth = mScreenSize.x - 2*mMaskThickness;
+        int maskHeight;
+
+        // Don't render the whole mask if it is partly offscreen.
+        if (maskWidth > mScreenSize.y) {
+            maskHeight = mScreenSize.y;
+        } else {
+            // To ensure the mask can be properly centered on the canvas the
+            // bitmap dimensions must have the same parity as those of the canvas.
+            maskHeight = mScreenSize.y - ((mScreenSize.y - maskWidth) & ~1);
+        }
+
+        double cx = (maskWidth - 1.0) / 2.0;
+        double cy = (maskHeight - 1.0) / 2.0;
+        double radius = maskWidth / 2.0;
+        int[] pixels = new int[maskWidth * maskHeight];
+
+        for (int py=0; py<maskHeight; py++) {
+            for (int px=0; px<maskWidth; px++) {
+                double shading = calcPixelShading(cx, cy, px, py, radius);
+                pixels[maskWidth*py + px] =
+                    Color.argb(255 - (int)Math.round(255.0*shading), 0, 0, 0);
+            }
+        }
+
+        Bitmap transparency = Bitmap.createBitmap(pixels, maskWidth, maskHeight,
+            Bitmap.Config.ARGB_8888);
+
+        c.drawBitmap(transparency,
+                     (float)mMaskThickness,
+                     (float)((mScreenSize.y - maskHeight) / 2),
+                     mPaint);
+
         mSurface.unlockCanvasAndPost(c);
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7b1a523..e8104c4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -28,15 +28,11 @@
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 
 import android.app.ActivityManager.StackId;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Region.Op;
-import android.os.Build;
-import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
@@ -728,8 +724,7 @@
         for (int i = 0; i < windowCount; i++) {
             WindowState window = windows.get(i);
             if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
-                    && !window.mPermanentlyHidden && !window.mAnimatingExit
-                    && !window.mRemoveOnExit) {
+                    && !window.isRemovedOrHidden()) {
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 55bf394..fbef2c6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2961,4 +2961,10 @@
     public boolean isRtl() {
         return mMergedConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
     }
+
+    public boolean isRemovedOrHidden() {
+        return mPermanentlyHidden || mAnimatingExit
+                || mRemoveOnExit || mWindowRemovalAllowed
+                || mViewVisibility == View.GONE;
+    }
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index 0dcd1521..dd7b5a8 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -27,6 +27,9 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.UUID;
 
@@ -40,7 +43,7 @@
     static final boolean DBG = false;
 
     private static final String NAME = "sound_model.db";
-    private static final int VERSION = 5;
+    private static final int VERSION = 6;
 
     public static interface SoundModelContract {
         public static final String TABLE = "sound_model";
@@ -58,15 +61,19 @@
     // Table Create Statement
     private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE "
             + SoundModelContract.TABLE + "("
-            + SoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
-            + SoundModelContract.KEY_VENDOR_UUID + " TEXT, "
+            + SoundModelContract.KEY_MODEL_UUID + " TEXT,"
+            + SoundModelContract.KEY_VENDOR_UUID + " TEXT,"
             + SoundModelContract.KEY_KEYPHRASE_ID + " INTEGER,"
             + SoundModelContract.KEY_TYPE + " INTEGER,"
             + SoundModelContract.KEY_DATA + " BLOB,"
             + SoundModelContract.KEY_RECOGNITION_MODES + " INTEGER,"
             + SoundModelContract.KEY_LOCALE + " TEXT,"
             + SoundModelContract.KEY_HINT_TEXT + " TEXT,"
-            + SoundModelContract.KEY_USERS + " TEXT" + ")";
+            + SoundModelContract.KEY_USERS + " TEXT,"
+            + "PRIMARY KEY (" + SoundModelContract.KEY_KEYPHRASE_ID + ","
+                              + SoundModelContract.KEY_LOCALE + ","
+                              + SoundModelContract.KEY_USERS + ")"
+            + ")";
 
     public DatabaseHelper(Context context) {
         super(context, NAME, null, VERSION);
@@ -93,6 +100,44 @@
                 oldVersion++;
             }
         }
+        if (oldVersion == 5) {
+            // We need to enforce the new primary key constraint that the
+            // keyphrase id, locale, and users are unique. We have to first pull
+            // everything out of the database, remove duplicates, create the new
+            // table, then push everything back in.
+            String selectQuery = "SELECT * FROM " + SoundModelContract.TABLE;
+            Cursor c = db.rawQuery(selectQuery, null);
+            List<SoundModelRecord> old_records = new ArrayList<SoundModelRecord>();
+            try {
+                if (c.moveToFirst()) {
+                    do {
+                        try {
+                            old_records.add(new SoundModelRecord(5, c));
+                        } catch (Exception e) {
+                            Slog.e(TAG, "Failed to extract V5 record", e);
+                        }
+                    } while (c.moveToNext());
+                }
+            } finally {
+                c.close();
+            }
+            db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
+            onCreate(db);
+            for (SoundModelRecord record : old_records) {
+                if (record.ifViolatesV6PrimaryKeyIsFirstOfAnyDuplicates(old_records)) {
+                    try {
+                        long return_value = record.writeToDatabase(6, db);
+                        if (return_value == -1) {
+                            Slog.e(TAG, "Database write failed " + record.modelUuid + ": "
+                                    + return_value);
+                        }
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Failed to update V6 record " + record.modelUuid, e);
+                    }
+                }
+            }
+            oldVersion++;
+        }
     }
 
     /**
@@ -279,4 +324,93 @@
         }
         return users;
     }
+
+    private static class SoundModelRecord {
+        public final String modelUuid;
+        public final String vendorUuid;
+        public final int keyphraseId;
+        public final int type;
+        public final byte[] data;
+        public final int recognitionModes;
+        public final String locale;
+        public final String hintText;
+        public final String users;
+
+        public SoundModelRecord(int version, Cursor c) {
+            modelUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_MODEL_UUID));
+            if (version >= 5) {
+                vendorUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_VENDOR_UUID));
+            } else {
+                vendorUuid = null;
+            }
+            keyphraseId = c.getInt(c.getColumnIndex(SoundModelContract.KEY_KEYPHRASE_ID));
+            type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+            data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+            recognitionModes = c.getInt(c.getColumnIndex(SoundModelContract.KEY_RECOGNITION_MODES));
+            locale = c.getString(c.getColumnIndex(SoundModelContract.KEY_LOCALE));
+            hintText = c.getString(c.getColumnIndex(SoundModelContract.KEY_HINT_TEXT));
+            users = c.getString(c.getColumnIndex(SoundModelContract.KEY_USERS));
+        }
+
+        private boolean V6PrimaryKeyMatches(SoundModelRecord record) {
+          return keyphraseId == record.keyphraseId && stringComparisonHelper(locale, record.locale)
+              && stringComparisonHelper(users, record.users);
+        }
+
+        // Returns true if this record is a) the only record with the same V6 primary key, or b) the
+        // first record in the list of all records that have the same primary key and equal data.
+        // It will return false if a) there are any records that have the same primary key and
+        // different data, or b) there is a previous record in the list that has the same primary
+        // key and data.
+        // Note that 'this' object must be inside the list.
+        public boolean ifViolatesV6PrimaryKeyIsFirstOfAnyDuplicates(
+                List<SoundModelRecord> records) {
+            // First pass - check to see if all the records that have the same primary key have
+            // duplicated data.
+            for (SoundModelRecord record : records) {
+                if (this == record) {
+                    continue;
+                }
+                // If we have different/missing data with the same primary key, then we should drop
+                // everything.
+                if (this.V6PrimaryKeyMatches(record) && !Arrays.equals(data, record.data)) {
+                    return false;
+                }
+            }
+
+            // We only want to return true for the first duplicated model.
+            for (SoundModelRecord record : records) {
+                if (this.V6PrimaryKeyMatches(record)) {
+                    return this == record;
+                }
+            }
+            return true;
+        }
+
+        public long writeToDatabase(int version, SQLiteDatabase db) {
+            ContentValues values = new ContentValues();
+            values.put(SoundModelContract.KEY_MODEL_UUID, modelUuid);
+            if (version >= 5) {
+                values.put(SoundModelContract.KEY_VENDOR_UUID, vendorUuid);
+            }
+            values.put(SoundModelContract.KEY_KEYPHRASE_ID, keyphraseId);
+            values.put(SoundModelContract.KEY_TYPE, type);
+            values.put(SoundModelContract.KEY_DATA, data);
+            values.put(SoundModelContract.KEY_RECOGNITION_MODES, recognitionModes);
+            values.put(SoundModelContract.KEY_LOCALE, locale);
+            values.put(SoundModelContract.KEY_HINT_TEXT, hintText);
+            values.put(SoundModelContract.KEY_USERS, users);
+
+            return db.insertWithOnConflict(
+                       SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
+        }
+
+        // Helper for checking string equality - including the case when they are null.
+        static private boolean stringComparisonHelper(String a, String b) {
+          if (a != null) {
+            return a.equals(b);
+          }
+          return a == b;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7432de9..4dcc7d5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -726,6 +726,16 @@
     public static final String KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS =
             "carrier_additional_cbs_channels_strings";
 
+    /**
+      * Indicates whether STK LAUNCH_BROWSER command is disabled.
+      * If {@code true}, then the browser will not be launched
+      * on UI for the LAUNCH_BROWSER STK command.
+      * @hide
+      */
+    public static final String KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL =
+            "stk_disable_launch_browser_bool";
+
+
     // These variables are used by the MMS service and exposed through another API, {@link
     // SmsManager}. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -1194,6 +1204,7 @@
         sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
         sDefaults.putStringArray(FILTERED_CNAP_NAMES_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+        sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
     }
 
     /**