am f5f54dd6: am 92dd1abe: Update restored task uid to match the package uid on current device. automerge: 7fd985f

* commit 'f5f54dd69122bc07ea0a25b8d98b9048cbe4582f':
  Update restored task uid to match the package uid on current device.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a2f5c15..fe25a17 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15464,6 +15464,9 @@
                                         removeUriPermissionsForPackageLocked(ssp, userId, true);
 
                                         removeTasksByPackageNameLocked(ssp, userId);
+                                        if (userId == UserHandle.USER_OWNER) {
+                                            mTaskPersister.removeFromPackageCache(ssp);
+                                        }
                                     }
                                 } else {
                                     removeTasksByRemovedPackageComponentsLocked(ssp, userId);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index cb693dd..af6a314 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -81,7 +81,7 @@
     private static final String ATTR_USERID = "user_id";
     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
-    private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
+    static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
@@ -90,7 +90,7 @@
     final IApplicationToken.Stub appToken; // window manager token
     final ActivityInfo info; // all about me
     final ApplicationInfo appInfo; // information about activity's app
-    final int launchedFromUid; // always the uid who started the activity.
+    int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
     final int userId;          // Which user is this running for?
     final Intent intent;    // the original intent that generated us
@@ -1141,8 +1141,8 @@
         }
     }
 
-    static ActivityRecord restoreFromXml(XmlPullParser in,
-            ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
+    static ActivityRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
+            throws IOException, XmlPullParserException {
         Intent intent = null;
         PersistableBundle persistentState = null;
         int launchedFromUid = 0;
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 9ac1a24..318cd45 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -133,6 +133,8 @@
     // Data organization: <packageNameOfAffiliateTask, listOfAffiliatedTasksChains>
     private ArrayMap<String, List<List<OtherDeviceTask>>> mOtherDeviceTasksMap =
                 new ArrayMap<>(10);
+    // Local cache of package names to uid used when restoring a task from another device.
+    private ArrayMap<String, Integer> mPackageUidMap;
 
     // The next time in milliseconds we will remove expired task from
     // {@link #mOtherDeviceTasksMap} and disk. Set to {@link Long.MAX_VALUE} to never clean-up
@@ -583,7 +585,12 @@
     private void removeExpiredTasksIfNeeded() {
         synchronized (mOtherDeviceTasksMap) {
             final long now = System.currentTimeMillis();
-            if (mOtherDeviceTasksMap.isEmpty() || now < mExpiredTasksCleanupTime) {
+            final boolean noMoreTasks = mOtherDeviceTasksMap.isEmpty();
+            if (noMoreTasks || now < mExpiredTasksCleanupTime) {
+                if (noMoreTasks && mPackageUidMap != null) {
+                    // All done! package->uid map no longer needed.
+                    mPackageUidMap = null;
+                }
                 return;
             }
 
@@ -636,6 +643,20 @@
                 if (DEBUG_RESTORER) Slog.d(TAG, "Reset expiration time to "
                             + DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
                             DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
+            } else {
+                // All done! package->uid map no longer needed.
+                mPackageUidMap = null;
+            }
+        }
+    }
+
+    /**
+     * Removes the input package name from the local package->uid map.
+     */
+    void removeFromPackageCache(String packageName) {
+        synchronized (mOtherDeviceTasksMap) {
+            if (mPackageUidMap != null) {
+                mPackageUidMap.remove(packageName);
             }
         }
     }
@@ -781,6 +802,27 @@
                             task.mAffiliatedTaskId = INVALID_TASK_ID;
                             task.mPrevAffiliateTaskId = INVALID_TASK_ID;
                             task.mNextAffiliateTaskId = INVALID_TASK_ID;
+                            // Set up uids valid for this device.
+                            Integer uid = mPackageUidMap.get(task.realActivity.getPackageName());
+                            if (uid == null) {
+                                // How did this happen???
+                                Slog.wtf(TAG, "Can't find uid for task=" + task
+                                        + " in mPackageUidMap=" + mPackageUidMap);
+                                return null;
+                            }
+                            task.effectiveUid = task.mCallingUid = uid;
+                            for (int i = task.mActivities.size() - 1; i >= 0; --i) {
+                                final ActivityRecord activity = task.mActivities.get(i);
+                                uid = mPackageUidMap.get(activity.launchedFromPackage);
+                                if (uid == null) {
+                                    // How did this happen??
+                                    Slog.wtf(TAG, "Can't find uid for activity=" + activity
+                                            + " in mPackageUidMap=" + mPackageUidMap);
+                                    return null;
+                                }
+                                activity.launchedFromUid = uid;
+                            }
+
                         } else {
                             Slog.e(TAG, "Unable to create task for backed-up file=" + file + ": "
                                         + fileToString(file));
@@ -804,42 +846,81 @@
 
     /**
      * Returns true if the input task chain backed-up from another device can be restored on this
-     * device.
+     * device. Also, sets the {@link OtherDeviceTask#mUid} on the input tasks if they can be
+     * restored.
      */
     private boolean canAddOtherDeviceTaskChain(List<OtherDeviceTask> chain) {
 
-        // Get component names of all the tasks in the chain.
-        // Mainly doing this to reduce checking for a component twice if two or more
-        // affiliations belong to the same component which is highly likely.
-        ArraySet<ComponentName> componentsToCheck = new ArraySet<>();
+        final ArraySet<ComponentName> validComponents = new ArraySet<>();
+        final IPackageManager pm = AppGlobals.getPackageManager();
         for (int i = 0; i < chain.size(); i++) {
 
             OtherDeviceTask task = chain.get(i);
             // Quick check, we can't add the task chain if any of its task files don't exist.
             if (!task.mFile.exists()) {
-                if (DEBUG_RESTORER)
-                        Slog.d(TAG, "Can't add chain due to missing file=" + task.mFile);
+                if (DEBUG_RESTORER) Slog.d(TAG,
+                        "Can't add chain due to missing file=" + task.mFile);
                 return false;
             }
-            componentsToCheck.add(task.mComponentName);
+
+            // Verify task package is installed.
+            if (!isPackageInstalled(task.mComponentName.getPackageName())) {
+                return false;
+            }
+            // Verify that all the launch packages are installed.
+            if (task.mLaunchPackages != null) {
+                for (int j = task.mLaunchPackages.size() - 1; j >= 0; --j) {
+                    if (!isPackageInstalled(task.mLaunchPackages.valueAt(j))) {
+                        return false;
+                    }
+                }
+            }
+
+            if (validComponents.contains(task.mComponentName)) {
+                // Existance of component has already been verified.
+                continue;
+            }
+
+            // Check to see if the specific component is installed.
+            try {
+                if (pm.getActivityInfo(task.mComponentName, 0, UserHandle.USER_OWNER) == null) {
+                    // Component isn't installed...
+                    return false;
+                }
+                validComponents.add(task.mComponentName);
+            } catch (RemoteException e) {
+                // Should not happen???
+                return false;
+            }
         }
 
-        boolean canAdd = true;
+        return true;
+    }
+
+    /**
+     * Returns true if the input package name is installed. If the package is installed, an entry
+     * for the package is added to {@link #mPackageUidMap}.
+     */
+    private boolean isPackageInstalled(final String packageName) {
+        if (mPackageUidMap != null && mPackageUidMap.containsKey(packageName)) {
+            return true;
+        }
         try {
-            // Check to see if all the components for this task chain are installed.
-            final IPackageManager pm = AppGlobals.getPackageManager();
-            for (int i = 0; canAdd && i < componentsToCheck.size(); i++) {
-                ComponentName cn = componentsToCheck.valueAt(i);
-                canAdd &= pm.getActivityInfo(cn, 0, UserHandle.USER_OWNER) != null;
-                if (DEBUG_RESTORER) Slog.d(TAG, "ComponentName=" + cn + " installed=" + canAdd);
+            int uid = AppGlobals.getPackageManager().getPackageUid(
+                    packageName, UserHandle.USER_OWNER);
+            if (uid == -1) {
+                // package doesn't exist...
+                return false;
             }
+            if (mPackageUidMap == null) {
+                mPackageUidMap = new ArrayMap<>();
+            }
+            mPackageUidMap.put(packageName, uid);
+            return true;
         } catch (RemoteException e) {
             // Should not happen???
-            canAdd = false;
+            return false;
         }
-
-        if (DEBUG_RESTORER) Slog.d(TAG, "canAdd=" + canAdd);
-        return canAdd;
     }
 
     private class LazyTaskWriterThread extends Thread {
@@ -995,12 +1076,17 @@
         final int mTaskId;
         final int mAffiliatedTaskId;
 
-        private OtherDeviceTask(
-                File file, ComponentName componentName, int taskId, int affiliatedTaskId) {
+        // Names of packages that launched activities in this task. All packages listed here need
+        // to be installed on the current device in order for the task to be restored successfully.
+        final ArraySet<String> mLaunchPackages;
+
+        private OtherDeviceTask(File file, ComponentName componentName, int taskId,
+                int affiliatedTaskId, ArraySet<String> launchPackages) {
             mFile = file;
             mComponentName = componentName;
             mTaskId = taskId;
             mAffiliatedTaskId = (affiliatedTaskId == INVALID_TASK_ID) ? taskId: affiliatedTaskId;
+            mLaunchPackages = launchPackages;
         }
 
         @Override
@@ -1038,6 +1124,7 @@
                     final String name = in.getName();
 
                     if (TAG_TASK.equals(name)) {
+                        final int outerDepth = in.getDepth();
                         ComponentName componentName = null;
                         int taskId = INVALID_TASK_ID;
                         int taskAffiliation = INVALID_TASK_ID;
@@ -1058,10 +1145,31 @@
                                     + " taskId=" + taskId + " file=" + file);
                             return null;
                         }
+
+                        ArraySet<String> launchPackages = null;
+                        while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
+                                (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+                            if (event == XmlPullParser.START_TAG) {
+                                if (TaskRecord.TAG_ACTIVITY.equals(in.getName())) {
+                                    for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
+                                        if (ActivityRecord.ATTR_LAUNCHEDFROMPACKAGE.equals(
+                                                in.getAttributeName(j))) {
+                                            if (launchPackages == null) {
+                                                launchPackages = new ArraySet();
+                                            }
+                                            launchPackages.add(in.getAttributeValue(j));
+                                        }
+                                    }
+                                } else {
+                                    XmlUtils.skipCurrentTag(in);
+                                }
+                            }
+                        }
                         if (DEBUG_RESTORER) Slog.d(TAG, "creating OtherDeviceTask from file="
                                 + file.getName() + " componentName=" + componentName
-                                + " taskId=" + taskId);
-                        return new OtherDeviceTask(file, componentName, taskId, taskAffiliation);
+                                + " taskId=" + taskId + " launchPackages=" + launchPackages);
+                        return new OtherDeviceTask(file, componentName, taskId,
+                                taskAffiliation, launchPackages);
                     } else {
                         Slog.wtf(TAG,
                                 "createFromFile: Unknown xml event=" + event + " name=" + name);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 21302b2..3011148 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -59,7 +59,7 @@
     private static final String TAG_AFFINITYINTENT = "affinity_intent";
     static final String ATTR_REALACTIVITY = "real_activity";
     private static final String ATTR_ORIGACTIVITY = "orig_activity";
-    private static final String TAG_ACTIVITY = "activity";
+    static final String TAG_ACTIVITY = "activity";
     private static final String ATTR_AFFINITY = "affinity";
     private static final String ATTR_ROOT_AFFINITY = "root_affinity";
     private static final String ATTR_ROOTHASRESET = "root_has_reset";