Merge "DO NOT MERGE CEC: Queue actions for starting later when not ready" 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 2eba29a..8917928 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/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/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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f8f20dc..a5a622c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5320,6 +5320,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();