Merge "Fix admin policies in managed profiles" into lmp-dev
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0e98175..4b705dd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3847,14 +3847,14 @@
      * their launch had come from the original activity.
      * @hide
      */
-    public void startActivityAsCaller(Intent intent, @Nullable Bundle options) {
+    public void startActivityAsCaller(Intent intent, @Nullable Bundle options, int userId) {
         if (mParent != null) {
             throw new RuntimeException("Can't be called from a child");
         }
         Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivityAsCaller(
                         this, mMainThread.getApplicationThread(), mToken, this,
-                        intent, -1, options);
+                        intent, -1, options, userId);
         if (ar != null) {
             mMainThread.sendActivityResult(
                 mToken, mEmbeddedID, -1, ar.getResultCode(),
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6c67c09..4e2ff0b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -184,8 +184,9 @@
                     ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             int result = startActivityAsCaller(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
+                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -2435,7 +2436,7 @@
     }
     public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
+            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -2459,6 +2460,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b72addf..be26f30 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -69,7 +69,7 @@
             ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
     public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
+            int flags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
     public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options,
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ba3a234..60a013e 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1671,7 +1671,7 @@
      */
     public ActivityResult execStartActivityAsCaller(
             Context who, IBinder contextThread, IBinder token, Activity target,
-            Intent intent, int requestCode, Bundle options) {
+            Intent intent, int requestCode, Bundle options, int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
             synchronized (mSync) {
@@ -1695,7 +1695,7 @@
                 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
                         token, target != null ? target.mEmbeddedID : null,
-                        requestCode, 0, null, options);
+                        requestCode, 0, null, options, userId);
             checkStartActivityResult(result, intent);
         } catch (RemoteException e) {
         }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a9d16bc..a30ae57 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -439,14 +439,20 @@
             = "android.app.action.SET_NEW_PASSWORD";
 
     /**
-     * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
-     * managed profile to its parent.
+     * Flag used by {@link #addCrossProfileIntentFilter} to allow access
+     * <em>from</em> a managed profile <em>to</em> its parent. That is, any
+     * matching activities in the parent profile are included in the
+     * disambiguation list shown when an app in the managed profile calls
+     * {@link Activity#startActivity(Intent)}.
      */
     public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
 
     /**
-     * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the
-     * parent to its managed profile.
+     * Flag used by {@link #addCrossProfileIntentFilter} to allow access
+     * <em>from</em> a parent <em>to</em> its managed profile. That is, any
+     * matching activities in the managed profile are included in the
+     * disambiguation list shown when an app in the parent profile calls
+     * {@link Activity#startActivity(Intent)}.
      */
     public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
 
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 6daefc8..ba62cd6 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -20,6 +20,7 @@
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.PackageInstaller;
+import android.content.pm.ParceledListSlice;
 import android.content.IntentSender;
 
 import android.graphics.Bitmap;
@@ -37,8 +38,8 @@
 
     PackageInstaller.SessionInfo getSessionInfo(int sessionId);
 
-    List<PackageInstaller.SessionInfo> getAllSessions(int userId);
-    List<PackageInstaller.SessionInfo> getMySessions(String installerPackageName, int userId);
+    ParceledListSlice getAllSessions(int userId);
+    ParceledListSlice getMySessions(String installerPackageName, int userId);
 
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 765b2a9..b66bd01 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -235,6 +235,9 @@
     public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
 
     /** @hide */
+    public boolean coreApp;
+
+    /** @hide */
     public boolean requiredForAllUsers;
 
     /** @hide */
@@ -293,6 +296,7 @@
         dest.writeTypedArray(reqFeatures, parcelableFlags);
         dest.writeTypedArray(featureGroups, parcelableFlags);
         dest.writeInt(installLocation);
+        dest.writeInt(coreApp ? 1 : 0);
         dest.writeInt(requiredForAllUsers ? 1 : 0);
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
@@ -337,6 +341,7 @@
         reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
         featureGroups = source.createTypedArray(FeatureGroupInfo.CREATOR);
         installLocation = source.readInt();
+        coreApp = source.readInt() != 0;
         requiredForAllUsers = source.readInt() != 0;
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index f249c5f..80efd0b 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -399,7 +399,7 @@
         }
 
         try {
-            return mInstaller.getAllSessions(mUserId);
+            return mInstaller.getAllSessions(mUserId).getList();
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -410,7 +410,7 @@
      */
     public @NonNull List<SessionInfo> getMySessions() {
         try {
-            return mInstaller.getMySessions(mInstallerPackageName, mUserId);
+            return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3364741..ca4ff6a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -415,6 +415,7 @@
         pi.sharedUserLabel = p.mSharedUserLabel;
         pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
         pi.installLocation = p.installLocation;
+        pi.coreApp = p.coreApp;
         if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
                 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
             pi.requiredForAllUsers = p.mRequiredForAllUsers;
@@ -1384,6 +1385,8 @@
                 PARSE_DEFAULT_INSTALL_LOCATION);
         pkg.applicationInfo.installLocation = pkg.installLocation;
 
+        pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
+
         sa.recycle();
 
         /* Set the global "forward lock" flag */
@@ -4267,6 +4270,8 @@
 
         public int installLocation;
 
+        public boolean coreApp;
+
         /* An app that's required for all users and cannot be uninstalled for a user */
         public boolean mRequiredForAllUsers;
 
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index d9493752..6e2f84a 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -20,26 +20,28 @@
 
 import android.app.Activity;
 import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
 import android.app.AppGlobals;
-import android.os.Bundle;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.content.pm.UserInfo;
+import android.os.Bundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
 import android.widget.Toast;
+
 import java.util.List;
-import java.util.Set;
 
-/*
- * This is used in conjunction with the {@link setCrossProfileIntentFilter} method of
- * {@link DevicePolicyManager} to enable intents to be passed in and out of a managed profile.
+/**
+ * This is used in conjunction with
+ * {@link DevicePolicyManager#addCrossProfileIntentFilter} to enable intents to
+ * be passed in and out of a managed profile.
  */
-
 public class IntentForwarderActivity extends Activity  {
 
     public static String TAG = "IntentForwarderActivity";
@@ -104,7 +106,23 @@
             final boolean shouldShowDisclosure =
                     !UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID);
 
-            startActivityAsUser(newIntent, userDest);
+            try {
+                startActivityAsCaller(newIntent, null, userDest.getIdentifier());
+            } catch (RuntimeException e) {
+                int launchedFromUid = -1;
+                String launchedFromPackage = "?";
+                try {
+                    launchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
+                            getActivityToken());
+                    launchedFromPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage(
+                            getActivityToken());
+                } catch (RemoteException ignored) {
+                }
+
+                Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package "
+                        + launchedFromPackage + ", while running in "
+                        + ActivityThread.currentProcessName(), e);
+            }
 
             if (shouldShowDisclosure) {
                 Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index aa55d23..0062e2d 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -641,7 +641,7 @@
             return;
         }
         try {
-            startActivityAsCaller(intent, null);
+            startActivityAsCaller(intent, null, UserHandle.USER_NULL);
         } catch (RuntimeException e) {
             String launchedFromPackage;
             try {
diff --git a/core/res/res/values-mcc234-mnc08/config.xml b/core/res/res/values-mcc234-mnc08/config.xml
new file mode 100644
index 0000000..13d4d8f
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc08/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23430</item>
+        <item>23433</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4aabc84..c156887 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4839,17 +4839,17 @@
     <string name="day_of_week_label_typeface">sans-serif</string>
 
     <!-- Notify use that they are in Lock-to-app -->
-    <string name="lock_to_app_toast">To unpin this screen, touch and hold  Back and Recents at the same time.</string>
+    <string name="lock_to_app_toast">To unpin this screen, touch and hold Back and Overview at the same time.</string>
     <!-- Notify use that they are in Lock-to-app in accessibility mode -->
-    <string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Recents.</string>
+    <string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Overview.</string>
     <!-- Notify user that they are locked in lock-to-app mode -->
     <string name="lock_to_app_toast_locked">Screen is pinned. Unpinning isn\'t allowed by your organization.</string>
     <!-- Lock-to-app dialog title. -->
     <string name="lock_to_app_title">Use screen pinning?</string>
     <!-- Lock-to-app dialog description. -->
-    <string name="lock_to_app_description">Screen pinning locks the display in a single view.\n\nTo exit, touch and hold Back and Recents at the same time.</string>
+    <string name="lock_to_app_description">Screen pinning locks the display in a single view.\n\nTo unpin, touch and hold Back and Overview at the same time.</string>
     <!-- Lock-to-app dialog description when in accessibility mode. -->
-    <string name="lock_to_app_description_accessible">Screen pinning locks the display in a single view.\n\nTo exit, touch and hold Recents.</string>
+    <string name="lock_to_app_description_accessible">Screen pinning locks the display in a single view.\n\nTo unpin, touch and hold Overview.</string>
     <!-- Lock-to-app negative response. -->
     <string name="lock_to_app_negative">NO, THANKS</string>
     <!-- Lock-to-app positive response. -->
diff --git a/docs/html/design/media/dialogs_examples.png b/docs/html/design/media/dialogs_examples.png
index 6ffcee2..c136476 100644
--- a/docs/html/design/media/dialogs_examples.png
+++ b/docs/html/design/media/dialogs_examples.png
Binary files differ
diff --git a/docs/html/design/media/navigation_drawer_titles_icons.png b/docs/html/design/media/navigation_drawer_titles_icons.png
index 902a72d..7cf1e0c 100644
--- a/docs/html/design/media/navigation_drawer_titles_icons.png
+++ b/docs/html/design/media/navigation_drawer_titles_icons.png
Binary files differ
diff --git a/docs/html/design/media/selection_adjusting_actions.png b/docs/html/design/media/selection_adjusting_actions.png
index 32a7fec..0799b6b 100644
--- a/docs/html/design/media/selection_adjusting_actions.png
+++ b/docs/html/design/media/selection_adjusting_actions.png
Binary files differ
diff --git a/docs/html/design/media/touch_feedback_communication.png b/docs/html/design/media/touch_feedback_communication.png
index 1d4a9dc..f8162d0 100644
--- a/docs/html/design/media/touch_feedback_communication.png
+++ b/docs/html/design/media/touch_feedback_communication.png
Binary files differ
diff --git a/docs/html/design/media/ui_overview_notifications.png b/docs/html/design/media/ui_overview_notifications.png
index 7975657..6043412 100644
--- a/docs/html/design/media/ui_overview_notifications.png
+++ b/docs/html/design/media/ui_overview_notifications.png
Binary files differ
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 84ada6f..20254f0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -286,7 +286,9 @@
                 mFileProvider, new RemotePrintDocument.RemoteAdapterDeathObserver() {
             @Override
             public void onDied() {
-                if (isFinishing()) {
+                // If we are finishing or we are in a state that we do not need any
+                // data from the printing app, then no need to finish.
+                if (isFinishing() || (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
                     return;
                 }
                 setState(STATE_PRINT_CANCELED);
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9ee18f3..71b9b61 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -40,8 +40,8 @@
 
     <!-- Message that is read when you enter recent apps in TalkBack -->
     <plurals name="status_bar_accessibility_recent_apps">
-        <item quantity="one">1 recent app</item>
-        <item quantity="other">%d recent apps</item>
+        <item quantity="one">1 screen in Overview</item>
+        <item quantity="other">%d screens in Overview</item>
     </plurals>
 
     <!-- The label in the bar at the top of the status bar when there are no notifications
@@ -206,7 +206,7 @@
     <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_menu">Menu</string>
     <!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_recent">Recent screens</string>
+    <string name="accessibility_recent">Overview</string>
     <!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] -->
     <string name="accessibility_search_light">Search</string>
     <!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -413,7 +413,7 @@
     <!-- Content description for the settings button in the status bar header. [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_settings">Settings</string>
     <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_recent_apps">Recent screens.</string>
+    <string name="accessibility_desc_recent_apps">Overview.</string>
 
     <!-- Content description of the user tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index d8c99f8..a7ff0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -372,6 +372,7 @@
     }
 
     protected void onTrackingStarted() {
+        mClosing = false;
         mTracking = true;
         mCollapseAfterPeek = false;
         mBar.onTrackingStarted(PanelView.this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index e4a1c27..853628e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -738,8 +738,9 @@
             if (mExpandedOnStart) {
 
                 // We are collapsing the shade, so the first child can get as most as high as the
-                // current height.
-                mFirstChildMaxHeight = mFirstChildWhileExpanding.getActualHeight();
+                // current height or the end value of the animation.
+                mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
+                        mFirstChildWhileExpanding);
             } else {
                 updateFirstChildMaxSizeToMaxHeight();
             }
@@ -801,9 +802,14 @@
         this.mIsExpanded = isExpanded;
     }
 
-    public void notifyChildrenChanged(ViewGroup hostView) {
+    public void notifyChildrenChanged(final ViewGroup hostView) {
         if (mIsExpansionChanging) {
-            updateFirstChildHeightWhileExpanding(hostView);
+            hostView.post(new Runnable() {
+                @Override
+                public void run() {
+                    updateFirstChildHeightWhileExpanding(hostView);
+                }
+            });
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index a69390e..433357e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -709,7 +709,7 @@
         };
     }
 
-    private <T> T getChildTag(View child, int tag) {
+    private static <T> T getChildTag(View child, int tag) {
         return (T) child.getTag(tag);
     }
 
@@ -848,4 +848,20 @@
             currentAnimator.cancel();
         }
     }
+
+    /**
+     * Get the end value of the height animation running on a view or the actualHeight
+     * if no animation is running.
+     */
+    public static int getFinalActualHeight(ExpandableView view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator heightAnimator = getChildTag(view, TAG_ANIMATOR_HEIGHT);
+        if (heightAnimator == null) {
+            return view.getActualHeight();
+        } else {
+            return getChildTag(view, TAG_END_HEIGHT);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8357366..8dfb321 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3561,7 +3561,7 @@
     @Override
     public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
+            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
 
         // This is very dangerous -- it allows you to perform a start activity (including
         // permission grants) as any app that may launch one of your own activities.  So
@@ -3599,11 +3599,15 @@
             targetPackage = sourceRecord.launchedFromPackage;
         }
 
+        if (userId == UserHandle.USER_NULL) {
+            userId = UserHandle.getUserId(sourceRecord.app.uid);
+        }
+
         // TODO: Switch to user app stacks here.
         try {
             int ret = mStackSupervisor.startActivityMayWait(null, targetUid, targetPackage, intent,
                     resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null,
-                    null, null, options, UserHandle.getUserId(sourceRecord.app.uid), null, null);
+                    null, null, options, userId, null, null);
             return ret;
         } catch (SecurityException e) {
             // XXX need to figure out how to propagate to original app.
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 198273e..1a0e45e 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -205,17 +205,20 @@
                     pw.print(" resultWho="); pw.print(resultWho);
                     pw.print(" resultCode="); pw.println(requestCode);
         }
-        final String iconFilename = taskDescription.getIconFilename();
-        if (iconFilename != null || taskDescription.getLabel() != null ||
-                taskDescription.getPrimaryColor() != 0) {
-            pw.print(prefix); pw.print("taskDescription:");
-                    pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
-                    pw.print(" label=\""); pw.print(taskDescription.getLabel()); pw.print("\"");
-                    pw.print(" color=");
-                    pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
-        }
-        if (iconFilename == null && taskDescription.getIcon() != null) {
-            pw.print(prefix); pw.println("taskDescription contains Bitmap");
+        if (taskDescription != null) {
+            final String iconFilename = taskDescription.getIconFilename();
+            if (iconFilename != null || taskDescription.getLabel() != null ||
+                    taskDescription.getPrimaryColor() != 0) {
+                pw.print(prefix); pw.print("taskDescription:");
+                        pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
+                        pw.print(" label=\""); pw.print(taskDescription.getLabel());
+                                pw.print("\"");
+                        pw.print(" color=");
+                        pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
+            }
+            if (iconFilename == null && taskDescription.getIcon() != null) {
+                pw.print(prefix); pw.println("taskDescription contains Bitmap");
+            }
         }
         if (results != null) {
             pw.print(prefix); pw.print("results="); pw.println(results);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index b2300a6..fc53c50 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -73,8 +73,9 @@
     }
 
     /**
-     * Called right after the action is created. Initialization or first step to take
-     * for the action can be done in this method.
+     * Called after the action is created. Initialization or first step to take
+     * for the action can be done in this method. Shall update {@code mState} to
+     * indicate that the action has started.
      *
      * @return true if the operation is successful; otherwise false.
      */
@@ -162,6 +163,10 @@
         mActionTimer.sendTimerMessage(state, delayMillis);
     }
 
+    boolean started() {
+        return mState != STATE_NONE;
+    }
+
     protected final void sendCommand(HdmiCecMessage cmd) {
         mService.sendCecCommand(cmd);
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 41ac589..8f9af61 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -617,14 +617,25 @@
     @ServiceThreadOnly
     void addAndStartAction(final HdmiCecFeatureAction action) {
         assertRunOnServiceThread();
+        mActions.add(action);
         if (mService.isPowerStandbyOrTransient()) {
-            Slog.w(TAG, "Skip the action during Standby: " + action);
+            Slog.i(TAG, "Not ready to start action. Queued for deferred start:" + action);
             return;
         }
-        mActions.add(action);
         action.start();
     }
 
+    @ServiceThreadOnly
+    void startQueuedActions() {
+        assertRunOnServiceThread();
+        for (HdmiCecFeatureAction action : mActions) {
+            if (!action.started()) {
+                Slog.i(TAG, "Starting queued action:" + action);
+                action.start();
+            }
+        }
+    }
+
     // See if we have an action of a given type in progress.
     @ServiceThreadOnly
     <T extends HdmiCecFeatureAction> boolean hasAction(final Class<T> clazz) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index b0ddf2ac..780d54b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -39,11 +39,18 @@
     }
 
     @Override
+    void init() {
+        super.init();
+        mIsActiveSource = false;
+    }
+
+    @Override
     @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress, int reason) {
         assertRunOnServiceThread();
         mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                 mAddress, mService.getPhysicalAddress(), mDeviceType));
+        startQueuedActions();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index bd9f04b..0fb4b48 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -142,6 +142,7 @@
         launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
                 reason != HdmiControlService.INITIATED_BY_BOOT_UP);
         launchDeviceDiscovery();
+        startQueuedActions();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 4d9b4e9..60d1520 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -415,12 +415,17 @@
         assertRunOnServiceThread();
         // A container for [Device type, Local device info].
         ArrayList<HdmiCecLocalDevice> localDevices = new ArrayList<>();
-        clearLocalDevices();
         for (int type : mLocalDevices) {
-            final HdmiCecLocalDevice localDevice = HdmiCecLocalDevice.create(this, type);
+            HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type);
+            if (localDevice == null) {
+                localDevice = HdmiCecLocalDevice.create(this, type);
+            }
             localDevice.init();
             localDevices.add(localDevice);
         }
+        // It's now safe to flush existing local devices from mCecController since they were
+        // already moved to 'localDevices'.
+        clearLocalDevices();
         allocateLogicalAddress(localDevices, initiatedBy);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9db3fba..2150e9a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -45,6 +45,7 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
@@ -714,7 +715,7 @@
     }
 
     @Override
-    public List<SessionInfo> getAllSessions(int userId) {
+    public ParceledListSlice<SessionInfo> getAllSessions(int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getAllSessions");
 
         final List<SessionInfo> result = new ArrayList<>();
@@ -726,11 +727,11 @@
                 }
             }
         }
-        return result;
+        return new ParceledListSlice<>(result);
     }
 
     @Override
-    public List<SessionInfo> getMySessions(String installerPackageName, int userId) {
+    public ParceledListSlice<SessionInfo> getMySessions(String installerPackageName, int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getMySessions");
         mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName);
 
@@ -744,7 +745,7 @@
                 }
             }
         }
-        return result;
+        return new ParceledListSlice<>(result);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a8a946a..b79e157 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -80,6 +80,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.admin.IDevicePolicyManager;
 import android.app.backup.IBackupManager;
@@ -4471,62 +4472,164 @@
         }
 
         if (pkgs != null) {
-            // Filter out packages that aren't recently used.
-            //
-            // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
-            // should do a full dexopt.
-            if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
-                // TODO: add a property to control this?
-                long dexOptLRUThresholdInMinutes;
-                if (mLazyDexOpt) {
-                    dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
-                } else {
-                    dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
-                }
-                long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
-
-                int total = pkgs.size();
-                int skipped = 0;
-                long now = System.currentTimeMillis();
-                for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
-                    PackageParser.Package pkg = i.next();
-                    long then = pkg.mLastPackageUsageTimeInMills;
-                    if (then + dexOptLRUThresholdInMills < now) {
-                        if (DEBUG_DEXOPT) {
-                            Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
-                                  ((then == 0) ? "never" : new Date(then)));
-                        }
-                        i.remove();
-                        skipped++;
+            // Sort apps by importance for dexopt ordering. Important apps are given more priority
+            // in case the device runs out of space.
+            ArrayList<PackageParser.Package> sortedPkgs = new ArrayList<PackageParser.Package>();
+            // Give priority to core apps.
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (pkg.coreApp) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding core app " + sortedPkgs.size() + ": " + pkg.packageName);
                     }
+                    sortedPkgs.add(pkg);
+                    it.remove();
                 }
+            }
+            // Give priority to system apps that listen for pre boot complete.
+            Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
+            HashSet<String> pkgNames = getPackageNamesForIntent(intent);
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (pkgNames.contains(pkg.packageName)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding pre boot system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
+            // Give priority to system apps.
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
+            // Give priority to updated system apps.
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (isUpdatedSystemApp(pkg)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
+            // Give priority to apps that listen for boot complete.
+            intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
+            pkgNames = getPackageNamesForIntent(intent);
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (pkgNames.contains(pkg.packageName)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
+            // Filter out packages that aren't recently used.
+            filterRecentlyUsedApps(pkgs);
+            // Add all remaining apps.
+            for (PackageParser.Package pkg : pkgs) {
                 if (DEBUG_DEXOPT) {
-                    Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+                    Log.i(TAG, "Adding app " + sortedPkgs.size() + ": " + pkg.packageName);
                 }
+                sortedPkgs.add(pkg);
             }
 
             int i = 0;
-            for (PackageParser.Package pkg : pkgs) {
-                i++;
-                if (DEBUG_DEXOPT) {
-                    Log.i(TAG, "Optimizing app " + i + " of " + pkgs.size()
-                          + ": " + pkg.packageName);
+            int total = sortedPkgs.size();
+            File dataDir = Environment.getDataDirectory();
+            long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
+            if (lowThreshold == 0) {
+                throw new IllegalStateException("Invalid low memory threshold");
+            }
+            for (PackageParser.Package pkg : sortedPkgs) {
+                long usableSpace = dataDir.getUsableSpace();
+                if (usableSpace < lowThreshold) {
+                    Log.w(TAG, "Not running dexopt on remaining apps due to low memory: " + usableSpace);
+                    break;
                 }
-                if (!isFirstBoot()) {
-                    try {
-                        ActivityManagerNative.getDefault().showBootMessage(
-                                mContext.getResources().getString(
-                                        R.string.android_upgrading_apk,
-                                        i, pkgs.size()), true);
-                    } catch (RemoteException e) {
+                performBootDexOpt(pkg, ++i, total);
+            }
+        }
+    }
+
+    private void filterRecentlyUsedApps(HashSet<PackageParser.Package> pkgs) {
+        // Filter out packages that aren't recently used.
+        //
+        // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
+        // should do a full dexopt.
+        if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
+            // TODO: add a property to control this?
+            long dexOptLRUThresholdInMinutes;
+            if (mLazyDexOpt) {
+                dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
+            } else {
+                dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
+            }
+            long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
+
+            int total = pkgs.size();
+            int skipped = 0;
+            long now = System.currentTimeMillis();
+            for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
+                PackageParser.Package pkg = i.next();
+                long then = pkg.mLastPackageUsageTimeInMills;
+                if (then + dexOptLRUThresholdInMills < now) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
+                              ((then == 0) ? "never" : new Date(then)));
                     }
-                }
-                PackageParser.Package p = pkg;
-                synchronized (mInstallLock) {
-                    performDexOptLI(p, null /* instruction sets */, false /* force dex */, false /* defer */,
-                            true /* include dependencies */);
+                    i.remove();
+                    skipped++;
                 }
             }
+            if (DEBUG_DEXOPT) {
+                Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+            }
+        }
+    }
+
+    private HashSet<String> getPackageNamesForIntent(Intent intent) {
+        List<ResolveInfo> ris = null;
+        try {
+            ris = AppGlobals.getPackageManager().queryIntentReceivers(
+                    intent, null, 0, UserHandle.USER_OWNER);
+        } catch (RemoteException e) {
+        }
+        HashSet<String> pkgNames = new HashSet<String>();
+        if (ris != null) {
+            for (ResolveInfo ri : ris) {
+                pkgNames.add(ri.activityInfo.packageName);
+            }
+        }
+        return pkgNames;
+    }
+
+    private void performBootDexOpt(PackageParser.Package pkg, int curr, int total) {
+        if (DEBUG_DEXOPT) {
+            Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName);
+        }
+        if (!isFirstBoot()) {
+            try {
+                ActivityManagerNative.getDefault().showBootMessage(
+                        mContext.getResources().getString(R.string.android_upgrading_apk,
+                                curr, total), true);
+            } catch (RemoteException e) {
+            }
+        }
+        PackageParser.Package p = pkg;
+        synchronized (mInstallLock) {
+            performDexOptLI(p, null /* instruction sets */, false /* force dex */,
+                            false /* defer */, true /* include dependencies */);
         }
     }
 
@@ -5077,6 +5180,9 @@
 
         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        } else {
+            // Only allow system apps to be flagged as core apps.
+            pkg.coreApp = false;
         }
 
         if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7dc2de2..af4ae44 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5316,6 +5316,9 @@
         @Override
         public List<String> getCrossProfileWidgetProviders(int profileId) {
             synchronized (DevicePolicyManagerService.this) {
+                if (mDeviceOwner == null) {
+                    return Collections.emptyList();
+                }
                 ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId);
                 if (ownerComponent == null) {
                     return Collections.emptyList();