Remove TaskInfo#topActivityToken usage in size compat for security
Security report shows that this can cause leak token of different app. Replace the functionality with a callback to the TaskOrganizerController to restart activity when size compat restart button is clicked. Bug: 186776724 Test: manually verify the restart button still works Change-Id: I097b9f02e8435e6765695b9d5a531a4e165bac66
This commit is contained in:
@@ -431,19 +431,6 @@ public class ActivityClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Restart the process and activity to adopt the latest configuration for size compat mode.
|
|
||||||
* This only takes effect for visible activity because invisible background activity can be
|
|
||||||
* restarted naturally when it becomes visible.
|
|
||||||
*/
|
|
||||||
public void restartActivityProcessIfVisible(IBinder token) {
|
|
||||||
try {
|
|
||||||
getActivityClientController().restartActivityProcessIfVisible(token);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Removes the snapshot of home task. */
|
/** Removes the snapshot of home task. */
|
||||||
public void invalidateHomeTaskSnapshot(IBinder homeToken) {
|
public void invalidateHomeTaskSnapshot(IBinder homeToken) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -116,16 +116,6 @@ interface IActivityClientController {
|
|||||||
/** See {@link android.app.Activity#setDisablePreviewScreenshots}. */
|
/** See {@link android.app.Activity#setDisablePreviewScreenshots}. */
|
||||||
oneway void setDisablePreviewScreenshots(in IBinder token, boolean disable);
|
oneway void setDisablePreviewScreenshots(in IBinder token, boolean disable);
|
||||||
|
|
||||||
/**
|
|
||||||
* Restarts the activity by killing its process if it is visible. If the activity is not
|
|
||||||
* visible, the activity will not be restarted immediately and just keep the activity record in
|
|
||||||
* the stack. It also resets the current override configuration so the activity will use the
|
|
||||||
* configuration according to the latest state.
|
|
||||||
*
|
|
||||||
* @param activityToken The token of the target activity to restart.
|
|
||||||
*/
|
|
||||||
void restartActivityProcessIfVisible(in IBinder activityToken);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It should only be called from home activity to remove its outdated snapshot. The home
|
* It should only be called from home activity to remove its outdated snapshot. The home
|
||||||
* snapshot is used to speed up entering home from screen off. If the content of home activity
|
* snapshot is used to speed up entering home from screen off. If the content of home activity
|
||||||
|
|||||||
@@ -193,13 +193,6 @@ public class TaskInfo {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public ActivityInfo topActivityInfo;
|
public ActivityInfo topActivityInfo;
|
||||||
|
|
||||||
/**
|
|
||||||
* The top activity in this task.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public IBinder topActivityToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the direct top activity is in size compat mode on foreground.
|
* Whether the direct top activity is in size compat mode on foreground.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -370,8 +363,7 @@ public class TaskInfo {
|
|||||||
return displayId == that.displayId
|
return displayId == that.displayId
|
||||||
&& taskId == that.taskId
|
&& taskId == that.taskId
|
||||||
&& topActivityInSizeCompat == that.topActivityInSizeCompat
|
&& topActivityInSizeCompat == that.topActivityInSizeCompat
|
||||||
// TopActivityToken and bounds are important if top activity is in size compat
|
// Bounds are important if top activity is in size compat
|
||||||
&& (!topActivityInSizeCompat || topActivityToken.equals(that.topActivityToken))
|
|
||||||
&& (!topActivityInSizeCompat || configuration.windowConfiguration.getBounds()
|
&& (!topActivityInSizeCompat || configuration.windowConfiguration.getBounds()
|
||||||
.equals(that.configuration.windowConfiguration.getBounds()))
|
.equals(that.configuration.windowConfiguration.getBounds()))
|
||||||
&& (!topActivityInSizeCompat || configuration.getLayoutDirection()
|
&& (!topActivityInSizeCompat || configuration.getLayoutDirection()
|
||||||
@@ -411,7 +403,6 @@ public class TaskInfo {
|
|||||||
isFocused = source.readBoolean();
|
isFocused = source.readBoolean();
|
||||||
isVisible = source.readBoolean();
|
isVisible = source.readBoolean();
|
||||||
isSleeping = source.readBoolean();
|
isSleeping = source.readBoolean();
|
||||||
topActivityToken = source.readStrongBinder();
|
|
||||||
topActivityInSizeCompat = source.readBoolean();
|
topActivityInSizeCompat = source.readBoolean();
|
||||||
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
|
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
|
||||||
displayAreaFeatureId = source.readInt();
|
displayAreaFeatureId = source.readInt();
|
||||||
@@ -451,7 +442,6 @@ public class TaskInfo {
|
|||||||
dest.writeBoolean(isFocused);
|
dest.writeBoolean(isFocused);
|
||||||
dest.writeBoolean(isVisible);
|
dest.writeBoolean(isVisible);
|
||||||
dest.writeBoolean(isSleeping);
|
dest.writeBoolean(isSleeping);
|
||||||
dest.writeStrongBinder(topActivityToken);
|
|
||||||
dest.writeBoolean(topActivityInSizeCompat);
|
dest.writeBoolean(topActivityInSizeCompat);
|
||||||
dest.writeTypedObject(mTopActivityLocusId, flags);
|
dest.writeTypedObject(mTopActivityLocusId, flags);
|
||||||
dest.writeInt(displayAreaFeatureId);
|
dest.writeInt(displayAreaFeatureId);
|
||||||
@@ -481,7 +471,6 @@ public class TaskInfo {
|
|||||||
+ " isFocused=" + isFocused
|
+ " isFocused=" + isFocused
|
||||||
+ " isVisible=" + isVisible
|
+ " isVisible=" + isVisible
|
||||||
+ " isSleeping=" + isSleeping
|
+ " isSleeping=" + isSleeping
|
||||||
+ " topActivityToken=" + topActivityToken
|
|
||||||
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
|
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
|
||||||
+ " locusId=" + mTopActivityLocusId
|
+ " locusId=" + mTopActivityLocusId
|
||||||
+ " displayAreaFeatureId=" + displayAreaFeatureId
|
+ " displayAreaFeatureId=" + displayAreaFeatureId
|
||||||
|
|||||||
@@ -61,4 +61,9 @@ interface ITaskOrganizerController {
|
|||||||
*/
|
*/
|
||||||
void setInterceptBackPressedOnTaskRoot(in WindowContainerToken task,
|
void setInterceptBackPressedOnTaskRoot(in WindowContainerToken task,
|
||||||
boolean interceptBackPressed);
|
boolean interceptBackPressed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restarts the top activity in the given task by killing its process if it is visible.
|
||||||
|
*/
|
||||||
|
void restartTaskTopActivityProcessIfVisible(in WindowContainerToken task);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,20 @@ public class TaskOrganizer extends WindowOrganizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restarts the top activity in the given task by killing its process if it is visible.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
|
||||||
|
public void restartTaskTopActivityProcessIfVisible(@NonNull WindowContainerToken task) {
|
||||||
|
try {
|
||||||
|
mTaskOrganizerController.restartTaskTopActivityProcessIfVisible(task);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the executor to run callbacks on.
|
* Gets the executor to run callbacks on.
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -157,6 +157,12 @@
|
|||||||
"group": "WM_DEBUG_ADD_REMOVE",
|
"group": "WM_DEBUG_ADD_REMOVE",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||||
},
|
},
|
||||||
|
"-1963363332": {
|
||||||
|
"message": "Restart top activity process of Task taskId=%d",
|
||||||
|
"level": "VERBOSE",
|
||||||
|
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
||||||
|
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
|
||||||
|
},
|
||||||
"-1949279037": {
|
"-1949279037": {
|
||||||
"message": "Attempted to add input method window with bad token %s. Aborting.",
|
"message": "Attempted to add input method window with bad token %s. Aborting.",
|
||||||
"level": "WARN",
|
"level": "WARN",
|
||||||
@@ -169,12 +175,6 @@
|
|||||||
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
||||||
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
|
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
|
||||||
},
|
},
|
||||||
"-1939358269": {
|
|
||||||
"message": "mRecentScreenshotAnimator finish",
|
|
||||||
"level": "DEBUG",
|
|
||||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
|
||||||
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
|
|
||||||
},
|
|
||||||
"-1938839202": {
|
"-1938839202": {
|
||||||
"message": "SURFACE LEAK DESTROY: %s",
|
"message": "SURFACE LEAK DESTROY: %s",
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
@@ -3535,12 +3535,6 @@
|
|||||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||||
"at": "com\/android\/server\/wm\/AppTransitionController.java"
|
"at": "com\/android\/server\/wm\/AppTransitionController.java"
|
||||||
},
|
},
|
||||||
"1984470582": {
|
|
||||||
"message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
|
|
||||||
"level": "DEBUG",
|
|
||||||
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
|
|
||||||
"at": "com\/android\/server\/wm\/TaskScreenshotAnimatable.java"
|
|
||||||
},
|
|
||||||
"1984782949": {
|
"1984782949": {
|
||||||
"message": ">>> OPEN TRANSACTION animate",
|
"message": ">>> OPEN TRANSACTION animate",
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ import java.util.function.Consumer;
|
|||||||
* Unified task organizer for all components in the shell.
|
* Unified task organizer for all components in the shell.
|
||||||
* TODO(b/167582004): may consider consolidating this class and TaskOrganizer
|
* TODO(b/167582004): may consider consolidating this class and TaskOrganizer
|
||||||
*/
|
*/
|
||||||
public class ShellTaskOrganizer extends TaskOrganizer {
|
public class ShellTaskOrganizer extends TaskOrganizer implements
|
||||||
|
SizeCompatUIController.SizeCompatUICallback {
|
||||||
|
|
||||||
// Intentionally using negative numbers here so the positive numbers can be used
|
// Intentionally using negative numbers here so the positive numbers can be used
|
||||||
// for task id specific listeners that will be added later.
|
// for task id specific listeners that will be added later.
|
||||||
@@ -158,6 +159,9 @@ public class ShellTaskOrganizer extends TaskOrganizer {
|
|||||||
Context context, @Nullable SizeCompatUIController sizeCompatUI) {
|
Context context, @Nullable SizeCompatUIController sizeCompatUI) {
|
||||||
super(taskOrganizerController, mainExecutor);
|
super(taskOrganizerController, mainExecutor);
|
||||||
mSizeCompatUI = sizeCompatUI;
|
mSizeCompatUI = sizeCompatUI;
|
||||||
|
if (sizeCompatUI != null) {
|
||||||
|
sizeCompatUI.setSizeCompatUICallback(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -481,6 +485,17 @@ public class ShellTaskOrganizer extends TaskOrganizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSizeCompatRestartButtonClicked(int taskId) {
|
||||||
|
final TaskAppearedInfo info;
|
||||||
|
synchronized (mLock) {
|
||||||
|
info = mTasks.get(taskId);
|
||||||
|
}
|
||||||
|
if (info != null) {
|
||||||
|
restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies {@link SizeCompatUIController} about the size compat info changed on the give Task
|
* Notifies {@link SizeCompatUIController} about the size compat info changed on the give Task
|
||||||
* to update the UI accordingly.
|
* to update the UI accordingly.
|
||||||
@@ -499,13 +514,12 @@ public class ShellTaskOrganizer extends TaskOrganizer {
|
|||||||
if (taskListener == null || !taskListener.supportSizeCompatUI()
|
if (taskListener == null || !taskListener.supportSizeCompatUI()
|
||||||
|| !taskInfo.topActivityInSizeCompat) {
|
|| !taskInfo.topActivityInSizeCompat) {
|
||||||
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
|
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
|
||||||
null /* taskConfig */, null /* sizeCompatActivity*/,
|
null /* taskConfig */, null /* taskListener */);
|
||||||
null /* taskListener */);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
|
mSizeCompatUI.onSizeCompatInfoChanged(taskInfo.displayId, taskInfo.taskId,
|
||||||
taskInfo.configuration, taskInfo.topActivityToken, taskListener);
|
taskInfo.configuration, taskListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) {
|
private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.annotation.Nullable;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -45,6 +44,13 @@ import java.util.function.Consumer;
|
|||||||
*/
|
*/
|
||||||
public class SizeCompatUIController implements DisplayController.OnDisplaysChangedListener,
|
public class SizeCompatUIController implements DisplayController.OnDisplaysChangedListener,
|
||||||
DisplayImeController.ImePositionProcessor {
|
DisplayImeController.ImePositionProcessor {
|
||||||
|
|
||||||
|
/** Callback for size compat UI interaction. */
|
||||||
|
public interface SizeCompatUICallback {
|
||||||
|
/** Called when the size compat restart button is clicked. */
|
||||||
|
void onSizeCompatRestartButtonClicked(int taskId);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String TAG = "SizeCompatUIController";
|
private static final String TAG = "SizeCompatUIController";
|
||||||
|
|
||||||
/** Whether the IME is shown on display id. */
|
/** Whether the IME is shown on display id. */
|
||||||
@@ -61,6 +67,8 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
|
|||||||
private final DisplayImeController mImeController;
|
private final DisplayImeController mImeController;
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
|
|
||||||
|
private SizeCompatUICallback mCallback;
|
||||||
|
|
||||||
/** Only show once automatically in the process life. */
|
/** Only show once automatically in the process life. */
|
||||||
private boolean mHasShownHint;
|
private boolean mHasShownHint;
|
||||||
|
|
||||||
@@ -76,29 +84,31 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
|
|||||||
mImeController.addPositionProcessor(this);
|
mImeController.addPositionProcessor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the callback for UI interactions. */
|
||||||
|
public void setSizeCompatUICallback(SizeCompatUICallback callback) {
|
||||||
|
mCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the Task info changed. Creates and updates the size compat UI if there is an
|
* Called when the Task info changed. Creates and updates the size compat UI if there is an
|
||||||
* activity in size compat, or removes the UI if there is no size compat activity.
|
* activity in size compat, or removes the UI if there is no size compat activity.
|
||||||
*
|
|
||||||
* @param displayId display the task and activity are in.
|
* @param displayId display the task and activity are in.
|
||||||
* @param taskId task the activity is in.
|
* @param taskId task the activity is in.
|
||||||
* @param taskConfig task config to place the size compat UI with.
|
* @param taskConfig task config to place the size compat UI with.
|
||||||
* @param sizeCompatActivity the size compat activity in the task. Can be {@code null} if the
|
|
||||||
* top activity in this Task is not in size compat.
|
|
||||||
* @param taskListener listener to handle the Task Surface placement.
|
* @param taskListener listener to handle the Task Surface placement.
|
||||||
*/
|
*/
|
||||||
public void onSizeCompatInfoChanged(int displayId, int taskId,
|
public void onSizeCompatInfoChanged(int displayId, int taskId,
|
||||||
@Nullable Configuration taskConfig, @Nullable IBinder sizeCompatActivity,
|
@Nullable Configuration taskConfig,
|
||||||
@Nullable ShellTaskOrganizer.TaskListener taskListener) {
|
@Nullable ShellTaskOrganizer.TaskListener taskListener) {
|
||||||
if (taskConfig == null || sizeCompatActivity == null || taskListener == null) {
|
if (taskConfig == null || taskListener == null) {
|
||||||
// Null token means the current foreground activity is not in size compatibility mode.
|
// Null token means the current foreground activity is not in size compatibility mode.
|
||||||
removeLayout(taskId);
|
removeLayout(taskId);
|
||||||
} else if (mActiveLayouts.contains(taskId)) {
|
} else if (mActiveLayouts.contains(taskId)) {
|
||||||
// UI already exists, update the UI layout.
|
// UI already exists, update the UI layout.
|
||||||
updateLayout(taskId, taskConfig, sizeCompatActivity, taskListener);
|
updateLayout(taskId, taskConfig, taskListener);
|
||||||
} else {
|
} else {
|
||||||
// Create a new size compat UI.
|
// Create a new size compat UI.
|
||||||
createLayout(displayId, taskId, taskConfig, sizeCompatActivity, taskListener);
|
createLayout(displayId, taskId, taskConfig, taskListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +147,7 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createLayout(int displayId, int taskId, Configuration taskConfig,
|
private void createLayout(int displayId, int taskId, Configuration taskConfig,
|
||||||
IBinder activityToken, ShellTaskOrganizer.TaskListener taskListener) {
|
ShellTaskOrganizer.TaskListener taskListener) {
|
||||||
final Context context = getOrCreateDisplayContext(displayId);
|
final Context context = getOrCreateDisplayContext(displayId);
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
Log.e(TAG, "Cannot get context for display " + displayId);
|
Log.e(TAG, "Cannot get context for display " + displayId);
|
||||||
@@ -145,17 +155,16 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
|
|||||||
}
|
}
|
||||||
|
|
||||||
final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig,
|
final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig,
|
||||||
activityToken, taskListener);
|
taskListener);
|
||||||
mActiveLayouts.put(taskId, layout);
|
mActiveLayouts.put(taskId, layout);
|
||||||
layout.createSizeCompatButton(isImeShowingOnDisplay(displayId));
|
layout.createSizeCompatButton(isImeShowingOnDisplay(displayId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
|
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
|
||||||
Configuration taskConfig, IBinder activityToken,
|
Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) {
|
||||||
ShellTaskOrganizer.TaskListener taskListener) {
|
final SizeCompatUILayout layout = new SizeCompatUILayout(mSyncQueue, mCallback, context,
|
||||||
final SizeCompatUILayout layout = new SizeCompatUILayout(mSyncQueue, context, taskConfig,
|
taskConfig, taskId, taskListener, mDisplayController.getDisplayLayout(displayId),
|
||||||
taskId, activityToken, taskListener, mDisplayController.getDisplayLayout(displayId),
|
|
||||||
mHasShownHint);
|
mHasShownHint);
|
||||||
// Only show hint for the first time.
|
// Only show hint for the first time.
|
||||||
mHasShownHint = true;
|
mHasShownHint = true;
|
||||||
@@ -163,13 +172,12 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateLayout(int taskId, Configuration taskConfig,
|
private void updateLayout(int taskId, Configuration taskConfig,
|
||||||
IBinder sizeCompatActivity,
|
|
||||||
ShellTaskOrganizer.TaskListener taskListener) {
|
ShellTaskOrganizer.TaskListener taskListener) {
|
||||||
final SizeCompatUILayout layout = mActiveLayouts.get(taskId);
|
final SizeCompatUILayout layout = mActiveLayouts.get(taskId);
|
||||||
if (layout == null) {
|
if (layout == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
layout.updateSizeCompatInfo(taskConfig, sizeCompatActivity, taskListener,
|
layout.updateSizeCompatInfo(taskConfig, taskListener,
|
||||||
isImeShowingOnDisplay(layout.getDisplayId()));
|
isImeShowingOnDisplay(layout.getDisplayId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,11 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
|
|||||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityClient;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@@ -48,11 +46,11 @@ class SizeCompatUILayout {
|
|||||||
private static final String TAG = "SizeCompatUILayout";
|
private static final String TAG = "SizeCompatUILayout";
|
||||||
|
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
|
private final SizeCompatUIController.SizeCompatUICallback mCallback;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Configuration mTaskConfig;
|
private Configuration mTaskConfig;
|
||||||
private final int mDisplayId;
|
private final int mDisplayId;
|
||||||
private final int mTaskId;
|
private final int mTaskId;
|
||||||
private IBinder mActivityToken;
|
|
||||||
private ShellTaskOrganizer.TaskListener mTaskListener;
|
private ShellTaskOrganizer.TaskListener mTaskListener;
|
||||||
private DisplayLayout mDisplayLayout;
|
private DisplayLayout mDisplayLayout;
|
||||||
|
|
||||||
@@ -72,15 +70,16 @@ class SizeCompatUILayout {
|
|||||||
final int mPopupOffsetY;
|
final int mPopupOffsetY;
|
||||||
boolean mShouldShowHint;
|
boolean mShouldShowHint;
|
||||||
|
|
||||||
SizeCompatUILayout(SyncTransactionQueue syncQueue, Context context, Configuration taskConfig,
|
SizeCompatUILayout(SyncTransactionQueue syncQueue,
|
||||||
int taskId, IBinder activityToken, ShellTaskOrganizer.TaskListener taskListener,
|
SizeCompatUIController.SizeCompatUICallback callback, Context context,
|
||||||
|
Configuration taskConfig, int taskId, ShellTaskOrganizer.TaskListener taskListener,
|
||||||
DisplayLayout displayLayout, boolean hasShownHint) {
|
DisplayLayout displayLayout, boolean hasShownHint) {
|
||||||
mSyncQueue = syncQueue;
|
mSyncQueue = syncQueue;
|
||||||
|
mCallback = callback;
|
||||||
mContext = context.createConfigurationContext(taskConfig);
|
mContext = context.createConfigurationContext(taskConfig);
|
||||||
mTaskConfig = taskConfig;
|
mTaskConfig = taskConfig;
|
||||||
mDisplayId = mContext.getDisplayId();
|
mDisplayId = mContext.getDisplayId();
|
||||||
mTaskId = taskId;
|
mTaskId = taskId;
|
||||||
mActivityToken = activityToken;
|
|
||||||
mTaskListener = taskListener;
|
mTaskListener = taskListener;
|
||||||
mDisplayLayout = displayLayout;
|
mDisplayLayout = displayLayout;
|
||||||
mShouldShowHint = !hasShownHint;
|
mShouldShowHint = !hasShownHint;
|
||||||
@@ -141,12 +140,11 @@ class SizeCompatUILayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Called when size compat info changed. */
|
/** Called when size compat info changed. */
|
||||||
void updateSizeCompatInfo(Configuration taskConfig, IBinder activityToken,
|
void updateSizeCompatInfo(Configuration taskConfig,
|
||||||
ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) {
|
ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) {
|
||||||
final Configuration prevTaskConfig = mTaskConfig;
|
final Configuration prevTaskConfig = mTaskConfig;
|
||||||
final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
|
final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
|
||||||
mTaskConfig = taskConfig;
|
mTaskConfig = taskConfig;
|
||||||
mActivityToken = activityToken;
|
|
||||||
mTaskListener = taskListener;
|
mTaskListener = taskListener;
|
||||||
|
|
||||||
// Update configuration.
|
// Update configuration.
|
||||||
@@ -253,7 +251,7 @@ class SizeCompatUILayout {
|
|||||||
|
|
||||||
/** Called when the restart button is clicked. */
|
/** Called when the restart button is clicked. */
|
||||||
void onRestartButtonClicked() {
|
void onRestartButtonClicked() {
|
||||||
ActivityClient.getInstance().restartActivityProcessIfVisible(mActivityToken);
|
mCallback.onSizeCompatRestartButtonClicked(mTaskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when the restart button is long clicked. */
|
/** Called when the restart button is long clicked. */
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import android.view.SurfaceControl;
|
|||||||
import android.window.ITaskOrganizer;
|
import android.window.ITaskOrganizer;
|
||||||
import android.window.ITaskOrganizerController;
|
import android.window.ITaskOrganizerController;
|
||||||
import android.window.TaskAppearedInfo;
|
import android.window.TaskAppearedInfo;
|
||||||
|
import android.window.WindowContainerToken;
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -289,7 +290,6 @@ public class ShellTaskOrganizerTests {
|
|||||||
public void testOnSizeCompatActivityChanged() {
|
public void testOnSizeCompatActivityChanged() {
|
||||||
final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN);
|
final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN);
|
||||||
taskInfo1.displayId = DEFAULT_DISPLAY;
|
taskInfo1.displayId = DEFAULT_DISPLAY;
|
||||||
taskInfo1.topActivityToken = mock(IBinder.class);
|
|
||||||
taskInfo1.topActivityInSizeCompat = false;
|
taskInfo1.topActivityInSizeCompat = false;
|
||||||
final TrackingTaskListener taskListener = new TrackingTaskListener();
|
final TrackingTaskListener taskListener = new TrackingTaskListener();
|
||||||
mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
|
mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
|
||||||
@@ -297,23 +297,22 @@ public class ShellTaskOrganizerTests {
|
|||||||
|
|
||||||
// sizeCompatActivity is null if top activity is not in size compat.
|
// sizeCompatActivity is null if top activity is not in size compat.
|
||||||
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
||||||
null /* taskConfig */, null /* sizeCompatActivity*/, null /* taskListener */);
|
null /* taskConfig */, null /* taskListener */);
|
||||||
|
|
||||||
// sizeCompatActivity is non-null if top activity is in size compat.
|
// sizeCompatActivity is non-null if top activity is in size compat.
|
||||||
clearInvocations(mSizeCompatUI);
|
clearInvocations(mSizeCompatUI);
|
||||||
final RunningTaskInfo taskInfo2 =
|
final RunningTaskInfo taskInfo2 =
|
||||||
createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
|
createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
|
||||||
taskInfo2.displayId = taskInfo1.displayId;
|
taskInfo2.displayId = taskInfo1.displayId;
|
||||||
taskInfo2.topActivityToken = taskInfo1.topActivityToken;
|
|
||||||
taskInfo2.topActivityInSizeCompat = true;
|
taskInfo2.topActivityInSizeCompat = true;
|
||||||
mOrganizer.onTaskInfoChanged(taskInfo2);
|
mOrganizer.onTaskInfoChanged(taskInfo2);
|
||||||
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
||||||
taskInfo1.configuration, taskInfo1.topActivityToken, taskListener);
|
taskInfo1.configuration, taskListener);
|
||||||
|
|
||||||
clearInvocations(mSizeCompatUI);
|
clearInvocations(mSizeCompatUI);
|
||||||
mOrganizer.onTaskVanished(taskInfo1);
|
mOrganizer.onTaskVanished(taskInfo1);
|
||||||
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
verify(mSizeCompatUI).onSizeCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId,
|
||||||
null /* taskConfig */, null /* sizeCompatActivity*/, null /* taskListener */);
|
null /* taskConfig */, null /* taskListener */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -433,6 +432,18 @@ public class ShellTaskOrganizerTests {
|
|||||||
assertEquals(listener.invisibleLocusTasks.size(), 0);
|
assertEquals(listener.invisibleLocusTasks.size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnSizeCompatRestartButtonClicked() throws RemoteException {
|
||||||
|
RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
|
||||||
|
task1.token = mock(WindowContainerToken.class);
|
||||||
|
|
||||||
|
mOrganizer.onTaskAppeared(task1, null);
|
||||||
|
|
||||||
|
mOrganizer.onSizeCompatRestartButtonClicked(task1.taskId);
|
||||||
|
|
||||||
|
verify(mTaskOrganizerController).restartTaskTopActivityProcessIfVisible(task1.token);
|
||||||
|
}
|
||||||
|
|
||||||
private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
|
private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
|
||||||
RunningTaskInfo taskInfo = new RunningTaskInfo();
|
RunningTaskInfo taskInfo = new RunningTaskInfo();
|
||||||
taskInfo.taskId = taskId;
|
taskInfo.taskId = taskId;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.doNothing;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -52,7 +51,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
public class SizeCompatHintPopupTest extends ShellTestCase {
|
public class SizeCompatHintPopupTest extends ShellTestCase {
|
||||||
|
|
||||||
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
||||||
@Mock private IBinder mActivityToken;
|
@Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
|
||||||
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
||||||
@Mock private DisplayLayout mDisplayLayout;
|
@Mock private DisplayLayout mDisplayLayout;
|
||||||
|
|
||||||
@@ -64,8 +63,9 @@ public class SizeCompatHintPopupTest extends ShellTestCase {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
final int taskId = 1;
|
final int taskId = 1;
|
||||||
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
|
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
|
||||||
taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
|
new Configuration(), taskId, mTaskListener, mDisplayLayout,
|
||||||
|
false /* hasShownHint */);
|
||||||
mHint = (SizeCompatHintPopup)
|
mHint = (SizeCompatHintPopup)
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
|
LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
|
||||||
mHint.inject(mLayout);
|
mHint.inject(mLayout);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.doNothing;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
@@ -51,8 +50,10 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
public class SizeCompatRestartButtonTest extends ShellTestCase {
|
public class SizeCompatRestartButtonTest extends ShellTestCase {
|
||||||
|
|
||||||
|
private static final int TASK_ID = 1;
|
||||||
|
|
||||||
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
||||||
@Mock private IBinder mActivityToken;
|
@Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
|
||||||
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
||||||
@Mock private DisplayLayout mDisplayLayout;
|
@Mock private DisplayLayout mDisplayLayout;
|
||||||
|
|
||||||
@@ -63,9 +64,9 @@ public class SizeCompatRestartButtonTest extends ShellTestCase {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
final int taskId = 1;
|
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
|
||||||
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
|
new Configuration(), TASK_ID, mTaskListener, mDisplayLayout,
|
||||||
taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
|
false /* hasShownHint */);
|
||||||
mButton = (SizeCompatRestartButton)
|
mButton = (SizeCompatRestartButton)
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.size_compat_ui, null);
|
LayoutInflater.from(mContext).inflate(R.layout.size_compat_ui, null);
|
||||||
mButton.inject(mLayout);
|
mButton.inject(mLayout);
|
||||||
@@ -75,12 +76,11 @@ public class SizeCompatRestartButtonTest extends ShellTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnClick() {
|
public void testOnClick() {
|
||||||
doNothing().when(mLayout).onRestartButtonClicked();
|
|
||||||
|
|
||||||
final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
|
final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
|
||||||
button.performClick();
|
button.performClick();
|
||||||
|
|
||||||
verify(mLayout).onRestartButtonClicked();
|
verify(mLayout).onRestartButtonClicked();
|
||||||
|
verify(mCallback).onSizeCompatRestartButtonClicked(TASK_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -61,7 +60,6 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
private @Mock DisplayController mMockDisplayController;
|
private @Mock DisplayController mMockDisplayController;
|
||||||
private @Mock DisplayLayout mMockDisplayLayout;
|
private @Mock DisplayLayout mMockDisplayLayout;
|
||||||
private @Mock DisplayImeController mMockImeController;
|
private @Mock DisplayImeController mMockImeController;
|
||||||
private @Mock IBinder mMockActivityToken;
|
|
||||||
private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
|
private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
|
||||||
private @Mock SyncTransactionQueue mMockSyncQueue;
|
private @Mock SyncTransactionQueue mMockSyncQueue;
|
||||||
private @Mock SizeCompatUILayout mMockLayout;
|
private @Mock SizeCompatUILayout mMockLayout;
|
||||||
@@ -77,8 +75,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
mMockImeController, mMockSyncQueue) {
|
mMockImeController, mMockSyncQueue) {
|
||||||
@Override
|
@Override
|
||||||
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
|
SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
|
||||||
Configuration taskConfig, IBinder activityToken,
|
Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) {
|
||||||
ShellTaskOrganizer.TaskListener taskListener) {
|
|
||||||
return mMockLayout;
|
return mMockLayout;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -97,21 +94,21 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
|
|
||||||
// Verify that the restart button is added with non-null size compat info.
|
// Verify that the restart button is added with non-null size compat info.
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
||||||
mMockActivityToken, mMockTaskListener);
|
mMockTaskListener);
|
||||||
|
|
||||||
verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig),
|
verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig),
|
||||||
eq(mMockActivityToken), eq(mMockTaskListener));
|
eq(mMockTaskListener));
|
||||||
|
|
||||||
// Verify that the restart button is updated with non-null new size compat info.
|
// Verify that the restart button is updated with non-null new size compat info.
|
||||||
final Configuration newTaskConfig = new Configuration();
|
final Configuration newTaskConfig = new Configuration();
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig,
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig,
|
||||||
mMockActivityToken, mMockTaskListener);
|
mMockTaskListener);
|
||||||
|
|
||||||
verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockActivityToken, mMockTaskListener,
|
verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener,
|
||||||
false /* isImeShowing */);
|
false /* isImeShowing */);
|
||||||
|
|
||||||
// Verify that the restart button is removed with null size compat info.
|
// Verify that the restart button is removed with null size compat info.
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, null, mMockTaskListener);
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener);
|
||||||
|
|
||||||
verify(mMockLayout).release();
|
verify(mMockLayout).release();
|
||||||
}
|
}
|
||||||
@@ -120,7 +117,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
public void testOnDisplayRemoved() {
|
public void testOnDisplayRemoved() {
|
||||||
final Configuration taskConfig = new Configuration();
|
final Configuration taskConfig = new Configuration();
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
||||||
mMockActivityToken, mMockTaskListener);
|
mMockTaskListener);
|
||||||
|
|
||||||
mController.onDisplayRemoved(DISPLAY_ID + 1);
|
mController.onDisplayRemoved(DISPLAY_ID + 1);
|
||||||
|
|
||||||
@@ -135,7 +132,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
public void testOnDisplayConfigurationChanged() {
|
public void testOnDisplayConfigurationChanged() {
|
||||||
final Configuration taskConfig = new Configuration();
|
final Configuration taskConfig = new Configuration();
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
||||||
mMockActivityToken, mMockTaskListener);
|
mMockTaskListener);
|
||||||
|
|
||||||
final Configuration newTaskConfig = new Configuration();
|
final Configuration newTaskConfig = new Configuration();
|
||||||
mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, newTaskConfig);
|
mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, newTaskConfig);
|
||||||
@@ -151,7 +148,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase {
|
|||||||
public void testChangeButtonVisibilityOnImeShowHide() {
|
public void testChangeButtonVisibilityOnImeShowHide() {
|
||||||
final Configuration taskConfig = new Configuration();
|
final Configuration taskConfig = new Configuration();
|
||||||
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
|
||||||
mMockActivityToken, mMockTaskListener);
|
mMockTaskListener);
|
||||||
|
|
||||||
mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
|
mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
|
||||||
|
|
||||||
|
|||||||
@@ -21,20 +21,16 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
import static org.mockito.Mockito.doNothing;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.app.ActivityClient;
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -66,7 +62,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
private static final int TASK_ID = 1;
|
private static final int TASK_ID = 1;
|
||||||
|
|
||||||
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
@Mock private SyncTransactionQueue mSyncTransactionQueue;
|
||||||
@Mock private IBinder mActivityToken;
|
@Mock private SizeCompatUIController.SizeCompatUICallback mCallback;
|
||||||
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
|
||||||
@Mock private DisplayLayout mDisplayLayout;
|
@Mock private DisplayLayout mDisplayLayout;
|
||||||
@Mock private SizeCompatRestartButton mButton;
|
@Mock private SizeCompatRestartButton mButton;
|
||||||
@@ -80,8 +76,9 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mTaskConfig = new Configuration();
|
mTaskConfig = new Configuration();
|
||||||
|
|
||||||
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
|
mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mCallback, mContext,
|
||||||
TASK_ID, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
|
new Configuration(), TASK_ID, mTaskListener, mDisplayLayout,
|
||||||
|
false /* hasShownHint */);
|
||||||
|
|
||||||
spyOn(mLayout);
|
spyOn(mLayout);
|
||||||
spyOn(mLayout.mButtonWindowManager);
|
spyOn(mLayout.mButtonWindowManager);
|
||||||
@@ -145,7 +142,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
|
|
||||||
// No diff
|
// No diff
|
||||||
clearInvocations(mLayout);
|
clearInvocations(mLayout);
|
||||||
mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, mTaskListener,
|
mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener,
|
||||||
false /* isImeShowing */);
|
false /* isImeShowing */);
|
||||||
|
|
||||||
verify(mLayout, never()).updateButtonSurfacePosition();
|
verify(mLayout, never()).updateButtonSurfacePosition();
|
||||||
@@ -156,7 +153,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
clearInvocations(mLayout);
|
clearInvocations(mLayout);
|
||||||
final ShellTaskOrganizer.TaskListener newTaskListener = mock(
|
final ShellTaskOrganizer.TaskListener newTaskListener = mock(
|
||||||
ShellTaskOrganizer.TaskListener.class);
|
ShellTaskOrganizer.TaskListener.class);
|
||||||
mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, newTaskListener,
|
mLayout.updateSizeCompatInfo(mTaskConfig, newTaskListener,
|
||||||
false /* isImeShowing */);
|
false /* isImeShowing */);
|
||||||
|
|
||||||
verify(mLayout).release();
|
verify(mLayout).release();
|
||||||
@@ -166,7 +163,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
clearInvocations(mLayout);
|
clearInvocations(mLayout);
|
||||||
final Configuration newTaskConfiguration = new Configuration();
|
final Configuration newTaskConfiguration = new Configuration();
|
||||||
newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
|
newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
|
||||||
mLayout.updateSizeCompatInfo(newTaskConfiguration, mActivityToken, newTaskListener,
|
mLayout.updateSizeCompatInfo(newTaskConfiguration, newTaskListener,
|
||||||
false /* isImeShowing */);
|
false /* isImeShowing */);
|
||||||
|
|
||||||
verify(mLayout).updateButtonSurfacePosition();
|
verify(mLayout).updateButtonSurfacePosition();
|
||||||
@@ -228,12 +225,9 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnRestartButtonClicked() {
|
public void testOnRestartButtonClicked() {
|
||||||
spyOn(ActivityClient.getInstance());
|
|
||||||
doNothing().when(ActivityClient.getInstance()).restartActivityProcessIfVisible(any());
|
|
||||||
|
|
||||||
mLayout.onRestartButtonClicked();
|
mLayout.onRestartButtonClicked();
|
||||||
|
|
||||||
verify(ActivityClient.getInstance()).restartActivityProcessIfVisible(mActivityToken);
|
verify(mCallback).onSizeCompatRestartButtonClicked(TASK_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -1076,8 +1076,7 @@ class ActivityClientController extends IActivityClientController.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void restartActivityProcessIfVisible(IBinder token) {
|
||||||
public void restartActivityProcessIfVisible(IBinder token) {
|
|
||||||
ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess");
|
ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess");
|
||||||
final long callingId = Binder.clearCallingIdentity();
|
final long callingId = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3339,9 +3339,6 @@ class Task extends TaskFragment {
|
|||||||
info.topActivityInfo = mReuseActivitiesReport.top != null
|
info.topActivityInfo = mReuseActivitiesReport.top != null
|
||||||
? mReuseActivitiesReport.top.info
|
? mReuseActivitiesReport.top.info
|
||||||
: null;
|
: null;
|
||||||
info.topActivityToken = mReuseActivitiesReport.top != null
|
|
||||||
? mReuseActivitiesReport.top.appToken
|
|
||||||
: null;
|
|
||||||
// Whether the direct top activity is in size compat mode on foreground.
|
// Whether the direct top activity is in size compat mode on foreground.
|
||||||
info.topActivityInSizeCompat = mReuseActivitiesReport.top != null
|
info.topActivityInSizeCompat = mReuseActivitiesReport.top != null
|
||||||
&& mReuseActivitiesReport.top.getOrganizedTask() == this
|
&& mReuseActivitiesReport.top.getOrganizedTask() == this
|
||||||
|
|||||||
@@ -930,6 +930,34 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restartTaskTopActivityProcessIfVisible(WindowContainerToken token) {
|
||||||
|
enforceTaskPermission("restartTopActivityProcessIfVisible()");
|
||||||
|
final long origId = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
synchronized (mGlobalLock) {
|
||||||
|
final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
|
||||||
|
if (wc == null) {
|
||||||
|
Slog.w(TAG, "Could not resolve window from token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Task task = wc.asTask();
|
||||||
|
if (task == null) {
|
||||||
|
Slog.w(TAG, "Could not resolve task from token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
||||||
|
"Restart top activity process of Task taskId=%d", task.mTaskId);
|
||||||
|
final ActivityRecord activity = task.getTopNonFinishingActivity();
|
||||||
|
if (activity != null) {
|
||||||
|
activity.restartProcessIfVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(origId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
|
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
|
||||||
if (task == null || !task.isOrganized()
|
if (task == null || !task.isOrganized()
|
||||||
|| !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
|
|| !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
|
||||||
|
|||||||
@@ -597,7 +597,6 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
verify(mTask).onSizeCompatActivityChanged();
|
verify(mTask).onSizeCompatActivityChanged();
|
||||||
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
|
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
|
||||||
|
|
||||||
assertEquals(mActivity.appToken, taskInfo.topActivityToken);
|
|
||||||
assertTrue(taskInfo.topActivityInSizeCompat);
|
assertTrue(taskInfo.topActivityInSizeCompat);
|
||||||
|
|
||||||
// Make the activity resizable again by restarting it
|
// Make the activity resizable again by restarting it
|
||||||
@@ -613,7 +612,6 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
verify(mTask).onSizeCompatActivityChanged();
|
verify(mTask).onSizeCompatActivityChanged();
|
||||||
taskInfo = mTask.getTaskInfo();
|
taskInfo = mTask.getTaskInfo();
|
||||||
|
|
||||||
assertEquals(mActivity.appToken, taskInfo.topActivityToken);
|
|
||||||
assertFalse(taskInfo.topActivityInSizeCompat);
|
assertFalse(taskInfo.topActivityInSizeCompat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +630,6 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
verify(mTask).onSizeCompatActivityChanged();
|
verify(mTask).onSizeCompatActivityChanged();
|
||||||
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
|
ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();
|
||||||
|
|
||||||
assertEquals(mActivity.appToken, taskInfo.topActivityToken);
|
|
||||||
assertTrue(taskInfo.topActivityInSizeCompat);
|
assertTrue(taskInfo.topActivityInSizeCompat);
|
||||||
|
|
||||||
// Create another Task to hold another size compat activity.
|
// Create another Task to hold another size compat activity.
|
||||||
@@ -653,7 +650,6 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
verify(mTask, never()).onSizeCompatActivityChanged();
|
verify(mTask, never()).onSizeCompatActivityChanged();
|
||||||
taskInfo = secondTask.getTaskInfo();
|
taskInfo = secondTask.getTaskInfo();
|
||||||
|
|
||||||
assertEquals(secondActivity.appToken, taskInfo.topActivityToken);
|
|
||||||
assertTrue(taskInfo.topActivityInSizeCompat);
|
assertTrue(taskInfo.topActivityInSizeCompat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1228,7 +1228,6 @@ public class WindowOrganizerTests extends WindowTestsBase {
|
|||||||
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
||||||
RunningTaskInfo info = infoCaptor.getValue();
|
RunningTaskInfo info = infoCaptor.getValue();
|
||||||
assertEquals(rootTask.mTaskId, info.taskId);
|
assertEquals(rootTask.mTaskId, info.taskId);
|
||||||
assertEquals(activity.appToken, info.topActivityToken);
|
|
||||||
assertTrue(info.topActivityInSizeCompat);
|
assertTrue(info.topActivityInSizeCompat);
|
||||||
|
|
||||||
// Ensure task info show top activity that is not in foreground as not in size compat.
|
// Ensure task info show top activity that is not in foreground as not in size compat.
|
||||||
@@ -1239,7 +1238,6 @@ public class WindowOrganizerTests extends WindowTestsBase {
|
|||||||
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
||||||
info = infoCaptor.getValue();
|
info = infoCaptor.getValue();
|
||||||
assertEquals(rootTask.mTaskId, info.taskId);
|
assertEquals(rootTask.mTaskId, info.taskId);
|
||||||
assertEquals(activity.appToken, info.topActivityToken);
|
|
||||||
assertFalse(info.topActivityInSizeCompat);
|
assertFalse(info.topActivityInSizeCompat);
|
||||||
|
|
||||||
// Ensure task info show non size compat top activity as not in size compat.
|
// Ensure task info show non size compat top activity as not in size compat.
|
||||||
@@ -1251,7 +1249,6 @@ public class WindowOrganizerTests extends WindowTestsBase {
|
|||||||
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
verify(organizer).onTaskInfoChanged(infoCaptor.capture());
|
||||||
info = infoCaptor.getValue();
|
info = infoCaptor.getValue();
|
||||||
assertEquals(rootTask.mTaskId, info.taskId);
|
assertEquals(rootTask.mTaskId, info.taskId);
|
||||||
assertEquals(activity.appToken, info.topActivityToken);
|
|
||||||
assertFalse(info.topActivityInSizeCompat);
|
assertFalse(info.topActivityInSizeCompat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user