Merge "Update package names to work with the proto3 compiler"
diff --git a/api/current.txt b/api/current.txt
index 22871fa..f89488d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -577,8 +577,11 @@
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
+    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
     field public static final int foreground = 16843017; // 0x1010109
@@ -29330,6 +29333,7 @@
     method public void finishBroadcast();
     method public java.lang.Object getBroadcastCookie(int);
     method public E getBroadcastItem(int);
+    method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
     method public void kill();
     method public void onCallbackDied(E);
@@ -32077,6 +32081,7 @@
     field public static final java.lang.String EXTRA_LOADING = "loading";
     field public static final java.lang.String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION";
     field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+    field public static final java.lang.String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
     field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
   }
 
@@ -37578,6 +37583,7 @@
     method public void listen(android.telephony.PhoneStateListener, int);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
diff --git a/api/system-current.txt b/api/system-current.txt
index a8a725e..baac810 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -683,8 +683,11 @@
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
+    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
     field public static final int foreground = 16843017; // 0x1010109
@@ -4545,7 +4548,9 @@
     ctor public EphemeralResolverService();
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
+    method public abstract deprecated java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
+    method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralIntentFilter(int[]);
+    method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralResolveInfo(int[]);
     field public static final java.lang.String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
     field public static final java.lang.String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
   }
@@ -9189,6 +9194,7 @@
     field public static final java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
     field public static final java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
     field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
+    field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
     field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
     field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
     field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
@@ -9893,18 +9899,39 @@
     field public int reqTouchScreen;
   }
 
+  public final class EphemeralIntentFilter implements android.os.Parcelable {
+    ctor public EphemeralIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
+    method public int describeContents();
+    method public java.util.List<android.content.IntentFilter> getFilters();
+    method public java.lang.String getSplitName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralIntentFilter> CREATOR;
+  }
+
   public final class EphemeralResolveInfo implements android.os.Parcelable {
-    ctor public EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
+    ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
+    ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
+    ctor public EphemeralResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
     method public int describeContents();
     method public byte[] getDigestBytes();
     method public int getDigestPrefix();
-    method public java.util.List<android.content.IntentFilter> getFilters();
+    method public deprecated java.util.List<android.content.IntentFilter> getFilters();
+    method public java.util.List<android.content.pm.EphemeralIntentFilter> getIntentFilters();
     method public java.lang.String getPackageName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo> CREATOR;
     field public static final java.lang.String SHA_ALGORITHM = "SHA-256";
   }
 
+  public static final class EphemeralResolveInfo.EphemeralDigest implements android.os.Parcelable {
+    ctor public EphemeralResolveInfo.EphemeralDigest(java.lang.String);
+    method public int describeContents();
+    method public byte[][] getDigestBytes();
+    method public int[] getDigestPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo.EphemeralDigest> CREATOR;
+  }
+
   public final class FeatureGroupInfo implements android.os.Parcelable {
     ctor public FeatureGroupInfo();
     ctor public FeatureGroupInfo(android.content.pm.FeatureGroupInfo);
@@ -31858,6 +31885,7 @@
     method public void finishBroadcast();
     method public java.lang.Object getBroadcastCookie(int);
     method public E getBroadcastItem(int);
+    method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
     method public void kill();
     method public void onCallbackDied(E);
@@ -34740,6 +34768,7 @@
     field public static final java.lang.String EXTRA_LOADING = "loading";
     field public static final java.lang.String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION";
     field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+    field public static final java.lang.String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
     field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
   }
 
@@ -40727,6 +40756,7 @@
     method public boolean needsOtaServiceProvisioning();
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void setDataEnabled(boolean);
     method public void setDataEnabled(int, boolean);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 50dfa2a..f7f5e50 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -577,8 +577,11 @@
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
+    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
     field public static final int foreground = 16843017; // 0x1010109
@@ -29412,6 +29415,7 @@
     method public void finishBroadcast();
     method public java.lang.Object getBroadcastCookie(int);
     method public E getBroadcastItem(int);
+    method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
     method public void kill();
     method public void onCallbackDied(E);
@@ -32163,6 +32167,7 @@
     field public static final java.lang.String EXTRA_LOADING = "loading";
     field public static final java.lang.String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION";
     field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+    field public static final java.lang.String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
     field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
   }
 
@@ -37667,6 +37672,7 @@
     method public void listen(android.telephony.PhoneStateListener, int);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
diff --git a/cmds/locksettings/Android.mk b/cmds/locksettings/Android.mk
new file mode 100644
index 0000000..76766c7
--- /dev/null
+++ b/cmds/locksettings/Android.mk
@@ -0,0 +1,30 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := locksettings
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := locksettings
+LOCAL_SRC_FILES := locksettings
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
+
+
diff --git a/cmds/locksettings/locksettings b/cmds/locksettings/locksettings
new file mode 100755
index 0000000..c963b23
--- /dev/null
+++ b/cmds/locksettings/locksettings
@@ -0,0 +1,5 @@
+# Script to start "locksettings" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/locksettings.jar
+exec app_process $base/bin com.android.commands.locksettings.LockSettingsCmd "$@"
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
new file mode 100644
index 0000000..1e426d6
--- /dev/null
+++ b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
@@ -0,0 +1,65 @@
+/*
+ * 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.commands.locksettings;
+
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.ShellCallback;
+
+import com.android.internal.os.BaseCommand;
+import com.android.internal.widget.ILockSettings;
+
+import java.io.FileDescriptor;
+import java.io.PrintStream;
+
+public final class LockSettingsCmd extends BaseCommand {
+
+    private static final String USAGE =
+            "usage: locksettings set-pattern [--old OLD_CREDENTIAL] NEW_PATTERN\n" +
+            "       locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n" +
+            "       locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" +
+            "       locksettings clear [--old OLD_CREDENTIAL]\n" +
+            "\n" +
+            "locksettings set-pattern: sets a pattern\n" +
+            "    A pattern is specified by a non-separated list of numbers that index the cell\n" +
+            "    on the pattern in a 1-based manner in left to right and top to bottom order,\n" +
+            "    i.e. the top-left cell is indexed with 1, whereas the bottom-right cell\n" +
+            "    is indexed with 9. Example: 1234\n" +
+            "\n" +
+            "locksettings set-pin: sets a PIN\n" +
+            "\n" +
+            "locksettings set-password: sets a password\n" +
+            "\n" +
+            "locksettings clear: clears the unlock credential\n";
+
+    public static void main(String[] args) {
+        (new LockSettingsCmd()).run(args);
+    }
+
+    @Override
+    public void onShowUsage(PrintStream out) {
+        out.println(USAGE);
+    }
+
+    @Override
+    public void onRun() throws Exception {
+        ILockSettings lockSettings = ILockSettings.Stub.asInterface(
+                ServiceManager.getService("lock_settings"));
+        lockSettings.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out,
+                FileDescriptor.err, getRawArgs(), new ShellCallback(), new ResultReceiver(null) {});
+    }
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9af7d8b..df970a4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -91,33 +91,18 @@
 
     static final class UidObserver extends IUidObserver.Stub {
         final OnUidImportanceListener mListener;
-        final int mImportanceCutpoint;
-        int mLastImportance;
 
-        UidObserver(OnUidImportanceListener listener, int importanceCutpoint) {
+        UidObserver(OnUidImportanceListener listener) {
             mListener = listener;
-            mImportanceCutpoint = importanceCutpoint;
         }
 
         @Override
         public void onUidStateChanged(int uid, int procState) {
-            final boolean lastAboveCut = mLastImportance <= mImportanceCutpoint;
-            final int importance = RunningAppProcessInfo.procStateToImportance(procState);
-            final boolean newAboveCut = importance <= mImportanceCutpoint;
-            /*
-            Log.d(TAG, "Uid " + uid + " state change from " + mLastImportance + " to "
-                    + importance + " @ cut " + mImportanceCutpoint
-                    + ": lastAbove=" + lastAboveCut + " newAbove=" + newAboveCut);
-            */
-            mLastImportance = importance;
-            if (lastAboveCut != newAboveCut) {
-                mListener.onUidImportance(uid, importance);
-            }
+            mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportance(procState));
         }
 
         @Override
         public void onUidGone(int uid) {
-            mLastImportance = RunningAppProcessInfo.IMPORTANCE_GONE;
             mListener.onUidImportance(uid, RunningAppProcessInfo.IMPORTANCE_GONE);
         }
 
@@ -380,8 +365,8 @@
     /** @hide User operation call: one of related users cannot be stopped. */
     public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4;
 
-    /** @hide Process does not exist. */
-    public static final int PROCESS_STATE_NONEXISTENT = -1;
+    /** @hide Not a real process state. */
+    public static final int PROCESS_STATE_UNKNOWN = -1;
 
     /** @hide Process is a persistent system process. */
     public static final int PROCESS_STATE_PERSISTENT = 0;
@@ -442,11 +427,14 @@
     /** @hide Process is being cached for later use and is empty. */
     public static final int PROCESS_STATE_CACHED_EMPTY = 16;
 
+    /** @hide Process does not exist. */
+    public static final int PROCESS_STATE_NONEXISTENT = 17;
+
     /** @hide The lowest process state number */
-    public static final int MIN_PROCESS_STATE = PROCESS_STATE_NONEXISTENT;
+    public static final int MIN_PROCESS_STATE = PROCESS_STATE_PERSISTENT;
 
     /** @hide The highest process state number */
-    public static final int MAX_PROCESS_STATE = PROCESS_STATE_CACHED_EMPTY;
+    public static final int MAX_PROCESS_STATE = PROCESS_STATE_NONEXISTENT;
 
     /** @hide Should this process state be considered a background state? */
     public static final boolean isProcStateBackground(int procState) {
@@ -2890,6 +2878,29 @@
             }
         }
 
+        /** @hide */
+        public static int importanceToProcState(int importance) {
+            if (importance == IMPORTANCE_GONE) {
+                return PROCESS_STATE_NONEXISTENT;
+            } else if (importance >= IMPORTANCE_BACKGROUND) {
+                return PROCESS_STATE_HOME;
+            } else if (importance >= IMPORTANCE_SERVICE) {
+                return PROCESS_STATE_SERVICE;
+            } else if (importance > IMPORTANCE_CANT_SAVE_STATE) {
+                return PROCESS_STATE_HEAVY_WEIGHT;
+            } else if (importance >= IMPORTANCE_PERCEPTIBLE) {
+                return PROCESS_STATE_IMPORTANT_BACKGROUND;
+            } else if (importance >= IMPORTANCE_VISIBLE) {
+                return PROCESS_STATE_IMPORTANT_FOREGROUND;
+            } else if (importance >= IMPORTANCE_TOP_SLEEPING) {
+                return PROCESS_STATE_TOP_SLEEPING;
+            } else if (importance >= IMPORTANCE_FOREGROUND_SERVICE) {
+                return PROCESS_STATE_FOREGROUND_SERVICE;
+            } else {
+                return PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+            }
+        }
+
         /**
          * The relative importance level that the system places on this
          * process.  May be one of {@link #IMPORTANCE_FOREGROUND},
@@ -3146,10 +3157,12 @@
                 throw new IllegalArgumentException("Listener already registered: " + listener);
             }
             // TODO: implement the cut point in the system process to avoid IPCs.
-            UidObserver observer = new UidObserver(listener, importanceCutpoint);
+            UidObserver observer = new UidObserver(listener);
             try {
                 getService().registerUidObserver(observer,
-                        UID_OBSERVER_PROCSTATE | UID_OBSERVER_GONE, mContext.getOpPackageName());
+                        UID_OBSERVER_PROCSTATE | UID_OBSERVER_GONE,
+                        RunningAppProcessInfo.importanceToProcState(importanceCutpoint),
+                        mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -3587,7 +3600,7 @@
      * allowed to run code through scheduled alarms, receiving broadcasts,
      * etc.  A started user may be either the current foreground user or a
      * background user; the result here does not distinguish between the two.
-     * @param userid the user's id. Zero indicates the default user.
+     * @param userId the user's id. Zero indicates the default user.
      * @hide
      */
     public boolean isUserRunning(int userId) {
diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java
index ba79108..d8d7340 100644
--- a/core/java/android/app/EphemeralResolverService.java
+++ b/core/java/android/app/EphemeralResolverService.java
@@ -40,6 +40,7 @@
     public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
     public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
     private static final String EXTRA_PREFIX = "android.app.PREFIX";
+    private static final String EXTRA_HOSTNAME = "android.app.HOSTNAME";
     private Handler mHandler;
 
     /**
@@ -49,9 +50,29 @@
      * @param prefixMask A mask that was applied to each digest prefix. This should
      *      be used when comparing against the digest prefixes as all bits might
      *      not be set.
+     * @deprecated use {@link #onGetEphemeralResolveInfo(int[])} instead
      */
+    @Deprecated
     public abstract List<EphemeralResolveInfo> onEphemeralResolveInfoList(
-            int digestPrefix[], int prefixMask);
+            int digestPrefix[], int prefix);
+
+    /**
+     * Called to retrieve resolve info for ephemeral applications.
+     *
+     * @param digestPrefix The hash prefix of the ephemeral's domain.
+     */
+    public List<EphemeralResolveInfo> onGetEphemeralResolveInfo(int digestPrefix[]) {
+        return onEphemeralResolveInfoList(digestPrefix, 0xFFFFF000);
+    }
+
+    /**
+     * Called to retrieve intent filters for ephemeral applications.
+     *
+     * @param digestPrefix The hash prefix of the ephemeral's domain.
+     */
+    public List<EphemeralResolveInfo> onGetEphemeralIntentFilter(int digestPrefix[]) {
+        throw new IllegalStateException("Must define");
+    }
 
     @Override
     public final void attachBaseContext(Context base) {
@@ -64,9 +85,20 @@
         return new IEphemeralResolver.Stub() {
             @Override
             public void getEphemeralResolveInfoList(
-                    IRemoteCallback callback, int digestPrefix[], int prefixMask, int sequence) {
+                    IRemoteCallback callback, int digestPrefix[], int sequence) {
                 final Message msg = mHandler.obtainMessage(
-                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, prefixMask, sequence, callback);
+                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, sequence, 0, callback);
+                final Bundle data = new Bundle();
+                data.putIntArray(EXTRA_PREFIX, digestPrefix);
+                msg.setData(data);
+                msg.sendToTarget();
+            }
+
+            @Override
+            public void getEphemeralIntentFilterList(
+                    IRemoteCallback callback, int digestPrefix[], int sequence) {
+                final Message msg = mHandler.obtainMessage(
+                        ServiceHandler.MSG_GET_EPHEMERAL_INTENT_FILTER, sequence, 0, callback);
                 final Bundle data = new Bundle();
                 data.putIntArray(EXTRA_PREFIX, digestPrefix);
                 msg.setData(data);
@@ -77,6 +109,7 @@
 
     private final class ServiceHandler extends Handler {
         public static final int MSG_GET_EPHEMERAL_RESOLVE_INFO = 1;
+        public static final int MSG_GET_EPHEMERAL_INTENT_FILTER = 2;
 
         public ServiceHandler(Looper looper) {
             super(looper, null /*callback*/, true /*async*/);
@@ -91,9 +124,23 @@
                     final IRemoteCallback callback = (IRemoteCallback) message.obj;
                     final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
                     final List<EphemeralResolveInfo> resolveInfo =
-                            onEphemeralResolveInfoList(digestPrefix, message.arg1);
+                            onGetEphemeralResolveInfo(digestPrefix);
                     final Bundle data = new Bundle();
-                    data.putInt(EXTRA_SEQUENCE, message.arg2);
+                    data.putInt(EXTRA_SEQUENCE, message.arg1);
+                    data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
+                    try {
+                        callback.sendResult(data);
+                    } catch (RemoteException e) {
+                    }
+                } break;
+
+                case MSG_GET_EPHEMERAL_INTENT_FILTER: {
+                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
+                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
+                    final List<EphemeralResolveInfo> resolveInfo =
+                            onGetEphemeralIntentFilter(digestPrefix);
+                    final Bundle data = new Bundle();
+                    data.putInt(EXTRA_SEQUENCE, message.arg1);
                     data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
                     try {
                         callback.sendResult(data);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 92d67b7..80267205 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -431,7 +431,8 @@
      *              etc.
      */
     void keyguardGoingAway(int flags) = 296;
-    void registerUidObserver(in IUidObserver observer, int which, String callingPackage) = 297;
+    void registerUidObserver(in IUidObserver observer, int which, int cutpoint,
+            String callingPackage) = 297;
     void unregisterUidObserver(in IUidObserver observer) = 298;
     boolean isAssistDataAllowedOnCurrentActivity() = 299;
     boolean showAssistFromActivity(in IBinder token, in Bundle args) = 300;
diff --git a/core/java/android/app/IEphemeralResolver.aidl b/core/java/android/app/IEphemeralResolver.aidl
index ee869ea..e0cef83 100644
--- a/core/java/android/app/IEphemeralResolver.aidl
+++ b/core/java/android/app/IEphemeralResolver.aidl
@@ -21,5 +21,8 @@
 /** @hide */
 oneway interface IEphemeralResolver {
     void getEphemeralResolveInfoList(IRemoteCallback callback, in int[] digestPrefix,
-            int prefixMask, int sequence);
+            int sequence);
+
+    void getEphemeralIntentFilterList(IRemoteCallback callback, in int[] digestPrefix,
+            int sequence);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4eecd48..a9e987a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1713,6 +1713,16 @@
     public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
 
     /**
+     * Intent extra: An app split name.
+     * <p>
+     * Type: String
+     * </p>
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
+
+    /**
      * Intent extra: An extra for specifying whether a result is needed.
      * <p>
      * Type: boolean
@@ -3120,10 +3130,11 @@
      * URIs that can be opened with
      * {@link ContentResolver#openFileDescriptor(Uri, String)}.
      * <p>
-     * Callers can set a document URI through {@link #setData(Uri)} to indicate
-     * the initial location of documents navigator. System will do its best to
-     * launch the navigator in the specified document if it's a folder, or the
-     * folder that contains the specified document if not.
+     * Callers can set a document URI through
+     * {@link DocumentsContract#EXTRA_INITIAL_URI} to indicate the initial
+     * location of documents navigator. System will do its best to launch the
+     * navigator in the specified document if it's a folder, or the folder that
+     * contains the specified document if not.
      * <p>
      * Output: The URI of the item that was picked, returned in
      * {@link #getData()}. This must be a {@code content://} URI so that any
@@ -3161,10 +3172,11 @@
      * URIs that can be opened with
      * {@link ContentResolver#openFileDescriptor(Uri, String)}.
      * <p>
-     * Callers can set a document URI through {@link #setData(Uri)} to indicate
-     * the initial location of documents navigator. System will do its best to
-     * launch the navigator in the specified document if it's a folder, or the
-     * folder that contains the specified document if not.
+     * Callers can set a document URI through
+     * {@link DocumentsContract#EXTRA_INITIAL_URI} to indicate the initial
+     * location of documents navigator. System will do its best to launch the
+     * navigator in the specified document if it's a folder, or the folder that
+     * contains the specified document if not.
      * <p>
      * Output: The URI of the item that was created. This must be a
      * {@code content://} URI so that any receiver can access it.
@@ -3188,10 +3200,11 @@
      * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)}
      * with the returned URI.
      * <p>
-     * Callers can set a document URI through {@link #setData(Uri)} to indicate
-     * the initial location of documents navigator. System will do its best to
-     * initiate the navigator in the specified document if it's a folder, or
-     * the folder that contains the specified document if not.
+     * Callers can set a document URI through
+     * {@link DocumentsContract#EXTRA_INITIAL_URI} to indicate the initial
+     * location of documents navigator. System will do its best to launch the
+     * navigator in the specified document if it's a folder, or the folder that
+     * contains the specified document if not.
      * <p>
      * Output: The URI representing the selected directory tree.
      *
diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java
new file mode 100644
index 0000000..0674e7c
--- /dev/null
+++ b/core/java/android/content/pm/EphemeralIntentFilter.java
@@ -0,0 +1,96 @@
+/*
+ * 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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Information about an ephemeral application intent filter.
+ * @hide
+ */
+@SystemApi
+public final class EphemeralIntentFilter implements Parcelable {
+    private final String mSplitName;
+    /** The filters used to match domain */
+    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+
+    public EphemeralIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
+        if (filters == null || filters.size() == 0) {
+            throw new IllegalArgumentException();
+        }
+        mSplitName = splitName;
+        mFilters.addAll(filters);
+    }
+
+    EphemeralIntentFilter(Parcel in) {
+        mSplitName = in.readString();
+        in.readList(mFilters, null /*loader*/);
+    }
+
+    public String getSplitName() {
+        return mSplitName;
+    }
+
+    public List<IntentFilter> getFilters() {
+        return mFilters;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mSplitName);
+        out.writeList(mFilters);
+    }
+
+    public static final Parcelable.Creator<EphemeralIntentFilter> CREATOR
+            = new Parcelable.Creator<EphemeralIntentFilter>() {
+        public EphemeralIntentFilter createFromParcel(Parcel in) {
+            return new EphemeralIntentFilter(in);
+        }
+
+        public EphemeralIntentFilter[] newArray(int size) {
+            return new EphemeralIntentFilter[size];
+        }
+    };
+
+    /** @hide */
+    public static final class EphemeralResolveIntentInfo extends IntentFilter {
+        private final EphemeralIntentFilter mResolveInfo;
+
+        public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
+                @NonNull EphemeralIntentFilter resolveInfo) {
+            super(orig);
+            this.mResolveInfo = resolveInfo;
+        }
+
+        public EphemeralIntentFilter getEphemeralResolveInfo() {
+            return mResolveInfo;
+        }
+    }
+}
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
index fc3b958..3bed06b 100644
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.IntentFilter;
 import android.net.Uri;
@@ -41,27 +42,54 @@
     private final EphemeralDigest mDigest;
     private final String mPackageName;
     /** The filters used to match domain */
-    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+    private final List<EphemeralIntentFilter> mFilters;
+    /** Filters only for legacy clients */
+    @Deprecated
+    private List<IntentFilter> mLegacyFilters;
 
+    @Deprecated
     public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName,
             @NonNull List<IntentFilter> filters) {
-        // validate arguments
-        if (uri == null
-                || packageName == null
-                || filters == null
-                || filters.size() == 0) {
+        if (uri == null || packageName == null || filters == null || filters.isEmpty()) {
             throw new IllegalArgumentException();
         }
-
-        mDigest = new EphemeralDigest(uri, 0xFFFFFFFF, -1);
-        mFilters.addAll(filters);
+        mDigest = new EphemeralDigest(uri.getHost());
         mPackageName = packageName;
+        mFilters = new ArrayList<EphemeralIntentFilter>();
+        mFilters.add(new EphemeralIntentFilter(packageName, filters));
+        mLegacyFilters = new ArrayList<IntentFilter>(filters.size());
+        mLegacyFilters.addAll(filters);
+    }
+
+    public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
+            @Nullable List<EphemeralIntentFilter> filters) {
+        // validate arguments
+        if ((packageName == null && (filters != null && filters.size() != 0))
+                || (packageName != null && (filters == null || filters.size() == 0))) {
+            throw new IllegalArgumentException();
+        }
+        mDigest = digest;
+        if (filters != null) {
+            mFilters = new ArrayList<EphemeralIntentFilter>(filters.size());
+            mFilters.addAll(filters);
+        } else {
+            mFilters = null;
+        }
+        mPackageName = packageName;
+    }
+
+    public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName,
+            @Nullable List<EphemeralIntentFilter> filters) {
+        this(new EphemeralDigest(hostName), packageName, filters);
     }
 
     EphemeralResolveInfo(Parcel in) {
         mDigest = in.readParcelable(null /*loader*/);
         mPackageName = in.readString();
+        mFilters = new ArrayList<EphemeralIntentFilter>();
         in.readList(mFilters, null /*loader*/);
+        mLegacyFilters = new ArrayList<IntentFilter>();
+        in.readList(mLegacyFilters, null /*loader*/);
     }
 
     public byte[] getDigestBytes() {
@@ -76,7 +104,12 @@
         return mPackageName;
     }
 
+    @Deprecated
     public List<IntentFilter> getFilters() {
+        return mLegacyFilters;
+    }
+
+    public List<EphemeralIntentFilter> getIntentFilters() {
         return mFilters;
     }
 
@@ -90,6 +123,7 @@
         out.writeParcelable(mDigest, flags);
         out.writeString(mPackageName);
         out.writeList(mFilters);
+        out.writeList(mLegacyFilters);
     }
 
     public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
@@ -106,16 +140,23 @@
     /** @hide */
     public static final class EphemeralResolveIntentInfo extends IntentFilter {
         private final EphemeralResolveInfo mResolveInfo;
+        private final String mSplitName;
 
         public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
-                @NonNull EphemeralResolveInfo resolveInfo) {
+                @NonNull EphemeralResolveInfo resolveInfo,
+                @Nullable String splitName) {
             super(orig);
-            this.mResolveInfo = resolveInfo;
+            mResolveInfo = resolveInfo;
+            mSplitName = splitName;
         }
 
         public EphemeralResolveInfo getEphemeralResolveInfo() {
             return mResolveInfo;
         }
+
+        public String getSplitName() {
+            return mSplitName;
+        }
     }
 
     /**
@@ -129,17 +170,25 @@
      *
      * @hide
      */
+    @SystemApi
     public static final class EphemeralDigest implements Parcelable {
+        private static final int DIGEST_MASK = 0xfffff000;
+        private static final int DIGEST_PREFIX_COUNT = 5;
         /** Full digest of the domain hashes */
         private final byte[][] mDigestBytes;
         /** The first 4 bytes of the domain hashes */
         private final int[] mDigestPrefix;
 
-        public EphemeralDigest(@NonNull Uri uri, int digestMask, int maxDigests) {
-            if (uri == null) {
+        public EphemeralDigest(@NonNull String hostName) {
+            this(hostName, -1 /*maxDigests*/);
+        }
+
+        /** @hide */
+        public EphemeralDigest(@NonNull String hostName, int maxDigests) {
+            if (hostName == null) {
                 throw new IllegalArgumentException();
             }
-            mDigestBytes = generateDigest(uri, maxDigests);
+            mDigestBytes = generateDigest(hostName.toLowerCase(Locale.ENGLISH), maxDigests);
             mDigestPrefix = new int[mDigestBytes.length];
             for (int i = 0; i < mDigestBytes.length; i++) {
                 mDigestPrefix[i] =
@@ -147,31 +196,32 @@
                                 | (mDigestBytes[i][1] & 0xFF) << 16
                                 | (mDigestBytes[i][2] & 0xFF) << 8
                                 | (mDigestBytes[i][3] & 0xFF) << 0)
-                        & digestMask;
+                        & DIGEST_MASK;
             }
         }
 
-        private static byte[][] generateDigest(Uri uri, int maxDigests) {
+        private static byte[][] generateDigest(String hostName, int maxDigests) {
             ArrayList<byte[]> digests = new ArrayList<>();
             try {
-                final String host = uri.getHost().toLowerCase(Locale.ENGLISH);
                 final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
                 if (maxDigests <= 0) {
-                    final byte[] hostBytes = host.getBytes();
+                    final byte[] hostBytes = hostName.getBytes();
                     digests.add(digest.digest(hostBytes));
                 } else {
-                    int prevDot = host.lastIndexOf('.');
-                    prevDot = host.lastIndexOf('.', prevDot - 1);
+                    int prevDot = hostName.lastIndexOf('.');
+                    prevDot = hostName.lastIndexOf('.', prevDot - 1);
                     // shortcut for short URLs
                     if (prevDot < 0) {
-                        digests.add(digest.digest(host.getBytes()));
+                        digests.add(digest.digest(hostName.getBytes()));
                     } else {
-                        byte[] hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
+                        byte[] hostBytes =
+                                hostName.substring(prevDot + 1, hostName.length()).getBytes();
                         digests.add(digest.digest(hostBytes));
                         int digestCount = 1;
                         while (prevDot >= 0 && digestCount < maxDigests) {
-                            prevDot = host.lastIndexOf('.', prevDot - 1);
-                            hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
+                            prevDot = hostName.lastIndexOf('.', prevDot - 1);
+                            hostBytes =
+                                    hostName.substring(prevDot + 1, hostName.length()).getBytes();
                             digests.add(digest.digest(hostBytes));
                             digestCount++;
                         }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index b5df4d7..86dbe8a 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.IntentFilter;
+import android.content.pm.EphemeralResolveInfo.EphemeralResolveIntentInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -65,7 +66,7 @@
      * only be set in specific circumstances.
      * @hide
      */
-    public EphemeralResolveInfo ephemeralResolveInfo;
+    public EphemeralResolveIntentInfo ephemeralIntentInfo;
 
     /**
      * The IntentFilter that was matched for this ResolveInfo.
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 8233ad2..c46fe29 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -553,6 +553,7 @@
             if (!mPreloading && useCache) {
                 final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
                 if (cachedDrawable != null) {
+                    cachedDrawable.setChangingConfigurations(value.changingConfigurations);
                     return cachedDrawable;
                 }
             }
@@ -588,9 +589,11 @@
             // If we were able to obtain a drawable, store it in the appropriate
             // cache: preload, not themed, null theme, or theme-specific. Don't
             // pollute the cache with drawables loaded from a foreign density.
-            if (dr != null && useCache) {
+            if (dr != null) {
                 dr.setChangingConfigurations(value.changingConfigurations);
-                cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+                if (useCache) {
+                    cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+                }
             }
 
             return dr;
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index a5b4eb5..e0a026e 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -38,9 +38,15 @@
     public static final int PROVISIONING_OK    = 1;
     public static final int PROVISIONING_FAIL  = 2;
     public static final int COMPLETE_LIFECYCLE = 3;
+    /** @hide */ public static final int ERROR_STARTING_IPV4 = 4;
+    /** @hide */ public static final int ERROR_STARTING_IPV6 = 5;
+    /** @hide */ public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6;
 
     /** {@hide} */
-    @IntDef(value = {PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE})
+    @IntDef(value = {
+            PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
+            ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
 
@@ -95,6 +101,7 @@
 
     final static class Decoder {
         static final SparseArray<String> constants = MessageUtils.findMessageNames(
-                new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"});
+                new Class[]{IpManagerEvent.class},
+                new String[]{"PROVISIONING_", "COMPLETE_", "ERROR_"});
     }
 }
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 0e7da63..481b2dc 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import java.util.ArrayList;
 import libcore.util.NativeAllocationRegistry;
 
 /** @hide */
@@ -39,10 +40,12 @@
             int code, HwParcel request, HwParcel reply, int flags);
 
     public native final void registerService(
-            String serviceName, int versionMajor, int versionMinor);
+            ArrayList<String> interfaceChain,
+            String serviceName);
 
     public static native final IHwBinder getService(
-            String serviceName, int versionMajor, int versionMinor);
+            String iface,
+            String serviceName);
 
     // Returns address of the "freeFunction".
     private static native final long native_init();
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 3546e17..819afb4 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -77,6 +77,7 @@
     public boolean register(E callback) {
         return register(callback, null);
     }
+
     /**
      * Add a new callback to the list.  This callback will remain in the list
      * until a corresponding call to {@link #unregister} or its hosting process
@@ -326,4 +327,27 @@
             return mCallbacks.size();
         }
     }
+
+    /**
+     * Return the cookies associated with a currently registered callback.  Note that this is
+     * <em>not</em> the same as {@link #getBroadcastCookie} and should not be used
+     * interchangeably with it.  This method returns the current cookied registered at the given
+     * index, not the current broadcast state.  This means that it is not itself thread-safe:
+     * any call to {@link #register} or {@link #unregister} will change these indices, so you
+     * must do your own thread safety between these to protect from such changes.
+     *
+     * @param index Index of which registration cookie to return from 0 to
+     * {@link #getRegisteredCallbackCount()}.
+     *
+     * @return Returns whatever cookie object is associated with this index, or null if
+     * {@link #kill()} has been called.
+     */
+    public Object getRegisteredCallbackCookie(int index) {
+        synchronized (mCallbacks) {
+            if (mKilled) {
+                return null;
+            }
+            return mCallbacks.valueAt(index).mCookie;
+        }
+    }
 }
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 2dcf220..f86193f 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -106,6 +106,22 @@
     public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
 
     /**
+     * Sets the desired initial location visible to user when file chooser is shown.
+     *
+     * <p>Applicable to {@link Intent} with actions:
+     * <ul>
+     *      <li>{@link Intent#ACTION_OPEN_DOCUMENT}</li>
+     *      <li>{@link Intent#ACTION_CREATE_DOCUMENT}</li>
+     *      <li>{@link Intent#ACTION_OPEN_DOCUMENT_TREE}</li>
+     * </ul>
+     *
+     * <p>Location should specify a document URI or a tree URI with document ID. If
+     * this URI identifies a non-directory, document navigator will attempt to use the parent
+     * of the document as the initial location.
+     */
+    public static final String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
+
+    /**
      * Set this in a DocumentsUI intent to cause a package's own roots to be
      * excluded from the roots list.
      */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1b905a0..22336c6 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8956,24 +8956,6 @@
         public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature";
 
         /**
-         * A mask applied to the ephemeral hash to generate the hash prefix.
-         * <p>
-         * Type: int
-         *
-         * @hide
-         */
-        public static final String EPHEMERAL_HASH_PREFIX_MASK = "ephemeral_hash_prefix_mask";
-
-        /**
-         * Number of hash prefixes to send during ephemeral resolution.
-         * <p>
-         * Type: int
-         *
-         * @hide
-         */
-        public static final String EPHEMERAL_HASH_PREFIX_COUNT = "ephemeral_hash_prefix_count";
-
-        /**
          * The duration for caching uninstalled ephemeral apps.
          * <p>
          * Type: long
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5a6cf7d..cdd8b6a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5611,6 +5611,13 @@
         }
     }
 
+    /**
+     * Notify that the window title changed
+     */
+    public void onWindowTitleChanged() {
+        mAttachInfo.mForceReportNewAttributes = true;
+    }
+
     public void handleDispatchWindowShown() {
         mAttachInfo.mTreeObserver.dispatchOnWindowShown();
     }
diff --git a/core/java/com/android/internal/os/AppFuseMount.java b/core/java/com/android/internal/os/AppFuseMount.java
new file mode 100644
index 0000000..b392186
--- /dev/null
+++ b/core/java/com/android/internal/os/AppFuseMount.java
@@ -0,0 +1,56 @@
+/*
+ * 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.os;
+
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import java.io.File;
+
+public class AppFuseMount implements Parcelable {
+    final public File mountPoint;
+    final public ParcelFileDescriptor fd;
+
+    public AppFuseMount(File mountPoint, ParcelFileDescriptor fd) {
+        this.mountPoint = mountPoint;
+        this.fd = fd;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(this.mountPoint.getPath());
+        dest.writeParcelable(fd, flags);
+    }
+
+    public static final Parcelable.Creator<AppFuseMount> CREATOR =
+            new Parcelable.Creator<AppFuseMount>() {
+        @Override
+        public AppFuseMount createFromParcel(Parcel in) {
+            return new AppFuseMount(new File(in.readString()), in.readParcelable(null));
+        }
+
+        @Override
+        public AppFuseMount[] newArray(int size) {
+            return new AppFuseMount[size];
+        }
+    };
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 878f3a6..50621f4 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -540,6 +540,13 @@
             WindowManager.LayoutParams params = getAttributes();
             if (!TextUtils.equals(title, params.accessibilityTitle)) {
                 params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
+                if (mDecor != null) {
+                    // ViewRootImpl will make sure the change propagates to WindowManagerService
+                    ViewRootImpl vr = mDecor.getViewRootImpl();
+                    if (vr != null) {
+                        vr.onWindowTitleChanged();
+                    }
+                }
                 dispatchWindowAttributesChanged(getAttributes());
             }
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 91e8310..f5429a1 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -211,6 +211,7 @@
     external/skia/include/private \
     external/skia/src/core \
     external/skia/src/effects \
+    external/skia/src/image \
     external/skia/src/images \
     external/sqlite/dist \
     external/sqlite/android \
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 657b1ef..0de46e6 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -95,15 +95,13 @@
         // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
         GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     }
-    sk_sp<SkShader> s = SkMakeBitmapShader(bitmap,
-                                           (SkShader::TileMode)tileModeX,
-                                           (SkShader::TileMode)tileModeY,
-                                           nullptr,
-                                           kNever_SkCopyPixelsMode,
-                                           nullptr);
 
-    ThrowIAE_IfNull(env, s.get());
-    return reinterpret_cast<jlong>(s.release());
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    sk_sp<SkShader> shader = image->makeShader((SkShader::TileMode)tileModeX,
+                                               (SkShader::TileMode)tileModeY);
+
+    ThrowIAE_IfNull(env, shader.get());
+    return reinterpret_cast<jlong>(shader.release());
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 1a33d91..10090a1 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -34,6 +34,8 @@
 #include "core_jni_helpers.h"
 
 using android::AndroidRuntime;
+using android::hardware::hidl_vec;
+using android::hardware::hidl_string;
 
 #define PACKAGE_PATH    "android/os"
 #define CLASS_NAME      "HwBinder"
@@ -41,10 +43,15 @@
 
 namespace android {
 
+static jclass gArrayListClass;
+static struct {
+    jmethodID size;
+    jmethodID get;
+} gArrayListMethods;
+
 static struct fields_t {
     jfieldID contextID;
     jmethodID onTransactID;
-
 } gFields;
 
 // static
@@ -199,45 +206,46 @@
 static void JHwBinder_native_registerService(
         JNIEnv *env,
         jobject thiz,
-        jstring serviceNameObj,
-        jint versionMajor,
-        jint versionMinor) {
+        jobject interfaceChainArrayList,
+        jstring serviceNameObj) {
     if (serviceNameObj == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", NULL);
         return;
     }
 
-    if (versionMajor < 0
-            || versionMajor > 65535
-            || versionMinor < 0
-            || versionMinor > 65535) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-
-    const jchar *serviceName = env->GetStringCritical(serviceNameObj, NULL);
-
+    const char *serviceName = env->GetStringUTFChars(serviceNameObj, NULL);
     if (serviceName == NULL) {
         return;  // XXX exception already pending?
     }
 
-    using android::hidl::manager::V1_0::IServiceManager;
+    jint numInterfaces = env->CallIntMethod(interfaceChainArrayList,
+                                            gArrayListMethods.size);
+    hidl_string *strings = new hidl_string[numInterfaces];
 
-    const IServiceManager::Version kVersion {
-        .major = static_cast<uint16_t>(versionMajor),
-        .minor = static_cast<uint16_t>(versionMinor),
-    };
+    for (jint i = 0; i < numInterfaces; i++) {
+        jstring strObj = static_cast<jstring>(
+            env->CallObjectMethod(interfaceChainArrayList,
+                                  gArrayListMethods.get,
+                                  i)
+        );
+        const char * str = env->GetStringUTFChars(strObj, nullptr);
+        strings[i] = hidl_string(str);
+        env->ReleaseStringUTFChars(strObj, str);
+    }
+
+    hidl_vec<hidl_string> interfaceChain;
+    interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
+
+    using android::hidl::manager::V1_0::IServiceManager;
 
     sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
 
     bool ok = hardware::defaultServiceManager()->add(
-                String8(String16(
-                          reinterpret_cast<const char16_t *>(serviceName),
-                          env->GetStringLength(serviceNameObj))).string(),
-                binder,
-                kVersion);
+                interfaceChain,
+                serviceName,
+                binder);
 
-    env->ReleaseStringCritical(serviceNameObj, serviceName);
+    env->ReleaseStringUTFChars(serviceNameObj, serviceName);
     serviceName = NULL;
 
     if (ok) {
@@ -251,52 +259,43 @@
 static jobject JHwBinder_native_getService(
         JNIEnv *env,
         jclass /* clazzObj */,
-        jstring serviceNameObj,
-        jint versionMajor,
-        jint versionMinor) {
+        jstring ifaceNameObj,
+        jstring serviceNameObj) {
+
+    if (ifaceNameObj == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        return NULL;
+    }
     if (serviceNameObj == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", NULL);
         return NULL;
     }
 
-    if (versionMajor < 0
-            || versionMajor > 65535
-            || versionMinor < 0
-            || versionMinor > 65535) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return NULL;
+    const char *ifaceName = env->GetStringUTFChars(ifaceNameObj, NULL);
+    if (ifaceName == NULL) {
+        return NULL; // XXX exception already pending?
     }
-
-    const jchar *serviceName = env->GetStringCritical(serviceNameObj, NULL);
-
+    const char *serviceName = env->GetStringUTFChars(serviceNameObj, NULL);
     if (serviceName == NULL) {
-        return NULL;  // XXX exception already pending?
+        env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
+        return NULL; // XXX exception already pending?
     }
 
-    using android::hidl::manager::V1_0::IServiceManager;
-
-    const IServiceManager::Version kVersion {
-        .major = static_cast<uint16_t>(versionMajor),
-        .minor = static_cast<uint16_t>(versionMinor),
-    };
-
     LOG(INFO) << "looking for service '"
-              << String8(String16(
-                          reinterpret_cast<const char16_t *>(serviceName),
-                          env->GetStringLength(serviceNameObj))).string()
+              << serviceName
               << "'";
 
     sp<hardware::IBinder> service;
     hardware::defaultServiceManager()->get(
-            String8(String16(
-                      reinterpret_cast<const char16_t *>(serviceName),
-                      env->GetStringLength(serviceNameObj))).string(),
-            kVersion,
+            ifaceName,
+            serviceName,
             [&service](sp<hardware::IBinder> out) {
                 service = out;
             });
 
-    env->ReleaseStringCritical(serviceNameObj, serviceName);
+    env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
+    ifaceName = NULL;
+    env->ReleaseStringUTFChars(serviceNameObj, serviceName);
     serviceName = NULL;
 
     if (service == NULL) {
@@ -318,16 +317,21 @@
         "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
         (void *)JHwBinder_native_transact },
 
-    { "registerService", "(Ljava/lang/String;II)V",
+    { "registerService", "(Ljava/util/ArrayList;Ljava/lang/String;)V",
         (void *)JHwBinder_native_registerService },
 
-    { "getService", "(Ljava/lang/String;II)L" PACKAGE_PATH "/IHwBinder;",
+    { "getService", "(Ljava/lang/String;Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
         (void *)JHwBinder_native_getService },
 };
 
 namespace android {
 
 int register_android_os_HwBinder(JNIEnv *env) {
+    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
+    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+    gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
+    gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
+
     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a58bc90..d70fbb9 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -178,7 +178,11 @@
                 // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
                 // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
                 char subdir[PROP_VALUE_MAX];
-                int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
+                int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PERSIST_PROPERTY,
+                        subdir);
+                if (len == 0) {
+                    len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
+                }
                 if (len > 0) {
                     String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
                     if (stat(overlayPath.string(), &st) == 0) {
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
index b78b8ff..2babe44 100644
--- a/core/jni/fd_utils-inl.h
+++ b/core/jni/fd_utils-inl.h
@@ -260,11 +260,11 @@
     }
 
     // Whitelist files needed for Runtime Resource Overlay, like these:
-    // /system/vendor/overlay/framework-res.apk
-    // /system/vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
+    // /vendor/overlay/framework-res.apk
+    // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
     // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
     // /data/resource-cache/system@vendor@overlay@PG@framework-res.apk@idmap
-    static const char* kOverlayDir = "/system/vendor/overlay/";
+    static const char* kOverlayDir = "/vendor/overlay/";
     static const char* kApkSuffix = ".apk";
 
     if (android::base::StartsWith(path, kOverlayDir)
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c3967e4..2d61e6e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8335,4 +8335,15 @@
     <declare-styleable name="ShortcutCategories">
         <attr name="name" />
     </declare-styleable>
+
+    <!-- Attributes that are read when parsing a <font> tag, which is a child of
+         <font-family>. -->
+    <declare-styleable name="FontFamilyFont">
+        <attr name="fontStyle">
+            <enum name="normal" value="0" />
+            <enum name="italic" value="1" />
+        </attr>
+        <attr name="font" format="reference" />
+        <attr name="fontWeight" format="integer" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ff1d383..d207c2b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2238,6 +2238,9 @@
          provisioning, availability etc -->
     <bool name="config_carrier_wfc_ims_available">false</bool>
 
+    <!-- Whether to use voip audio mode for ims call -->
+    <bool name="config_use_voip_mode_for_ims">false</bool>
+
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
     <string-array translatable="false" name="config_cdma_home_system" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c06a93d..ed68582 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2756,6 +2756,9 @@
     <eat-comment />
 
     <public-group type="attr" first-id="0x01010531">
+        <public name="fontStyle" />
+        <public name="font" />
+        <public name="fontWeight" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 92fff65..07c4c69 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2228,6 +2228,7 @@
   <java-symbol type="bool" name="config_carrier_vt_available" />
   <java-symbol type="bool" name="config_device_wfc_ims_available" />
   <java-symbol type="bool" name="config_carrier_wfc_ims_available" />
+  <java-symbol type="bool" name="config_use_voip_mode_for_ims" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
   <java-symbol type="string" name="whichApplicationNamed" />
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index ae789d6..e068900 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,6 +74,7 @@
 const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
 const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
+const char* AssetManager::OVERLAY_THEME_DIR_PERSIST_PROPERTY = "persist.vendor.overlay.theme";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
 const char* AssetManager::IDMAP_DIR = "/data/resource-cache";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index 0441b9d..becd307 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -66,6 +66,11 @@
      * OVERLAY_DIR.
      */
     static const char* OVERLAY_THEME_DIR_PROPERTY;
+    /**
+     * If OVERLAY_THEME_DIR_PERSIST_PROPERTY, use it to override
+     * OVERLAY_THEME_DIR_PROPERTY.
+     */
+    static const char* OVERLAY_THEME_DIR_PERSIST_PROPERTY;
     static const char* TARGET_PACKAGE_NAME;
     static const char* TARGET_APK_PATH;
     static const char* IDMAP_DIR;
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 9b217fb..8d4271f 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -31,6 +31,7 @@
     libutils \
     libbinder \
     libmedia \
+    libmediadrm \
     libskia \
     libui \
     liblog \
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 56aabb5..de7def6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -668,10 +668,16 @@
     @Override
     public boolean onLongClick(View v) {
         SystemServicesProxy ssp = Recents.getSystemServices();
-        // Since we are clipping the view to the bounds, manually do the hit test
+        boolean inBounds = false;
         Rect clipBounds = new Rect(mViewBounds.mClipBounds);
-        clipBounds.scale(getScaleX());
-        boolean inBounds = clipBounds.contains(mDownTouchPos.x, mDownTouchPos.y);
+        if (!clipBounds.isEmpty()) {
+            // If we are clipping the view to the bounds, manually do the hit test.
+            clipBounds.scale(getScaleX());
+            inBounds = clipBounds.contains(mDownTouchPos.x, mDownTouchPos.y);
+        } else {
+            // Otherwise just make sure we're within the view's bounds.
+            inBounds = mDownTouchPos.x <= getWidth() && mDownTouchPos.y <= getHeight();
+        }
         if (v == this && inBounds && !ssp.hasDockedTask()) {
             // Start listening for drag events
             setClipViewInStack(false);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8e01e9e..82897fb 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -938,7 +938,7 @@
 
         try {
             ActivityManagerNative.getDefault().registerUidObserver(new UidObserver(),
-                    ActivityManager.UID_OBSERVER_IDLE, null);
+                    ActivityManager.UID_OBSERVER_IDLE, ActivityManager.PROCESS_STATE_UNKNOWN, null);
         } catch (RemoteException e) {
             // ignored; both services live in system_server
         }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index a2207b2..dd342c5 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -49,6 +49,8 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.os.ServiceManager;
@@ -79,6 +81,7 @@
 import libcore.util.HexEncoding;
 
 import java.io.ByteArrayOutputStream;
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -1585,6 +1588,31 @@
         return mStrongAuthTracker.getStrongAuthForUser(userId);
     }
 
+    private boolean isCallerShell() {
+        final int callingUid = Binder.getCallingUid();
+        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+    }
+
+    private void enforceShell() {
+        if (!isCallerShell()) {
+            throw new SecurityException("Caller must be shell");
+        }
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
+            throws RemoteException {
+        enforceShell();
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
+                    this, in, out, err, args, callback, resultReceiver);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
     private static final String[] VALID_SETTINGS = new String[] {
         LockPatternUtils.LOCKOUT_PERMANENT_KEY,
         LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
diff --git a/services/core/java/com/android/server/LockSettingsShellCommand.java b/services/core/java/com/android/server/LockSettingsShellCommand.java
new file mode 100644
index 0000000..0efdd51
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsShellCommand.java
@@ -0,0 +1,143 @@
+/*
+ * 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.server;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static com.android.internal.widget.LockPatternUtils.stringToPattern;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
+
+class LockSettingsShellCommand extends ShellCommand {
+
+    private static final String COMMAND_SET_PATTERN = "set-pattern";
+    private static final String COMMAND_SET_PIN = "set-pin";
+    private static final String COMMAND_SET_PASSWORD = "set-password";
+    private static final String COMMAND_CLEAR = "clear";
+
+    private int mCurrentUserId;
+    private final LockPatternUtils mLockPatternUtils;
+    private final Context mContext;
+    private String mOld = "";
+    private String mNew = "";
+
+    LockSettingsShellCommand(Context context, LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mLockPatternUtils = lockPatternUtils;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        try {
+            mCurrentUserId = ActivityManagerNative.getDefault().getCurrentUser().id;
+
+            parseArgs();
+            if (!checkCredential()) {
+                return -1;
+            }
+            switch (cmd) {
+                case COMMAND_SET_PATTERN:
+                    runSetPattern();
+                    break;
+                case COMMAND_SET_PASSWORD:
+                    runSetPassword();
+                    break;
+                case COMMAND_SET_PIN:
+                    runSetPin();
+                    break;
+                case COMMAND_CLEAR:
+                    runClear();
+                    break;
+                default:
+                    getErrPrintWriter().println("Unknown command: " + cmd);
+                    break;
+            }
+            return 0;
+        } catch (Exception e) {
+            getErrPrintWriter().println("Error while executing command: " + e);
+            return -1;
+        }
+    }
+
+    @Override
+    public void onHelp() {
+    }
+
+    private void parseArgs() {
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("--old".equals(opt)) {
+                mOld = getNextArgRequired();
+            } else {
+                getErrPrintWriter().println("Unknown option: " + opt);
+                throw new IllegalArgumentException();
+            }
+        }
+        mNew = getNextArg();
+    }
+
+    private void runSetPattern() throws RemoteException {
+        mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
+        getOutPrintWriter().println("Pattern set to '" + mNew + "'");
+    }
+
+    private void runSetPassword() throws RemoteException {
+        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
+        getOutPrintWriter().println("Password set to '" + mNew + "'");
+    }
+
+    private void runSetPin() throws RemoteException {
+        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
+        getOutPrintWriter().println("Pin set to '" + mNew + "'");
+    }
+
+    private void runClear() throws RemoteException {
+        mLockPatternUtils.clearLock(mCurrentUserId);
+        getOutPrintWriter().println("Lock credential cleared");
+    }
+
+    private boolean checkCredential() throws RemoteException, RequestThrottledException {
+        final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
+        final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
+        if (havePassword || havePattern) {
+            boolean result;
+            if (havePassword) {
+                result = mLockPatternUtils.checkPassword(mOld, mCurrentUserId);
+            } else {
+                result = mLockPatternUtils.checkPattern(stringToPattern(mOld),
+                        mCurrentUserId);
+            }
+            if (result) {
+                return true;
+            } else {
+                getOutPrintWriter().println("Old password '" + mOld + "' didn't match");
+                return false;
+            }
+        } else {
+            return true;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 356ccb3..fa5a52c 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -63,7 +63,7 @@
 
     private BinderService mBinderService;
 
-    private final long MAX_CAMERA_PIN_SIZE = 50 * (1 << 20); //50MB max
+    private final long MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
 
     private PinnerHandler mPinnerHandler = null;
 
@@ -192,6 +192,9 @@
 
         if (isResolverActivity(cameraResolveInfo.activityInfo))
         {
+            if (DEBUG) {
+              Slog.v(TAG, "cameraIntent returned resolverActivity");
+            }
             return null;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2d6832d..42d16fb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,9 +22,6 @@
 import android.app.IActivityManager;
 import android.app.WaitResult;
 import android.os.IDeviceIdentifiersPolicyService;
-import android.util.Size;
-import android.util.TypedValue;
-import android.view.DisplayInfo;
 import com.android.internal.telephony.TelephonyIntents;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -80,7 +77,6 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.StackInfo;
-import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityManager.TaskThumbnailInfo;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerInternal.SleepToken;
@@ -221,6 +217,7 @@
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import android.util.Xml;
 import android.view.Gravity;
@@ -1398,6 +1395,27 @@
         boolean foregroundActivities;
     }
 
+    static final class UidObserverRegistration {
+        final int uid;
+        final String pkg;
+        final int which;
+        final int cutpoint;
+
+        final SparseIntArray lastProcStates;
+
+        UidObserverRegistration(int _uid, String _pkg, int _which, int _cutpoint) {
+            uid = _uid;
+            pkg = _pkg;
+            which = _which;
+            cutpoint = _cutpoint;
+            if (cutpoint >= ActivityManager.MIN_PROCESS_STATE) {
+                lastProcStates = new SparseIntArray();
+            } else {
+                lastProcStates = null;
+            }
+        }
+    }
+
     final RemoteCallbackList<IProcessObserver> mProcessObservers = new RemoteCallbackList<>();
     ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
 
@@ -4105,7 +4123,8 @@
         while (i > 0) {
             i--;
             final IUidObserver observer = mUidObservers.getBroadcastItem(i);
-            final int which = (Integer)mUidObservers.getBroadcastCookie(i);
+            final UidObserverRegistration reg = (UidObserverRegistration)
+                    mUidObservers.getBroadcastCookie(i);
             if (observer != null) {
                 try {
                     for (int j=0; j<N; j++) {
@@ -4122,7 +4141,7 @@
                         }
                         if (change == UidRecord.CHANGE_IDLE
                                 || change == UidRecord.CHANGE_GONE_IDLE) {
-                            if ((which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
+                            if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID idle uid=" + item.uid);
                                 observer.onUidIdle(item.uid);
@@ -4133,7 +4152,7 @@
                                 }
                             }
                         } else if (change == UidRecord.CHANGE_ACTIVE) {
-                            if ((which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
+                            if ((reg.which & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID active uid=" + item.uid);
                                 observer.onUidActive(item.uid);
@@ -4144,22 +4163,43 @@
                         }
                         if (change == UidRecord.CHANGE_GONE
                                 || change == UidRecord.CHANGE_GONE_IDLE) {
-                            if ((which & ActivityManager.UID_OBSERVER_GONE) != 0) {
+                            if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID gone uid=" + item.uid);
                                 observer.onUidGone(item.uid);
                             }
+                            if (reg.lastProcStates != null) {
+                                reg.lastProcStates.delete(item.uid);
+                            }
                             if (VALIDATE_UID_STATES && i == 0) {
                                 if (validateUid != null) {
                                     mValidateUids.remove(item.uid);
                                 }
                             }
                         } else {
-                            if ((which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
+                            if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID CHANGED uid=" + item.uid
                                                 + ": " + item.processState);
-                                observer.onUidStateChanged(item.uid, item.processState);
+                                boolean doReport = true;
+                                if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) {
+                                    final int lastState = reg.lastProcStates.get(item.uid,
+                                            ActivityManager.PROCESS_STATE_UNKNOWN);
+                                    if (lastState != ActivityManager.PROCESS_STATE_UNKNOWN) {
+                                        final boolean lastAboveCut = lastState <= reg.cutpoint;
+                                        final boolean newAboveCut = item.processState <= reg.cutpoint;
+                                        doReport = lastAboveCut != newAboveCut;
+                                    } else {
+                                        doReport = item.processState
+                                                != ActivityManager.PROCESS_STATE_NONEXISTENT;
+                                    }
+                                }
+                                if (doReport) {
+                                    if (reg.lastProcStates != null) {
+                                        reg.lastProcStates.put(item.uid, item.processState);
+                                    }
+                                    observer.onUidStateChanged(item.uid, item.processState);
+                                }
                             }
                             if (VALIDATE_UID_STATES && i == 0) {
                                 validateUid.curProcState = validateUid.setProcState
@@ -12245,13 +12285,15 @@
     }
 
     @Override
-    public void registerUidObserver(IUidObserver observer, int which, String callingPackage) {
+    public void registerUidObserver(IUidObserver observer, int which, int cutpoint,
+            String callingPackage) {
         if (!hasUsageStatsPermission(callingPackage)) {
             enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
                     "registerUidObserver");
         }
         synchronized (this) {
-            mUidObservers.register(observer, which);
+            mUidObservers.register(observer, new UidObserverRegistration(Binder.getCallingUid(),
+                    callingPackage, which, cutpoint));
         }
     }
 
@@ -12897,7 +12939,7 @@
                         }
                     }
                 } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME
-                        && proc.setProcState > ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                        && proc.setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
                     proc.notCachedSinceIdle = true;
                     proc.initialIdlePss = 0;
                     proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
@@ -14332,7 +14374,7 @@
                         pw.print("  ");
                         for (int i=0; i<ass.mStateTimes.length; i++) {
                             long amt = ass.mStateTimes[i];
-                            if (ass.mLastState-ActivityManager.MIN_PROCESS_STATE == i) {
+                            if ((ass.mLastState-ActivityManager.MIN_PROCESS_STATE) == i) {
                                 amt += now - ass.mLastStateUptime;
                             }
                             if (amt != 0) {
@@ -14341,7 +14383,7 @@
                                             i + ActivityManager.MIN_PROCESS_STATE));
                                 pw.print("=");
                                 TimeUtils.formatDuration(amt, pw);
-                                if (ass.mLastState-ActivityManager.MIN_PROCESS_STATE == i) {
+                                if ((ass.mLastState-ActivityManager.MIN_PROCESS_STATE) == i) {
                                     pw.print("*");
                                 }
                             }
@@ -14613,6 +14655,43 @@
                             pw.print(mode); pw.println();
                 }
             }
+            final int NI = mUidObservers.getRegisteredCallbackCount();
+            boolean printed = false;
+            for (int i=0; i<NI; i++) {
+                final UidObserverRegistration reg = (UidObserverRegistration)
+                        mUidObservers.getRegisteredCallbackCookie(i);
+                if (dumpPackage == null || dumpPackage.equals(reg.pkg)) {
+                    if (!printed) {
+                        pw.println("  mUidObservers:");
+                        printed = true;
+                    }
+                    pw.print("    "); UserHandle.formatUid(pw, reg.uid);
+                    pw.print(" "); pw.print(reg.pkg); pw.print(":");
+                    if ((reg.which&ActivityManager.UID_OBSERVER_IDLE) != 0) {
+                        pw.print(" IDLE");
+                    }
+                    if ((reg.which&ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
+                        pw.print(" ACT" );
+                    }
+                    if ((reg.which&ActivityManager.UID_OBSERVER_GONE) != 0) {
+                        pw.print(" GONE");
+                    }
+                    if ((reg.which&ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
+                        pw.print(" STATE");
+                        pw.print(" (cut="); pw.print(reg.cutpoint);
+                        pw.print(")");
+                    }
+                    pw.println();
+                    if (reg.lastProcStates != null) {
+                        final int NJ = reg.lastProcStates.size();
+                        for (int j=0; j<NJ; j++) {
+                            pw.print("      Last ");
+                            UserHandle.formatUid(pw, reg.lastProcStates.keyAt(j));
+                            pw.print(": "); pw.println(reg.lastProcStates.valueAt(j));
+                        }
+                    }
+                }
+            }
         }
         if (dumpPackage == null) {
             pw.println("  mWakefulness="
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index e4ec169..2a0c6d0 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -458,9 +458,12 @@
         // Instead, launch the ephemeral installer. Once the installer is finished, it
         // starts either the intent we resolved here [on install error] or the ephemeral
         // app [on install success].
-        if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
+        if (rInfo != null && rInfo.ephemeralIntentInfo != null) {
+            final String packageName =
+                    rInfo.ephemeralIntentInfo.getEphemeralResolveInfo().getPackageName();
+            final String splitName = rInfo.ephemeralIntentInfo.getSplitName();
             intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
-                    rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
+                    packageName, splitName, callingPackage, resolvedType,
                     userId);
             resolvedType = null;
             callingUid = realCallingUid;
@@ -524,7 +527,8 @@
      * Builds and returns an intent to launch the ephemeral installer.
      */
     private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
-            String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
+            String ephemeralPackageName, String ephemeralSplitName, String callingPackage,
+            String resolvedType, int userId) {
         final Intent nonEphemeralIntent = new Intent(origIntent);
         nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
         // Intent that is launched if the ephemeral package couldn't be installed
@@ -540,7 +544,7 @@
         if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
             // Force the intent to be directed to the ephemeral package
             ephemeralIntent = new Intent(origIntent);
-            ephemeralIntent.setPackage(ephemeralPackage);
+            ephemeralIntent.setPackage(ephemeralPackageName);
         } else {
             // Success intent goes back to the installer
             ephemeralIntent = new Intent(launchIntent);
@@ -564,7 +568,8 @@
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK
                 | Intent.FLAG_ACTIVITY_NO_HISTORY
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
+        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackageName);
+        intent.putExtra(Intent.EXTRA_SPLIT_NAME, ephemeralSplitName);
         intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
         intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
         // TODO: Remove when the platform has fully implemented ephemeral apps
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 2b00f86..1322ecf 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -371,9 +371,6 @@
     public static String makeProcStateString(int curProcState) {
         String procState;
         switch (curProcState) {
-            case -1:
-                procState = "N ";
-                break;
             case ActivityManager.PROCESS_STATE_PERSISTENT:
                 procState = "P ";
                 break;
@@ -425,6 +422,9 @@
             case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                 procState = "CE";
                 break;
+            case ActivityManager.PROCESS_STATE_NONEXISTENT:
+                procState = "N ";
+                break;
             default:
                 procState = "??";
                 break;
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index a37dfed..df64447 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -824,7 +824,8 @@
             try {
                 ActivityManagerNative.getDefault().registerUidObserver(mUidObserver,
                         ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
-                        | ActivityManager.UID_OBSERVER_IDLE, null);
+                        | ActivityManager.UID_OBSERVER_IDLE, ActivityManager.PROCESS_STATE_UNKNOWN,
+                        null);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
             }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d8103fc..fd99f57 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -612,7 +612,7 @@
             try {
                 mActivityManager.registerUidObserver(mUidObserver,
                         ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
-                        null);
+                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
                 mNetworkManager.registerObserver(mAlertObserver);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6ebdb3c..f3ae2bc 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -760,7 +760,7 @@
                 mListeners.onPackagesChanged(removingPackage, pkgList);
                 mRankerServices.onPackagesChanged(removingPackage, pkgList);
                 mConditionProviders.onPackagesChanged(removingPackage, pkgList);
-                mRankingHelper.onPackagesChanged(removingPackage, pkgList);
+                mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList);
             }
         }
     };
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 1bb8b3b..d65ea7f 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -716,9 +716,8 @@
         return packageBans;
     }
 
-    public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
-        if (removingPackage || pkgList == null || pkgList.length == 0
-                || mRestoredWithoutUids.isEmpty()) {
+    public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList) {
+        if (removingPackage || pkgList == null || pkgList.length == 0) {
             return; // nothing to do
         }
         boolean updated = false;
@@ -726,8 +725,7 @@
             final Record r = mRestoredWithoutUids.get(pkg);
             if (r != null) {
                 try {
-                    //TODO: http://b/22388012
-                    r.uid = mPm.getPackageUidAsUser(r.pkg, UserHandle.USER_SYSTEM);
+                    r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
                     mRestoredWithoutUids.remove(pkg);
                     mRecords.put(recordKey(r.pkg, r.uid), r);
                     updated = true;
@@ -737,7 +735,7 @@
             }
             try {
                 Record fullRecord = getRecord(pkg,
-                        mPm.getPackageUidAsUser(pkg, UserHandle.USER_SYSTEM));
+                        mPm.getPackageUidAsUser(pkg, changeUserId));
                 if (fullRecord != null) {
                     clampDefaultChannel(fullRecord);
                 }
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index a6a3774..9778919 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -51,6 +51,8 @@
     private final Object mLock = new Object();
     private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller =
             new GetEphemeralResolveInfoCaller();
+    private final GetEphemeralIntentFilterCaller mGetEphemeralIntentFilterCaller =
+            new GetEphemeralIntentFilterCaller();
     private final ServiceConnection mServiceConnection = new MyServiceConnection();
     private final Context mContext;
     /** Intent used to bind to the service */
@@ -64,12 +66,26 @@
         mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
     }
 
-    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(
-            int hashPrefix[], int prefixMask) {
+    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(int hashPrefix[]) {
         throwIfCalledOnMainThread();
         try {
             return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList(
-                    getRemoteInstanceLazy(), hashPrefix, prefixMask);
+                    getRemoteInstanceLazy(), hashPrefix);
+        } catch (RemoteException re) {
+        } catch (TimeoutException te) {
+        } finally {
+            synchronized (mLock) {
+                mLock.notifyAll();
+            }
+        }
+        return null;
+    }
+
+    public final List<EphemeralResolveInfo> getEphemeralIntentFilterList(int digestPrefix[]) {
+        throwIfCalledOnMainThread();
+        try {
+            return mGetEphemeralIntentFilterCaller.getEphemeralIntentFilterList(
+                    getRemoteInstanceLazy(), digestPrefix);
         } catch (RemoteException re) {
         } catch (TimeoutException te) {
         } finally {
@@ -181,10 +197,38 @@
         }
 
         public List<EphemeralResolveInfo> getEphemeralResolveInfoList(
-                IEphemeralResolver target, int hashPrefix[], int prefixMask)
+                IEphemeralResolver target, int hashPrefix[])
                         throws RemoteException, TimeoutException {
             final int sequence = onBeforeRemoteCall();
-            target.getEphemeralResolveInfoList(mCallback, hashPrefix, prefixMask, sequence);
+            target.getEphemeralResolveInfoList(mCallback, hashPrefix, sequence);
+            return getResultTimed(sequence);
+        }
+    }
+
+    private static final class GetEphemeralIntentFilterCaller
+            extends TimedRemoteCaller<List<EphemeralResolveInfo>> {
+        private final IRemoteCallback mCallback;
+
+        public GetEphemeralIntentFilterCaller() {
+            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
+            mCallback = new IRemoteCallback.Stub() {
+                @Override
+                public void sendResult(Bundle data) throws RemoteException {
+                    final ArrayList<EphemeralResolveInfo> resolveList =
+                            data.getParcelableArrayList(
+                                    EphemeralResolverService.EXTRA_RESOLVE_INFO);
+                    int sequence =
+                            data.getInt(EphemeralResolverService.EXTRA_SEQUENCE, -1);
+                    onRemoteMethodResult(resolveList, sequence);
+                }
+            };
+        }
+
+        public List<EphemeralResolveInfo> getEphemeralIntentFilterList(
+                IEphemeralResolver target, int digestPrefix[])
+                        throws RemoteException, TimeoutException {
+            final int sequence = onBeforeRemoteCall();
+            target.getEphemeralIntentFilterList(mCallback, digestPrefix, sequence);
             return getResultTimed(sequence);
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ca77335..cf3aaba 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -122,6 +122,7 @@
 import android.content.pm.AppsQueryHelper;
 import android.content.pm.ComponentInfo;
 import android.content.pm.EphemeralApplicationInfo;
+import android.content.pm.EphemeralIntentFilter;
 import android.content.pm.EphemeralResolveInfo;
 import android.content.pm.EphemeralResolveInfo.EphemeralDigest;
 import android.content.pm.EphemeralResolveInfo.EphemeralResolveIntentInfo;
@@ -471,9 +472,12 @@
      * VENDOR_OVERLAY_DIR.
      */
     private static final String VENDOR_OVERLAY_THEME_PROPERTY = "ro.boot.vendor.overlay.theme";
-
-    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFF000;
-    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT = 5;
+    /**
+     * Same as VENDOR_OVERLAY_THEME_PROPERTY, except persistent. If set will override whatever
+     * is in VENDOR_OVERLAY_THEME_PROPERTY.
+     */
+    private static final String VENDOR_OVERLAY_THEME_PERSIST_PROPERTY
+            = "persist.vendor.overlay.theme";
 
     /** Permission grant: not grant the permission. */
     private static final int GRANT_DENIED = 1;
@@ -2289,7 +2293,10 @@
             // 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.
-            String overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PROPERTY);
+            String overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PERSIST_PROPERTY);
+            if (overlayThemeDir.isEmpty()) {
+                overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PROPERTY);
+            }
             if (!overlayThemeDir.isEmpty()) {
                 scanDirTracedLI(new File(VENDOR_OVERLAY_DIR, overlayThemeDir), mDefParseFlags
                         | PackageParser.PARSE_IS_SYSTEM
@@ -4936,19 +4943,15 @@
         return true;
     }
 
-    private static EphemeralResolveInfo getEphemeralResolveInfo(
+    private static EphemeralResolveIntentInfo getEphemeralIntentInfo(
             Context context, EphemeralResolverConnection resolverConnection, Intent intent,
             String resolvedType, int userId, String packageName) {
-        final int ephemeralPrefixMask = Global.getInt(context.getContentResolver(),
-                Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK);
-        final int ephemeralPrefixCount = Global.getInt(context.getContentResolver(),
-                Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT);
-        final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask,
-                ephemeralPrefixCount);
+        final EphemeralDigest digest =
+                new EphemeralDigest(intent.getData().getHost(), 5 /*maxDigests*/);
         final int[] shaPrefix = digest.getDigestPrefix();
         final byte[][] digestBytes = digest.getDigestBytes();
         final List<EphemeralResolveInfo> ephemeralResolveInfoList =
-                resolverConnection.getEphemeralResolveInfoList(shaPrefix, ephemeralPrefixMask);
+                resolverConnection.getEphemeralResolveInfoList(shaPrefix);
         if (ephemeralResolveInfoList == null || ephemeralResolveInfoList.size() == 0) {
             // No hash prefix match; there are no ephemeral apps for this domain.
             return null;
@@ -4960,9 +4963,10 @@
                 if (!Arrays.equals(digestBytes[i], ephemeralApplication.getDigestBytes())) {
                     continue;
                 }
-                final List<IntentFilter> filters = ephemeralApplication.getFilters();
+                final List<EphemeralIntentFilter> ephemeralFilters =
+                        ephemeralApplication.getIntentFilters();
                 // No filters; this should never happen.
-                if (filters.isEmpty()) {
+                if (ephemeralFilters.isEmpty()) {
                     continue;
                 }
                 if (packageName != null
@@ -4971,13 +4975,21 @@
                 }
                 // We have a domain match; resolve the filters to see if anything matches.
                 final EphemeralIntentResolver ephemeralResolver = new EphemeralIntentResolver();
-                for (int j = filters.size() - 1; j >= 0; --j) {
-                    final EphemeralResolveIntentInfo intentInfo =
-                            new EphemeralResolveIntentInfo(filters.get(j), ephemeralApplication);
-                    ephemeralResolver.addFilter(intentInfo);
+                for (int j = ephemeralFilters.size() - 1; j >= 0; --j) {
+                    final EphemeralIntentFilter ephemeralFilter = ephemeralFilters.get(j);
+                    final List<IntentFilter> splitFilters = ephemeralFilter.getFilters();
+                    if (splitFilters == null || splitFilters.isEmpty()) {
+                        continue;
+                    }
+                    for (int k = splitFilters.size() - 1; k >= 0; --k) {
+                        final EphemeralResolveIntentInfo intentInfo =
+                                new EphemeralResolveIntentInfo(splitFilters.get(k),
+                                        ephemeralApplication, ephemeralFilter.getSplitName());
+                        ephemeralResolver.addFilter(intentInfo);
+                    }
                 }
-                List<EphemeralResolveInfo> matchedResolveInfoList = ephemeralResolver.queryIntent(
-                        intent, resolvedType, false /*defaultOnly*/, userId);
+                List<EphemeralResolveIntentInfo> matchedResolveInfoList = ephemeralResolver
+                        .queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
                 if (!matchedResolveInfoList.isEmpty()) {
                     return matchedResolveInfoList.get(0);
                 }
@@ -5460,15 +5472,15 @@
         }
         if (addEphemeral) {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
-            final EphemeralResolveInfo ai = getEphemeralResolveInfo(
+            final EphemeralResolveIntentInfo intentInfo = getEphemeralIntentInfo(
                     mContext, mEphemeralResolverConnection, intent, resolvedType, userId,
                     matchEphemeralPackage ? pkgName : null);
-            if (ai != null) {
+            if (intentInfo != null) {
                 if (DEBUG_EPHEMERAL) {
                     Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
                 }
                 final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo);
-                ephemeralInstaller.ephemeralResolveInfo = ai;
+                ephemeralInstaller.ephemeralIntentInfo = intentInfo;
                 // make sure this resolver is the default
                 ephemeralInstaller.isDefault = true;
                 ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -11442,7 +11454,7 @@
     }
 
     private static final class EphemeralIntentResolver
-            extends IntentResolver<EphemeralResolveIntentInfo, EphemeralResolveInfo> {
+            extends IntentResolver<EphemeralResolveIntentInfo, EphemeralResolveIntentInfo> {
         /**
          * The result that has the highest defined order. Ordering applies on a
          * per-package basis. Mapping is from package name to Pair of order and
@@ -11467,7 +11479,7 @@
         }
 
         @Override
-        protected EphemeralResolveInfo newResult(EphemeralResolveIntentInfo info, int match,
+        protected EphemeralResolveIntentInfo newResult(EphemeralResolveIntentInfo info, int match,
                 int userId) {
             if (!sUserManager.exists(userId)) {
                 return null;
@@ -11485,18 +11497,18 @@
                 // non-zero order, enable ordering
                 mOrderResult.put(packageName, new Pair<>(order, res));
             }
-            return res;
+            return info;
         }
 
         @Override
-        protected void filterResults(List<EphemeralResolveInfo> results) {
+        protected void filterResults(List<EphemeralResolveIntentInfo> results) {
             // only do work if ordering is enabled [most of the time it won't be]
             if (mOrderResult.size() == 0) {
                 return;
             }
             int resultSize = results.size();
             for (int i = 0; i < resultSize; i++) {
-                final EphemeralResolveInfo info = results.get(i);
+                final EphemeralResolveInfo info = results.get(i).getEphemeralResolveInfo();
                 final String packageName = info.getPackageName();
                 final Pair<Integer, EphemeralResolveInfo> savedInfo = mOrderResult.get(packageName);
                 if (savedInfo == null) {
@@ -18088,8 +18100,10 @@
         }
 
         synchronized (mPackages) {
-            if (uid == Process.SHELL_UID) {
+            if (uid == Process.SHELL_UID
+                    && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
                 // Shell can only change whole packages between ENABLED and DISABLED_USER states
+                // unless it is a test package.
                 int oldState = pkgSetting.getEnabled(userId);
                 if (className == null
                     &&
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 38d69ed..d558b07 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -635,11 +635,7 @@
                 return false; // Shouldn't happen.
             }
 
-            // Always scan the settings app, since its version code is the same for DR and MR1.
-            // TODO Fix it properly: b/32554059
-            final boolean isSettings = "com.android.settings".equals(getPackageName());
-
-            if (!isNewApp && !forceRescan && !isSettings) {
+            if (!isNewApp && !forceRescan) {
                 // Return if the package hasn't changed, ie:
                 // - version code hasn't change
                 // - lastUpdateTime hasn't change
@@ -656,11 +652,6 @@
                     return false;
                 }
             }
-            if (isSettings) {
-                if (ShortcutService.DEBUG) {
-                    Slog.d(TAG, "Always scan settings.");
-                }
-            }
         } finally {
             s.logDurationStat(Stats.PACKAGE_UPDATE_CHECK, start);
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 37acf5c..ad31a32 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -468,7 +468,7 @@
 
         @Override
         public void onUidGone(int uid) throws RemoteException {
-            handleOnUidStateChanged(uid, ActivityManager.MAX_PROCESS_STATE);
+            handleOnUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
         }
 
         @Override
@@ -497,8 +497,7 @@
     }
 
     private boolean isProcessStateForeground(int processState) {
-        return (processState != ActivityManager.PROCESS_STATE_NONEXISTENT)
-                && (processState <= PROCESS_STATE_FOREGROUND_THRESHOLD);
+        return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD;
     }
 
     boolean isUidForegroundLocked(int uid) {
@@ -2667,8 +2666,7 @@
                     }
                 }
 
-                rescanUpdatedPackagesLocked(ownerUserId, user.getLastAppScanTime(),
-                        /* forceRescan=*/ false);
+                rescanUpdatedPackagesLocked(ownerUserId, user.getLastAppScanTime());
             }
         } finally {
             logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
@@ -2676,8 +2674,7 @@
         verifyStates();
     }
 
-    private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime,
-            boolean forceRescan) {
+    private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime) {
         final ShortcutUser user = getUserShortcutsLocked(userId);
 
         // Note after each OTA, we'll need to rescan all system apps, as their lastUpdateTime
@@ -2689,7 +2686,8 @@
         // Then for each installed app, publish manifest shortcuts when needed.
         forUpdatedPackages(userId, lastScanTime, afterOta, ai -> {
             user.attemptToRestoreIfNeededAndSave(this, ai.packageName, userId);
-            user.rescanPackageIfNeeded(ai.packageName, forceRescan);
+
+            user.rescanPackageIfNeeded(ai.packageName, /* forceRescan= */ true);
         });
 
         // Write the time just before the scan, because there may be apps that have just
@@ -2937,32 +2935,26 @@
     private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, boolean afterOta,
             Consumer<ApplicationInfo> callback) {
         if (DEBUG) {
-            Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime);
+            Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime
+                    + " afterOta=" + afterOta);
         }
         final List<PackageInfo> list = getInstalledPackages(userId);
         for (int i = list.size() - 1; i >= 0; i--) {
             final PackageInfo pi = list.get(i);
 
             // If the package has been updated since the last scan time, then scan it.
-            // Also if it's a system app with no update, lastUpdateTime is not reliable, so
-            // just scan it.
-            if (pi.lastUpdateTime >= lastScanTime
-                    || (afterOta && isPureSystemApp(pi.applicationInfo))) {
+            // Also if it's right after an OTA, always re-scan all apps anyway, since the
+            // shortcut parser might have changed.
+            if (afterOta || (pi.lastUpdateTime >= lastScanTime)) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Found updated package " + pi.packageName);
+                    Slog.d(TAG, "Found updated package " + pi.packageName
+                            + " updateTime=" + pi.lastUpdateTime);
                 }
                 callback.accept(pi.applicationInfo);
             }
         }
     }
 
-    /**
-     * @return true if it's a system app with no updates.
-     */
-    private boolean isPureSystemApp(ApplicationInfo ai) {
-        return ai.isSystemApp() && !ai.isUpdatedSystemApp();
-    }
-
     private boolean isApplicationFlagSet(@NonNull String packageName, int userId, int flags) {
         final ApplicationInfo ai = injectApplicationInfoWithUninstalled(packageName, userId);
         return (ai != null) && ((ai.flags & flags) == flags);
@@ -3213,8 +3205,8 @@
 
             // Rescan all packages to re-publish manifest shortcuts and do other checks.
             rescanUpdatedPackagesLocked(userId,
-                    0, // lastScanTime = 0; rescan all packages.
-                    /* forceRescan= */ true);
+                    0 // lastScanTime = 0; rescan all packages.
+                    );
 
             saveUserLocked(userId);
         }
@@ -3677,7 +3669,8 @@
     @VisibleForTesting
     void injectRegisterUidObserver(IUidObserver observer, int which) {
         try {
-            ActivityManagerNative.getDefault().registerUidObserver(observer, which, null);
+            ActivityManagerNative.getDefault().registerUidObserver(observer, which,
+                    ActivityManager.PROCESS_STATE_UNKNOWN, null);
         } catch (RemoteException shouldntHappen) {
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index d755e58..1790554 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2731,6 +2731,8 @@
                     }
                 } else {
                     disabled = !wakeLock.mUidState.mActive &&
+                            wakeLock.mUidState.mProcState
+                                    != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                             wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
                 }
             }
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
new file mode 100644
index 0000000..23be9a3
--- /dev/null
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -0,0 +1,95 @@
+/*
+ * 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.server.storage;
+
+import android.annotation.CallSuper;
+import android.annotation.WorkerThread;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+import com.android.internal.os.AppFuseMount;
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+public class AppFuseBridge implements Runnable {
+    private static final String TAG = AppFuseBridge.class.getSimpleName();
+
+    private final FileDescriptor mDeviceFd;
+    private final FileDescriptor mProxyFd;
+    private final CountDownLatch mMountLatch = new CountDownLatch(1);
+
+    /**
+     * @param deviceFd FD of /dev/fuse. Ownership of fd is taken by AppFuseBridge.
+     * @param proxyFd FD of socket pair. Ownership of fd is taken by AppFuseBridge.
+     */
+    private AppFuseBridge(FileDescriptor deviceFd, FileDescriptor proxyFd) {
+        mDeviceFd = deviceFd;
+        mProxyFd = proxyFd;
+    }
+
+    public static AppFuseMount startMessageLoop(
+            int uid,
+            String name,
+            FileDescriptor deviceFd,
+            Handler handler,
+            ParcelFileDescriptor.OnCloseListener listener)
+                    throws IOException, ErrnoException, InterruptedException {
+        final FileDescriptor localFd = new FileDescriptor();
+        final FileDescriptor remoteFd = new FileDescriptor();
+        // Needs to specify OsConstants.SOCK_SEQPACKET to keep message boundaries.
+        Os.socketpair(OsConstants.AF_UNIX, OsConstants.SOCK_SEQPACKET, 0, remoteFd, localFd);
+
+        // Caller must invoke #start() after instantiate AppFuseBridge.
+        // Otherwise FDs will be leaked.
+        final AppFuseBridge bridge = new AppFuseBridge(deviceFd, localFd);
+        final Thread thread = new Thread(bridge, TAG);
+        thread.start();
+        try {
+            bridge.mMountLatch.await();
+        } catch (InterruptedException error) {
+            throw error;
+        }
+        return new AppFuseMount(
+                new File("/mnt/appfuse/" + uid + "_" + name),
+                ParcelFileDescriptor.fromFd(remoteFd, handler, listener));
+    }
+
+    @Override
+    public void run() {
+        // deviceFd and proxyFd must be closed in native_start_loop.
+        final int deviceFd = mDeviceFd.getInt$();
+        final int proxyFd = mProxyFd.getInt$();
+        mDeviceFd.setInt$(-1);
+        mProxyFd.setInt$(-1);
+        native_start_loop(deviceFd, proxyFd);
+    }
+
+    // Used by com_android_server_storage_AppFuse.cpp.
+    private void onMount() {
+        mMountLatch.countDown();
+    }
+
+    private native boolean native_start_loop(int deviceFd, int proxyFd);
+}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 670b9cc..869e207 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1034,7 +1034,6 @@
                 boolean focusedWindowAdded = false;
 
                 final int visibleWindowCount = visibleWindows.size();
-                int skipRemainingWindowsForTaskId = -1;
                 HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
                 for (int i = visibleWindowCount - 1; i >= 0; i--) {
                     final WindowState windowState = visibleWindows.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f038135..299fa05 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,9 +40,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OP_NONE;
@@ -55,17 +53,13 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -78,7 +72,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
@@ -760,9 +753,6 @@
                 WindowToken token = exitingTokens.get(i);
                 if (!token.hasVisible) {
                     exitingTokens.remove(i);
-                    if (token.windowType == TYPE_WALLPAPER) {
-                        displayContent.mWallpaperController.removeWallpaperToken(token);
-                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 250d381..178fbe7 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -55,7 +55,7 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
     final private WindowManagerService mService;
 
-    private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
+    private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
 
     // If non-null, this is the currently visible window that is associated
     // with the wallpaper.
@@ -135,7 +135,7 @@
      */
     void startWallpaperAnimation(Animation a) {
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             token.startAnimation(a);
         }
     }
@@ -163,7 +163,7 @@
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
 
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             token.updateWallpaperVisibility(visible);
         }
     }
@@ -189,7 +189,7 @@
 
         final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
         for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
-            final WindowToken token = mWallpaperTokens.get(i);
+            final WallpaperWindowToken token = mWallpaperTokens.get(i);
             token.hideWallpaperToken(wasDeferred, "hideWallpapers");
             if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
                     + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
@@ -304,7 +304,7 @@
                 || window == mUpperWallpaperTarget) {
             boolean doWait = sync;
             for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-                final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+                final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
                 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
             }
 
@@ -652,7 +652,7 @@
         // Start stepping backwards from here, ensuring that our wallpaper windows are correctly placed.
         boolean changed = false;
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             changed |= token.updateWallpaperWindowsPlacement(windows, wallpaperTarget,
                     wallpaperTargetIndex, visible, dw, dh, mWallpaperAnimLayerAdjustment);
         }
@@ -725,7 +725,7 @@
         boolean wallpaperReady = true;
         for (int curTokenIndex = mWallpaperTokens.size() - 1;
                 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenIndex);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenIndex);
             if (token.hasVisibleNotDrawnWallpaper()) {
                 // We've told this wallpaper to be visible, but it is not drawn yet
                 wallpaperReady = false;
@@ -777,11 +777,11 @@
         }
     }
 
-    void addWallpaperToken(WindowToken token) {
+    void addWallpaperToken(WallpaperWindowToken token) {
         mWallpaperTokens.add(token);
     }
 
-    void removeWallpaperToken(WindowToken token) {
+    void removeWallpaperToken(WallpaperWindowToken token) {
         mWallpaperTokens.remove(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
new file mode 100644
index 0000000..fdefcfe
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -0,0 +1,228 @@
+/*
+ * 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.server.wm;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.animation.Animation;
+
+/**
+ * A token that represents a set of wallpaper windows.
+ */
+class WallpaperWindowToken extends WindowToken {
+
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM;
+
+    WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
+            DisplayContent dc) {
+        super(service, token, TYPE_WALLPAPER, explicit, dc);
+        dc.mWallpaperController.addWallpaperToken(this);
+    }
+
+    @Override
+    void setExiting() {
+        super.setExiting();
+        mDisplayContent.mWallpaperController.removeWallpaperToken(this);
+    }
+
+    void hideWallpaperToken(boolean wasDeferred, String reason) {
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowState wallpaper = mChildren.get(j);
+            wallpaper.hideWallpaperWindow(wasDeferred, reason);
+        }
+        hidden = true;
+    }
+
+    void sendWindowWallpaperCommand(
+            String action, int x, int y, int z, Bundle extras, boolean sync) {
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            try {
+                wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
+                // We only want to be synchronous with one wallpaper.
+                sync = false;
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    void updateWallpaperOffset(int dw, int dh, boolean sync) {
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
+                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+                winAnimator.computeShownFrameLocked();
+                // No need to lay out the windows - we can just set the wallpaper position directly.
+                winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
+                // We only want to be synchronous with one wallpaper.
+                sync = false;
+            }
+        }
+    }
+
+    void updateWallpaperVisibility(boolean visible) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
+        if (hidden == visible) {
+            hidden = !visible;
+            // Need to do a layout to ensure the wallpaper now has the correct size.
+            mDisplayContent.setLayoutNeeded();
+        }
+
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            if (visible) {
+                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+            }
+
+            wallpaper.dispatchWallpaperVisibility(visible);
+        }
+    }
+
+    /**
+     * Starts {@param anim} on all children.
+     */
+    void startAnimation(Animation anim) {
+        for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
+            final WindowState windowState = mChildren.get(ndx);
+            windowState.mWinAnimator.setAnimation(anim);
+        }
+    }
+
+    boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
+            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
+            int wallpaperAnimLayerAdj) {
+
+        boolean changed = false;
+        if (hidden == visible) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
+                    "Wallpaper token " + token + " hidden=" + !visible);
+            hidden = !visible;
+            // Need to do a layout to ensure the wallpaper now has the correct size.
+            mDisplayContent.setLayoutNeeded();
+        }
+
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+
+            if (visible) {
+                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+            }
+
+            // First, make sure the client has the current visibility state.
+            wallpaper.dispatchWallpaperVisibility(visible);
+            wallpaper.adjustAnimLayer(wallpaperAnimLayerAdj);
+
+            if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+                    + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+
+            // First, if this window is at the current index, then all is well.
+            if (wallpaper == wallpaperTarget) {
+                wallpaperTargetIndex--;
+                wallpaperTarget = wallpaperTargetIndex > 0
+                        ? windowList.get(wallpaperTargetIndex - 1) : null;
+                continue;
+            }
+
+            // The window didn't match...  the current wallpaper window,
+            // wherever it is, is in the wrong place, so make sure it is not in the list.
+            int oldIndex = windowList.indexOf(wallpaper);
+            if (oldIndex >= 0) {
+                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+                        "Wallpaper removing at " + oldIndex + ": " + wallpaper);
+                mDisplayContent.removeFromWindowList(wallpaper);
+                if (oldIndex < wallpaperTargetIndex) {
+                    wallpaperTargetIndex--;
+                }
+            }
+
+            // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
+            // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
+            // is currently on screen, i.e. not hidden by policy.
+            int insertionIndex = 0;
+            if (visible && wallpaperTarget != null) {
+                final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
+                if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
+                            findLowestWindowOnScreen(windowList));
+                }
+            }
+            if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
+                    || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG,
+                    "Moving wallpaper " + wallpaper + " from " + oldIndex + " to " + insertionIndex);
+
+            mDisplayContent.addToWindowList(wallpaper, insertionIndex);
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    /**
+     * @return The index in {@param windows} of the lowest window that is currently on screen and
+     *         not hidden by the policy.
+     */
+    private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) {
+        final int size = windowList.size();
+        for (int index = 0; index < size; index++) {
+            final WindowState win = windowList.get(index);
+            if (win.isOnScreen()) {
+                return index;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    boolean hasVisibleNotDrawnWallpaper() {
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState wallpaper = mChildren.get(j);
+            if (wallpaper.hasVisibleNotDrawnWallpaper()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        if (stringName == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("WallpaperWindowToken{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" token="); sb.append(token); sb.append('}');
+            stringName = sb.toString();
+        }
+        return stringName;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7723752..5baa72a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1932,6 +1932,12 @@
                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
                     win.mAppToken.checkKeyguardFlagsChanged();
                 }
+                if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
+                        && (mAccessibilityController != null)
+                        && (win.getDisplayId() == DEFAULT_DISPLAY)) {
+                    // No move or resize, but the controller checks for title changes as well
+                    mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+                }
             }
 
             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
@@ -2409,9 +2415,10 @@
                         + " displayId=" + displayId);
                 return;
             }
-            token = new WindowToken(this, binder, type, true, dc);
             if (type == TYPE_WALLPAPER) {
-                dc.mWallpaperController.addWallpaperToken(token);
+                new WallpaperWindowToken(this, binder, true, dc);
+            } else {
+                new WindowToken(this, binder, type, true, dc);
             }
         }
     }
@@ -2440,9 +2447,6 @@
                 }
 
                 token.setExiting();
-                if (token.windowType == TYPE_WALLPAPER) {
-                    dc.mWallpaperController.removeWallpaperToken(token);
-                }
 
                 mInputMonitor.updateInputWindowsLw(true /*force*/);
             }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b821f09..93f1610 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -82,7 +82,7 @@
     boolean sendingToBottom;
 
     // The display this token is on.
-    private DisplayContent mDisplayContent;
+    protected DisplayContent mDisplayContent;
 
     /**
      * Compares two child window of this token and returns -1 if the first is lesser than the
@@ -280,169 +280,6 @@
         return false;
     }
 
-    void hideWallpaperToken(boolean wasDeferred, String reason) {
-        for (int j = mChildren.size() - 1; j >= 0; j--) {
-            final WindowState wallpaper = mChildren.get(j);
-            wallpaper.hideWallpaperWindow(wasDeferred, reason);
-        }
-        hidden = true;
-    }
-
-    void sendWindowWallpaperCommand(
-            String action, int x, int y, int z, Bundle extras, boolean sync) {
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            try {
-                wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
-                // We only want to be synchronous with one wallpaper.
-                sync = false;
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    void updateWallpaperOffset(int dw, int dh, boolean sync) {
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
-                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
-                winAnimator.computeShownFrameLocked();
-                // No need to lay out the windows - we can just set the wallpaper position directly.
-                winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
-                // We only want to be synchronous with one wallpaper.
-                sync = false;
-            }
-        }
-    }
-
-    void updateWallpaperVisibility(boolean visible) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
-        if (hidden == visible) {
-            hidden = !visible;
-            // Need to do a layout to ensure the wallpaper now has the correct size.
-            mDisplayContent.setLayoutNeeded();
-        }
-
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
-            }
-
-            wallpaper.dispatchWallpaperVisibility(visible);
-        }
-    }
-
-    /**
-     * Starts {@param anim} on all children.
-     */
-    void startAnimation(Animation anim) {
-        for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
-            final WindowState windowState = mChildren.get(ndx);
-            windowState.mWinAnimator.setAnimation(anim);
-        }
-    }
-
-    boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
-            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
-            int wallpaperAnimLayerAdj) {
-
-        boolean changed = false;
-        if (hidden == visible) {
-            if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
-                    "Wallpaper token " + token + " hidden=" + !visible);
-            hidden = !visible;
-            // Need to do a layout to ensure the wallpaper now has the correct size.
-            mDisplayContent.setLayoutNeeded();
-        }
-
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-
-            if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
-            }
-
-            // First, make sure the client has the current visibility state.
-            wallpaper.dispatchWallpaperVisibility(visible);
-            wallpaper.adjustAnimLayer(wallpaperAnimLayerAdj);
-
-            if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
-                    + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
-
-            // First, if this window is at the current index, then all is well.
-            if (wallpaper == wallpaperTarget) {
-                wallpaperTargetIndex--;
-                wallpaperTarget = wallpaperTargetIndex > 0
-                        ? windowList.get(wallpaperTargetIndex - 1) : null;
-                continue;
-            }
-
-            // The window didn't match...  the current wallpaper window,
-            // wherever it is, is in the wrong place, so make sure it is not in the list.
-            int oldIndex = windowList.indexOf(wallpaper);
-            if (oldIndex >= 0) {
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
-                        "Wallpaper removing at " + oldIndex + ": " + wallpaper);
-                mDisplayContent.removeFromWindowList(wallpaper);
-                if (oldIndex < wallpaperTargetIndex) {
-                    wallpaperTargetIndex--;
-                }
-            }
-
-            // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
-            // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
-            // is currently on screen, i.e. not hidden by policy.
-            int insertionIndex = 0;
-            if (visible && wallpaperTarget != null) {
-                final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
-                if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                    insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
-                            findLowestWindowOnScreen(windowList));
-                }
-            }
-            if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
-                    || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG,
-                    "Moving wallpaper " + wallpaper + " from " + oldIndex + " to " + insertionIndex);
-
-            mDisplayContent.addToWindowList(wallpaper, insertionIndex);
-            changed = true;
-        }
-
-        return changed;
-    }
-
-    /**
-     * @return The index in {@param windows} of the lowest window that is currently on screen and
-     *         not hidden by the policy.
-     */
-    private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) {
-        final int size = windowList.size();
-        for (int index = 0; index < size; index++) {
-            final WindowState win = windowList.get(index);
-            if (win.isOnScreen()) {
-                return index;
-            }
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    boolean hasVisibleNotDrawnWallpaper() {
-        for (int j = mChildren.size() - 1; j >= 0; --j) {
-            final WindowState wallpaper = mChildren.get(j);
-            if (wallpaper.hasVisibleNotDrawnWallpaper()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     int getHighestAnimLayer() {
         int highest = -1;
         for (int j = 0; j < mChildren.size(); j++) {
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index a4b5e6a..c03a460 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -19,6 +19,7 @@
     $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \
     $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_storage_AppFuseBridge.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvUinputBridge.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \
@@ -37,6 +38,7 @@
     frameworks/base/libs/hwui \
     frameworks/base/core/jni \
     frameworks/native/services \
+    system/core/libappfuse/include \
     system/security/keystore/include \
     $(call include-path-for, libhardware)/hardware \
     $(call include-path-for, libhardware_legacy)/hardware_legacy \
@@ -44,6 +46,7 @@
 LOCAL_SHARED_LIBRARIES += \
     libandroid_runtime \
     libandroidfw \
+    libappfuse \
     libbinder \
     libcutils \
     liblog \
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
new file mode 100644
index 0000000..640fd0e
--- /dev/null
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 specic language governing permissions and
+ * limitations under the License.
+ */
+
+// Need to use LOGE_EX.
+#define LOG_TAG "AppFuseBridge"
+
+#include <android_runtime/Log.h>
+#include <android-base/logging.h>
+#include <core_jni_helpers.h>
+#include <libappfuse/FuseBridgeLoop.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+namespace {
+
+constexpr const char* CLASS_NAME = "com/android/server/storage/AppFuseBridge";
+static jclass appFuseClass;
+static jmethodID appFuseOnMount;
+
+class Callback : public FuseBridgeLoop::Callback {
+    JNIEnv* mEnv;
+    jobject mSelf;
+
+public:
+    Callback(JNIEnv* env, jobject self) : mEnv(env), mSelf(self) {}
+    void OnMount() override {
+        mEnv->CallVoidMethod(mSelf, appFuseOnMount);
+        if (mEnv->ExceptionCheck()) {
+            LOGE_EX(mEnv, nullptr);
+            mEnv->ExceptionClear();
+        }
+    }
+};
+
+jboolean com_android_server_storage_AppFuseBridge_start_loop(
+        JNIEnv* env, jobject self, jint devJavaFd, jint proxyJavaFd) {
+    FuseBridgeLoop loop;
+    Callback callback(env, self);
+    return loop.Start(devJavaFd, proxyJavaFd, &callback);
+}
+
+const JNINativeMethod methods[] = {
+    {
+        "native_start_loop",
+        "(II)Z",
+        (void *) com_android_server_storage_AppFuseBridge_start_loop
+    }
+};
+
+}  // namespace
+
+void register_android_server_storage_AppFuse(JNIEnv* env) {
+    CHECK(env != nullptr);
+
+    appFuseClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME));
+    appFuseOnMount = GetMethodIDOrDie(env, appFuseClass, "onMount", "()V");
+    RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods));
+}
+}  // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index d69c37f..c291ba0 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -28,6 +28,7 @@
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
+int register_android_server_storage_AppFuse(JNIEnv* env);
 int register_android_server_SerialService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 int register_android_server_UsbDeviceManager(JNIEnv* env);
@@ -83,6 +84,7 @@
     register_android_server_PersistentDataBlockService(env);
     register_android_server_Watchdog(env);
     register_android_server_HardwarePropertiesManagerService(env);
+    register_android_server_storage_AppFuse(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 01d9304..39f14e5 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -631,6 +631,11 @@
         return shouldLog;
     }
 
+    // TODO: Migrate all Log.e(...) to logError(...).
+    private void logError(String fmt, Object... args) {
+        mLocalLog.log("ERROR " + String.format(fmt, args));
+    }
+
     private void getNetworkInterface() {
         try {
             mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
@@ -880,7 +885,7 @@
             mNwService.setInterfaceConfig(mInterfaceName, ifcg);
             if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
         } catch (IllegalStateException | RemoteException e) {
-            Log.e(mTag, "IPv4 configuration failed: ", e);
+            logError("IPv4 configuration failed: %s", e);
             return false;
         }
         return true;
@@ -944,6 +949,12 @@
         }
     }
 
+    private void doImmediateProvisioningFailure(int failureType) {
+        if (DBG) { Log.e(mTag, "onProvisioningFailure(): " + failureType); }
+        recordMetric(failureType);
+        mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));
+    }
+
     private boolean startIPv4() {
         // If we have a StaticIpConfiguration attempt to apply it and
         // handle the result accordingly.
@@ -951,9 +962,6 @@
             if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
                 handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
             } else {
-                if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
-                recordMetric(IpManagerEvent.PROVISIONING_FAIL);
-                mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));
                 return false;
             }
         } else {
@@ -972,16 +980,40 @@
             mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
             mNwService.enableIpv6(mInterfaceName);
         } catch (RemoteException re) {
-            Log.e(mTag, "Unable to change interface settings: " + re);
+            logError("Unable to change interface settings: %s", re);
             return false;
         } catch (IllegalStateException ie) {
-            Log.e(mTag, "Unable to change interface settings: " + ie);
+            logError("Unable to change interface settings: %s", ie);
             return false;
         }
 
         return true;
     }
 
+    private boolean startIpReachabilityMonitor() {
+        try {
+            mIpReachabilityMonitor = new IpReachabilityMonitor(
+                    mContext,
+                    mInterfaceName,
+                    new IpReachabilityMonitor.Callback() {
+                        @Override
+                        public void notifyLost(InetAddress ip, String logMsg) {
+                            mCallback.onReachabilityLost(logMsg);
+                        }
+                    },
+                    mAvoidBadWifiTracker);
+        } catch (IllegalArgumentException iae) {
+            // Failed to start IpReachabilityMonitor. Log it and call
+            // onProvisioningFailure() immediately.
+            //
+            // See http://b/31038971.
+            logError("IpReachabilityMonitor failure: %s", iae);
+            mIpReachabilityMonitor = null;
+        }
+
+        return (mIpReachabilityMonitor != null);
+    }
+
     private void stopAllIP() {
         // We don't need to worry about routes, just addresses, because:
         //     - disableIpv6() will clear autoconf IPv6 routes as well, and
@@ -1165,29 +1197,23 @@
                 mCallback.setFallbackMulticastFilter(mMulticastFiltering);
             }
 
-            if (mConfiguration.mEnableIPv6) {
-                // TODO: Consider transitionTo(mStoppingState) if this fails.
-                startIPv6();
+            if (mConfiguration.mEnableIPv6 && !startIPv6()) {
+                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
+                transitionTo(mStoppingState);
+                return;
             }
 
-            if (mConfiguration.mEnableIPv4) {
-                if (!startIPv4()) {
-                    transitionTo(mStoppingState);
-                    return;
-                }
+            if (mConfiguration.mEnableIPv4 && !startIPv4()) {
+                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
+                transitionTo(mStoppingState);
+                return;
             }
 
-            if (mConfiguration.mUsingIpReachabilityMonitor) {
-                mIpReachabilityMonitor = new IpReachabilityMonitor(
-                        mContext,
-                        mInterfaceName,
-                        new IpReachabilityMonitor.Callback() {
-                            @Override
-                            public void notifyLost(InetAddress ip, String logMsg) {
-                                mCallback.onReachabilityLost(logMsg);
-                            }
-                        },
-                        mAvoidBadWifiTracker);
+            if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {
+                doImmediateProvisioningFailure(
+                        IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
+                transitionTo(mStoppingState);
+                return;
             }
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
new file mode 100644
index 0000000..d6ee367
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.server;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+
+import static com.android.internal.widget.LockPatternUtils.stringToPattern;
+
+import static junit.framework.Assert.*;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static java.io.FileDescriptor.*;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+
+/**
+ * Test class for {@link LockSettingsShellCommand}.
+ *
+ * runtest frameworks-services -c com.android.server.LockSettingsShellCommandTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class LockSettingsShellCommandTest {
+
+    private LockSettingsShellCommand mCommand;
+
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private int mUserId;
+    private final Binder mBinder = new Binder();
+    private final ShellCallback mShellCallback = new ShellCallback();
+    private final ResultReceiver mResultReceiver = new ResultReceiver(
+            new Handler(Looper.getMainLooper()));
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final Context context = InstrumentationRegistry.getTargetContext();
+        mUserId = ActivityManager.getCurrentUser();
+        mCommand = new LockSettingsShellCommand(context, mLockPatternUtils);
+    }
+
+    @Test
+    public void testWrongPassword() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(false);
+        assertEquals(-1, mCommand.exec(mBinder, in, out, err,
+                new String[] { "set-pin", "--old", "1234" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).saveLockPassword(any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testChangePin() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_NUMERIC,
+                mUserId);
+    }
+
+    @Test
+    public void testChangePassword() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        assertEquals(0,  mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-password", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_ALPHABETIC,
+                mUserId);
+    }
+
+    @Test
+    public void testChangePattern() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPattern(stringToPattern("4321"), "1234", mUserId);
+    }
+
+    @Test
+    public void testClear() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "clear", "--old", "1234" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).clearLock(mUserId);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 42d9412..3114f3f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -246,7 +246,8 @@
                 Log.d(TAG, "set mUidObserver to " + mUidObserver);
                 return null;
             }
-        }).when(mActivityManager).registerUidObserver(any(), anyInt(), null);
+        }).when(mActivityManager).registerUidObserver(any(), anyInt(),
+                ActivityManager.PROCESS_STATE_UNKNOWN, null);
 
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
                 mNetworkManager, mIpm, mTime, mPolicyDir, true);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 792f300..9f01773 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -737,6 +737,10 @@
         // Start the service.
         initService();
         setCaller(CALLING_PACKAGE_1);
+
+        if (ENABLE_DUMP) {
+            Log.d(TAG, "setUp done");
+        }
     }
 
     private static boolean b(Boolean value) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 3cfdc32..771ca146 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4181,7 +4181,7 @@
         assertEquals(START_TIME,
                 findShortcut(shortcuts.getValue(), "s4").getLastChangedTimestamp());
 
-        // Next, send unlock even on user-10.  Now we scan packages on this user and send a
+        // Next, send an unlock event on user-10.  Now we scan packages on this user and send a
         // notification to the launcher.
         mInjectedCurrentTimeMillis = START_TIME + 200;
 
@@ -4222,9 +4222,8 @@
         updatePackageVersion(CALLING_PACKAGE_2, 10);
 
         // Then send the broadcast, to only user-0.
-                mService.mPackageMonitor.onReceive(getTestContext(),
+        mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
-        mService.checkPackageChanges(USER_10);
 
         waitOnMainThread();
 
@@ -4395,7 +4394,7 @@
         });
 
         // Next.
-        // Update the build finger print.  All system apps will be scanned now.
+        // Update the build finger print.  All apps will be scanned now.
         mInjectedBuildFingerprint = "update1";
         mInjectedCurrentTimeMillis += 1000;
         mService.checkPackageChanges(USER_0);
@@ -4406,12 +4405,11 @@
         });
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
             assertWith(getCallerShortcuts())
-                    .isEmpty();
+                    .haveIds("ms1");
         });
 
         // Next.
         // Update manifest shortcuts.
-        mInjectedBuildFingerprint = "update2";
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                 R.xml.shortcut_2);
@@ -4421,44 +4419,29 @@
         mInjectedCurrentTimeMillis += 1000;
         mService.checkPackageChanges(USER_0);
 
-        // Fingerprint hasn't changed, so CALLING_PACKAGE_1 wasn't scanned.
+        // Fingerprint hasn't changed, so there packages weren't scanned.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1");
         });
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
             assertWith(getCallerShortcuts())
-                    .isEmpty();
+                    .haveIds("ms1");
         });
 
-        // Update the fingerprint, but CALLING_PACKAGE_1's version code hasn't changed, so
-        // still not scanned.
+        // Update the fingerprint.  CALLING_PACKAGE_1's version code hasn't changed, but we scan
+        // all apps anyway.
         mInjectedBuildFingerprint = "update2";
         mInjectedCurrentTimeMillis += 1000;
         mService.checkPackageChanges(USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertWith(getCallerShortcuts())
-                    .haveIds("ms1");
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertWith(getCallerShortcuts())
-                    .isEmpty();
-        });
-
-        // Now update the version code, so CALLING_PACKAGE_1 is scanned again.
-        mInjectedBuildFingerprint = "update3";
-        mInjectedCurrentTimeMillis += 1000;
-        updatePackageVersion(CALLING_PACKAGE_1, 1);
-        mService.checkPackageChanges(USER_0);
-
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2");
         });
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
             assertWith(getCallerShortcuts())
-                    .isEmpty();
+                    .haveIds("ms1", "ms2");
         });
 
         // Make sure getLastAppScanTime / getLastAppScanOsFingerprint are persisted.
@@ -5721,6 +5704,7 @@
                 R.xml.shortcut_5);
 
         // Unlock user-0.
+        mInjectedCurrentTimeMillis += 100;
         mService.handleUnlockUser(USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5750,6 +5734,7 @@
         uninstallPackage(USER_10, CALLING_PACKAGE_1);
         uninstallPackage(USER_10, CALLING_PACKAGE_3);
 
+        mInjectedCurrentTimeMillis += 100;
         mService.handleUnlockUser(USER_10);
 
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -5774,6 +5759,8 @@
         // hasn't changed.
         shutdownServices();
 
+        mInjectedCurrentTimeMillis += 100;
+
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                 R.xml.shortcut_5);
@@ -5785,7 +5772,7 @@
         mService.handleUnlockUser(USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
+            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled( // FAIL
                     mManager.getManifestShortcuts()))),
                     "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
@@ -5808,6 +5795,8 @@
         // Do it again, but this time we change the app version, so we do detect the changes.
         shutdownServices();
 
+        mInjectedCurrentTimeMillis += 100;
+
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         updatePackageLastUpdateTime(CALLING_PACKAGE_3, 1);
 
@@ -5870,6 +5859,8 @@
 
         shutdownServices();
 
+        mInjectedCurrentTimeMillis += 100;
+
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                 R.xml.shortcut_0);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d75dd7d..dcf2f06 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4650,32 +4650,46 @@
 
     /* <p>Requires permission:
      * @link android.Manifest.permission#CALL_PHONE}
+     * @param ussdRequest the USSD command to be executed.
+     * @param wrappedCallback receives a callback result.
      */
     @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public void sendUssdRequest(String ussdRequest,
                                 final OnReceiveUssdResponseCallback callback, Handler handler) {
-       checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+        sendUssdRequest(ussdRequest, getSubId(), callback, handler);
+    }
 
-       ResultReceiver wrappedCallback = new ResultReceiver(handler) {
-           @Override
-           protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
-              Rlog.d(TAG, "USSD:" + resultCode);
-              checkNotNull(ussdResponse, "ussdResponse cannot be null.");
-              UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+   /* <p>Requires permission:
+    * @link android.Manifest.permission#CALL_PHONE}
+    * @param subId The subscription to use.
+    * @param ussdRequest the USSD command to be executed.
+    * @param wrappedCallback receives a callback result.
+    */
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
+    public void sendUssdRequest(String ussdRequest, int subId,
+                                final OnReceiveUssdResponseCallback callback, Handler handler) {
+        checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
 
-              if (resultCode == USSD_RETURN_SUCCESS) {
-                 callback.onReceiveUssdResponse(response.getUssdRequest(),
-                         response.getReturnMessage());
-              } else {
-                 callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
-              }
-           }
+        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
+                Rlog.d(TAG, "USSD:" + resultCode);
+                checkNotNull(ussdResponse, "ussdResponse cannot be null.");
+                UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+
+                if (resultCode == USSD_RETURN_SUCCESS) {
+                    callback.onReceiveUssdResponse(response.getUssdRequest(),
+                            response.getReturnMessage());
+                } else {
+                    callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+                }
+            }
         };
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.handleUssdRequest(ussdRequest, wrappedCallback);
+                telephony.handleUssdRequest(subId, ussdRequest, wrappedCallback);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4c66be1..9c62988 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -275,10 +275,11 @@
     /**
      * Handles USSD commands.
      *
+     * @param subId The subscription to use.
      * @param ussdRequest the USSD command to be executed.
      * @param wrappedCallback receives a callback result.
      */
-    void handleUssdRequest(String ussdRequest, in ResultReceiver wrappedCallback);
+    void handleUssdRequest(int subId, String ussdRequest, in ResultReceiver wrappedCallback);
 
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 8dd176d..a3404e5 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
 static const char* sMajorVersion = "2";
 
 // Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "2";
+static const char* sMinorVersion = "3";
 
 int PrintVersion() {
   std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index 1d414743..3eef7aa7 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -41,6 +41,8 @@
       return "dimen";
     case ResourceType::kDrawable:
       return "drawable";
+    case ResourceType::kFont:
+      return "font";
     case ResourceType::kFraction:
       return "fraction";
     case ResourceType::kId:
@@ -83,6 +85,7 @@
     {"color", ResourceType::kColor},
     {"dimen", ResourceType::kDimen},
     {"drawable", ResourceType::kDrawable},
+    {"font", ResourceType::kFont},
     {"fraction", ResourceType::kFraction},
     {"id", ResourceType::kId},
     {"integer", ResourceType::kInteger},
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 78acb70..13330b5 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -46,6 +46,7 @@
   kColor,
   kDimen,
   kDrawable,
+  kFont,
   kFraction,
   kId,
   kInteger,
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index 720ab91..6acb4d3 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -57,6 +57,10 @@
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kDrawable);
 
+  type = ParseResourceType("font");
+  ASSERT_NE(type, nullptr);
+  EXPECT_EQ(*type, ResourceType::kFont);
+
   type = ParseResourceType("fraction");
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kFraction);
diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont-italic.ttf b/tools/aapt2/integration-tests/AppOne/res/font/myfont-italic.ttf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/font/myfont-italic.ttf
diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont-normal.ttf b/tools/aapt2/integration-tests/AppOne/res/font/myfont-normal.ttf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/font/myfont-normal.ttf
diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont.xml b/tools/aapt2/integration-tests/AppOne/res/font/myfont.xml
new file mode 100644
index 0000000..1fb6791
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/font/myfont.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/myfont-normal" />
+    <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/myfont-italic" />
+</font-family>
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 93c790d..ac411b1 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,9 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.3
+### `aapt2`
+- Support new `font` resource type.
+
 ## Version 2.2
 ### `aapt2 compile ...`
 - Added support for inline complex XML resources. See