OSDN Git Service

Remove activity from task if not set properly.
authorBryce Lee <brycelee@google.com>
Thu, 23 Feb 2017 00:39:06 +0000 (16:39 -0800)
committerBryce Lee <brycelee@google.com>
Mon, 27 Feb 2017 15:26:30 +0000 (07:26 -0800)
We do not start an activity in the case of a lock task mode
violation. However, the activity is still associated with the task
and therefore participates in future interactions, such as
visibility checks.

This changelist addresses this issue by removing the assocation in
the case of failures.

Change-Id: I77692465cb1082478528771fd6fd844fab62f697
Fixes: 35034729
Fixes: 35035258
Fixes: 34179495
Test: cts-tradefed run cts-dev --module DevicePolicyManager --test com.android.cts.devicepolicy.DeviceOwnerTest#testLockTask_deviceOwnerUser

services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityRecord.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java
services/core/java/com/android/server/am/ActivityStarter.java
services/core/java/com/android/server/am/TaskRecord.java

index d287d85..fb324ca 100644 (file)
@@ -3023,15 +3023,24 @@ public class ActivityManagerService extends IActivityManager.Stub
             startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
         } else {
             finishRunningVoiceLocked();
-            IVoiceInteractionSession session;
-            if (mLastResumedActivity != null
-                    && ((session = mLastResumedActivity.task.voiceSession) != null
-                    || (session = mLastResumedActivity.voiceSession) != null)) {
-                // We had been in a voice interaction session, but now focused has
-                // move to something different.  Just finish the session, we can't
-                // return to it and retain the proper state and synchronization with
-                // the voice interaction service.
-                finishVoiceTask(session);
+
+            if (mLastResumedActivity != null) {
+                final IVoiceInteractionSession session;
+
+                if (mLastResumedActivity.task != null
+                    && mLastResumedActivity.task.voiceSession != null) {
+                    session = mLastResumedActivity.task.voiceSession;
+                } else {
+                    session = mLastResumedActivity.voiceSession;
+                }
+
+                if (session != null) {
+                    // We had been in a voice interaction session, but now focused has
+                    // move to something different.  Just finish the session, we can't
+                    // return to it and retain the proper state and synchronization with
+                    // the voice interaction service.
+                    finishVoiceTask(session);
+                }
             }
         }
 
index aef429e..10055c8 100644 (file)
@@ -802,10 +802,7 @@ final class ActivityRecord implements AppWindowContainerListener {
 
         // Remove the activity from the old task and add it to the new task
         prevTask.removeActivity(this);
-        // TODO(b/34179495): This should really be set to null in removeActivity() call above,
-        // but really bad things that I can't track down right now happen when I do that.
-        // So, setting it here now and will change later when there is time for investigation.
-        task = null;
+
         newTask.addActivityAtIndex(position, this);
     }
 
index 6f79bc2..ab1559d 100644 (file)
@@ -177,7 +177,6 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -4902,7 +4901,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                 setResizingDuringAnimation(task);
             }
 
-            mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(),
+            mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
                     ActivityManager.START_TASK_TO_FRONT,
                     sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
                     sourceRecord, task.getStack());
index 83d43db..d8c5533 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.app.Activity.RESULT_CANCELED;
+import static android.app.ActivityManager.START_CANCELED;
 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
@@ -88,12 +89,10 @@ import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityContainer;
 import android.app.IApplicationThread;
-import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.ProfilerInfo;
 import android.app.WaitResult;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -509,33 +508,26 @@ class ActivityStarter {
 
         doPendingActivityLaunchesLocked(false);
 
-        try {
-            mService.mWindowManager.deferSurfaceLayout();
-            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
-                    true, options, inTask);
-        } finally {
-            mService.mWindowManager.continueSurfaceLayout();
-        }
-        postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
-        return err;
+        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
+            options, inTask);
     }
 
     /** Creates a launch intent for the given auxiliary resolution data. */
     private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
-            Intent originalIntent, String callingPackage,
-            String resolvedType, int userId) {
+        Intent originalIntent, String callingPackage,
+        String resolvedType, int userId) {
         if (auxiliaryResponse.needsPhaseTwo) {
             // request phase two resolution
             mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
-                    auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
+                auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
         }
         return EphemeralResolver.buildEphemeralInstallerIntent(originalIntent,
-                callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
-                auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
-                auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+            callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
+            auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
+            auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
     }
 
-    void postStartActivityUncheckedProcessing(
+    void postStartActivityProcessing(
             ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
             ActivityStack targetStack) {
 
@@ -937,6 +929,32 @@ class ActivityStarter {
         }
     }
 
+    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
+        int result = START_CANCELED;
+        try {
+            mService.mWindowManager.deferSurfaceLayout();
+            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
+                startFlags,
+                doResume, options, inTask);
+        } finally {
+            // If we are not able to proceed, disassociate the activity from the task. Leaving an
+            // activity in an incomplete state can lead to issues, such as performing operations
+            // without a window container.
+            if (result != START_SUCCESS && mStartActivity.task != null) {
+                mStartActivity.task.removeActivity(mStartActivity);
+            }
+            mService.mWindowManager.continueSurfaceLayout();
+        }
+
+        postStartActivityProcessing(r, result, mSupervisor.mFocusedStack.mStackId,
+            mSourceRecord, mTargetStack);
+
+        return result;
+    }
+
+    // Note: This method should only be called from {@link startActivity}.
     private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
             int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
@@ -1843,11 +1861,8 @@ class ActivityStarter {
             final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
             final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
             try {
-                final int result = startActivityUnchecked(
-                        pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
-                postStartActivityUncheckedProcessing(
-                        pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
-                        mTargetStack);
+                startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
+                    null);
             } catch (Exception e) {
                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                 pal.sendErrorResult(e.getMessage());
index f8645d6..b051304 100644 (file)
@@ -1083,6 +1083,13 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
 
     /** @return true if this was the last activity in the task */
     boolean removeActivity(ActivityRecord r) {
+        if (r.task != this) {
+            throw new IllegalArgumentException(
+                "Activity=" + r + " does not belong to task=" + this);
+        }
+
+        r.task = null;
+
         if (mActivities.remove(r) && r.fullscreen) {
             // Was previously in list.
             numFullscreen--;