Merge "Properly remove activity from task on start failure." into pi-dev

am: 65317bac02

Change-Id: Id0770cf31559d3ccd80332a4fa1178f92b360eeb
This commit is contained in:
Bryce Lee
2018-04-10 15:11:06 -07:00
committed by android-build-merger
12 changed files with 141 additions and 46 deletions

View File

@@ -767,7 +767,7 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* The controller for all operations related to locktask.
*/
final LockTaskController mLockTaskController;
private final LockTaskController mLockTaskController;
final UserController mUserController;
@@ -12315,6 +12315,10 @@ public class ActivityManagerService extends IActivityManager.Stub
return mActivityStartController;
}
LockTaskController getLockTaskController() {
return mLockTaskController;
}
ClientLifecycleManager getLifecycleManager() {
return mLifecycleManager;
}

View File

@@ -1589,14 +1589,20 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
void pauseKeyDispatchingLocked() {
if (!keysPaused) {
keysPaused = true;
mWindowContainerController.pauseKeyDispatching();
if (mWindowContainerController != null) {
mWindowContainerController.pauseKeyDispatching();
}
}
}
void resumeKeyDispatchingLocked() {
if (keysPaused) {
keysPaused = false;
mWindowContainerController.resumeKeyDispatching();
if (mWindowContainerController != null) {
mWindowContainerController.resumeKeyDispatching();
}
}
}

View File

@@ -3743,7 +3743,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
if (endTask) {
mService.mLockTaskController.clearLockedTask(task);
mService.getLockTaskController().clearLockedTask(task);
}
} else if (!r.isState(PAUSING)) {
// If the activity is PAUSING, we will complete the finish once
@@ -4639,7 +4639,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// In LockTask mode, moving a locked task to the back of the stack may expose unlocked
// ones. Therefore we need to check if this operation is allowed.
if (!mService.mLockTaskController.canMoveTaskToBack(tr)) {
if (!mService.getLockTaskController().canMoveTaskToBack(tr)) {
return false;
}
@@ -5084,7 +5084,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
onActivityRemovedFromStack(record);
}
mTaskHistory.remove(task);
final boolean removed = mTaskHistory.remove(task);
if (removed) {
EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
}
removeActivitiesFromLRUListLocked(task);
updateTaskMovement(task, true);

View File

@@ -1372,12 +1372,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
final LockTaskController lockTaskController = mService.getLockTaskController();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
|| task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
|| (task.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED
&& mService.mLockTaskController.getLockTaskModeState()
== LOCK_TASK_MODE_LOCKED)) {
mService.mLockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
&& lockTaskController.getLockTaskModeState()
== LOCK_TASK_MODE_LOCKED)) {
lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
}
try {
@@ -2900,7 +2901,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (tr != null) {
tr.removeTaskActivitiesLocked(pauseImmediately, reason);
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
mService.mLockTaskController.clearLockedTask(tr);
mService.getLockTaskController().clearLockedTask(tr);
if (tr.isPersistable) {
mService.notifyTaskPersisterLocked(null, true);
}
@@ -3814,7 +3815,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
pw.print(mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
getKeyguardController().dump(pw, prefix);
mService.mLockTaskController.dump(pw, prefix);
mService.getLockTaskController().dump(pw, prefix);
}
public void writeToProto(ProtoOutputStream proto, long fieldId) {

View File

@@ -1156,9 +1156,10 @@ class ActivityStarter {
// 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 (!ActivityManager.isStartResultSuccessful(result)
&& mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
final ActivityStack stack = mStartActivity.getStack();
if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
null /* intentResultData */, "startActivity", true /* oomAdj */);
}
mService.mWindowManager.continueSurfaceLayout();
}
@@ -1208,7 +1209,7 @@ class ActivityStarter {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(),
if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
@@ -2020,7 +2021,7 @@ class ActivityStarter {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) {
if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -2043,7 +2044,7 @@ class ActivityStarter {
}
private int setTaskFromSourceRecord() {
if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) {
if (mService.getLockTaskController().isLockTaskModeViolation(mSourceRecord.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -2137,7 +2138,7 @@ class ActivityStarter {
private int setTaskFromInTask() {
// The caller is asking that the new activity be started in an explicit
// task it has provided to us.
if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) {
if (mService.getLockTaskController().isLockTaskModeViolation(mInTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}

View File

@@ -133,4 +133,7 @@ option java_package com.android.server.am
# The activity's onStart has been called.
30059 am_on_start_called (User|1|5),(Component Name|3),(Reason|3)
# The activity's onDestroy has been called.
30060 am_on_destroy_called (User|1|5),(Component Name|3),(Reason|3)
30060 am_on_destroy_called (User|1|5),(Component Name|3),(Reason|3)
# The task is being removed from its parent stack
30061 am_remove_task (Task ID|1|5), (Stack ID|1|5)

View File

@@ -523,7 +523,7 @@ class RecentTasks {
}
for (int i = mTasks.size() - 1; i >= 0; --i) {
final TaskRecord tr = mTasks.get(i);
if (tr.userId == userId && !mService.mLockTaskController.isTaskWhitelisted(tr)) {
if (tr.userId == userId && !mService.getLockTaskController().isTaskWhitelisted(tr)) {
remove(tr);
}
}
@@ -1156,7 +1156,7 @@ class RecentTasks {
}
// If we're in lock task mode, ignore the root task
if (task == mService.mLockTaskController.getRootTask()) {
if (task == mService.getLockTaskController().getRootTask()) {
return false;
}

View File

@@ -210,7 +210,7 @@ class SafeActivityOptions {
// Check if someone tries to launch an unwhitelisted activity into LockTask mode.
final boolean lockTaskMode = options.getLockTaskMode();
if (aInfo != null && lockTaskMode
&& !supervisor.mService.mLockTaskController.isPackageWhitelisted(
&& !supervisor.mService.getLockTaskController().isPackageWhitelisted(
UserHandle.getUserId(callingUid), aInfo.packageName)) {
final String msg = "Permission Denial: starting " + getIntentString(intent)
+ " from " + callerApp + " (pid=" + callingPid

View File

@@ -451,7 +451,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
void removeWindowContainer() {
mService.mLockTaskController.clearLockedTask(this);
mService.getLockTaskController().clearLockedTask(this);
mWindowContainerController.removeContainer();
if (!getWindowConfiguration().persistTaskBounds()) {
// Reset current bounds for task whose bounds shouldn't be persisted so it uses
@@ -1446,9 +1446,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
final LockTaskController lockTaskController = mService.getLockTaskController();
switch (r.lockTaskLaunchMode) {
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
break;
@@ -1461,7 +1462,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
break;
case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
break;
}

View File

@@ -2215,7 +2215,7 @@ class UserController implements Handler.Callback {
protected void clearAllLockedTasks(String reason) {
synchronized (mService) {
mService.mLockTaskController.clearLockedTasks(reason);
mService.getLockTaskController().clearLockedTasks(reason);
}
}

View File

@@ -23,6 +23,7 @@ import static android.app.ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
import static android.app.ActivityManager.START_INTENT_NOT_RESOLVED;
import static android.app.ActivityManager.START_NOT_VOICE_COMPATIBLE;
import static android.app.ActivityManager.START_PERMISSION_DENIED;
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_SWITCHES_CANCELED;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
@@ -34,6 +35,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND
import android.app.ActivityOptions;
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.WindowLayout;
@@ -74,6 +76,8 @@ import com.android.server.am.ActivityStarter.Factory;
import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
import com.android.server.am.TaskRecord.TaskRecordFactory;
import java.util.ArrayList;
/**
* Tests for the {@link ActivityStarter} class.
*
@@ -301,13 +305,14 @@ public class ActivityStarterTests extends ActivityTestsBase {
anyBoolean(), any(), any(), any());
// instrument the stack and task used.
final ActivityStack stack = spy(mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */));
final TaskRecord task =
spy(new TaskBuilder(mService.mStackSupervisor).setStack(stack).build());
final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
.setCreateStack(false)
.build();
// supervisor needs a focused stack.
mService.mStackSupervisor.mFocusedStack = task.getStack();
mService.mStackSupervisor.mFocusedStack = stack;
// use factory that only returns spy task.
final TaskRecordFactory factory = mock(TaskRecordFactory.class);
@@ -322,14 +327,6 @@ public class ActivityStarterTests extends ActivityTestsBase {
doReturn(stack).when(mService.mStackSupervisor)
.getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
// ignore the start request.
doNothing().when(stack)
.startActivityLocked(any(), any(), anyBoolean(), anyBoolean(), any());
// ignore requests to create window container.
doNothing().when(task).createWindowContainer(anyBoolean(), anyBoolean());
final Intent intent = new Intent();
intent.addFlags(launchFlags);
intent.setComponent(ActivityBuilder.getDefaultComponent());
@@ -448,4 +445,30 @@ public class ActivityStarterTests extends ActivityTestsBase {
// Ensure result is moving task to front.
assertEquals(result, START_TASK_TO_FRONT);
}
/**
* Tests activity is cleaned up properly in a task mode violation.
*/
@Test
public void testTaskModeViolation() {
final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
assertNoTasks(display);
final ActivityStarter starter = prepareStarter(0);
final LockTaskController lockTaskController = mService.getLockTaskController();
doReturn(true).when(lockTaskController).isLockTaskModeViolation(any());
final int result = starter.setReason("testTaskModeViolation").execute();
assertEquals(START_RETURN_LOCK_TASK_MODE_VIOLATION, result);
assertNoTasks(display);
}
private void assertNoTasks(ActivityDisplay display) {
for (int i = display.getChildCount() - 1; i >= 0; --i) {
final ActivityStack stack = display.getChildAt(i);
assertTrue(stack.getAllTasks().isEmpty());
}
}
}

View File

@@ -30,6 +30,7 @@ import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import android.app.ActivityOptions;
import com.android.server.wm.DisplayWindowController;
import org.junit.Rule;
@@ -51,6 +52,9 @@ import android.service.voice.IVoiceInteractionSession;
import android.support.test.InstrumentationRegistry;
import android.testing.DexmakerShareClassLoaderRule;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.AttributeCache;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.PinnedStackWindowController;
@@ -62,6 +66,7 @@ import org.junit.After;
import org.junit.Before;
import org.mockito.MockitoAnnotations;
/**
* A base class to handle common operations in activity related unit tests.
*/
@@ -215,6 +220,7 @@ public class ActivityTestsBase {
private int mTaskId = 0;
private int mUserId = 0;
private IVoiceInteractionSession mVoiceSession;
private boolean mCreateStack = true;
private ActivityStack mStack;
@@ -232,6 +238,15 @@ public class ActivityTestsBase {
return this;
}
/**
* Set to {@code true} by default, set to {@code false} to prevent the task from
* automatically creating a parent stack.
*/
TaskBuilder setCreateStack(boolean createStack) {
mCreateStack = createStack;
return this;
}
TaskBuilder setVoiceSession(IVoiceInteractionSession session) {
mVoiceSession = session;
return this;
@@ -258,7 +273,7 @@ public class ActivityTestsBase {
}
TaskRecord build() {
if (mStack == null) {
if (mStack == null && mCreateStack) {
mStack = mSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
@@ -276,17 +291,38 @@ public class ActivityTestsBase {
intent.setComponent(mComponent);
intent.setFlags(mFlags);
final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
final TestTaskRecord task = new TestTaskRecord(mSupervisor.mService, mTaskId, aInfo,
intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/);
task.userId = mUserId;
mSupervisor.setFocusStackUnchecked("test", mStack);
mStack.addTask(task, true, "creating test task");
task.setStack(mStack);
task.setWindowContainerController(mock(TaskWindowContainerController.class));
if (mStack != null) {
mSupervisor.setFocusStackUnchecked("test", mStack);
mStack.addTask(task, true, "creating test task");
task.setStack(mStack);
task.setWindowContainerController();
}
task.touchActiveTime();
return task;
}
private static class TestTaskRecord extends TaskRecord {
TestTaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info,
Intent _intent, IVoiceInteractionSession _voiceSession,
IVoiceInteractor _voiceInteractor) {
super(service, _taskId, info, _intent, _voiceSession, _voiceInteractor);
}
@Override
void createWindowContainer(boolean onTop, boolean showForAllUsers) {
setWindowContainerController();
}
private void setWindowContainerController() {
setWindowContainerController(mock(TaskWindowContainerController.class));
}
}
}
/**
@@ -295,6 +331,7 @@ public class ActivityTestsBase {
*/
protected static class TestActivityManagerService extends ActivityManagerService {
private ClientLifecycleManager mLifecycleManager;
private LockTaskController mLockTaskController;
TestActivityManagerService(Context context) {
super(context);
@@ -314,6 +351,14 @@ public class ActivityTestsBase {
return mLifecycleManager;
}
public LockTaskController getLockTaskController() {
if (mLockTaskController == null) {
mLockTaskController = spy(super.getLockTaskController());
}
return mLockTaskController;
}
void setLifecycleManager(ClientLifecycleManager manager) {
mLifecycleManager = manager;
}
@@ -444,7 +489,7 @@ public class ActivityTestsBase {
}
/**
* Overrided of {@link ActivityStack} that tracks test metrics, such as the number of times a
* Overridden {@link ActivityStack} that tracks test metrics, such as the number of times a
* method is called. Note that its functionality depends on the implementations of the
* construction arguments.
*/
@@ -530,5 +575,11 @@ public class ActivityTestsBase {
return super.supportsSplitScreenWindowingMode();
}
}
@Override
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
}
}
}