Merge "RESTRICT AUTOMERGE: More improve IME transition during task switch" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d92e142ac4
@@ -88,4 +88,9 @@ oneway interface ITaskOrganizer {
|
|||||||
* user has pressed back on the root activity of a task controlled by the task organizer.
|
* user has pressed back on the root activity of a task controlled by the task organizer.
|
||||||
*/
|
*/
|
||||||
void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo);
|
void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the IME has drawn on the organized task.
|
||||||
|
*/
|
||||||
|
void onImeDrawnOnTask(int taskId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,10 @@ public class TaskOrganizer extends WindowOrganizer {
|
|||||||
@BinderThread
|
@BinderThread
|
||||||
public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
|
public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@BinderThread
|
||||||
|
public void onImeDrawnOnTask(int taskId) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a persistent root task in WM for a particular windowing-mode.
|
* Creates a persistent root task in WM for a particular windowing-mode.
|
||||||
* @param displayId The display to create the root task on.
|
* @param displayId The display to create the root task on.
|
||||||
@@ -287,6 +291,11 @@ public class TaskOrganizer extends WindowOrganizer {
|
|||||||
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
|
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
|
||||||
mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info));
|
mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImeDrawnOnTask(int taskId) {
|
||||||
|
mExecutor.execute(() -> TaskOrganizer.this.onImeDrawnOnTask(taskId));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private ITaskOrganizerController getController() {
|
private ITaskOrganizerController getController() {
|
||||||
|
|||||||
@@ -335,6 +335,13 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImeDrawnOnTask(int taskId) {
|
||||||
|
if (mStartingWindow != null) {
|
||||||
|
mStartingWindow.onImeDrawnOnTask(taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
|||||||
@@ -545,6 +545,15 @@ public class StartingSurfaceDrawer {
|
|||||||
removeWindowSynced(taskId, null, null, false);
|
removeWindowSynced(taskId, null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onImeDrawnOnTask(int taskId) {
|
||||||
|
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
|
||||||
|
if (record != null && record.mTaskSnapshotWindow != null
|
||||||
|
&& record.mTaskSnapshotWindow.hasImeSurface()) {
|
||||||
|
record.mTaskSnapshotWindow.removeImmediately();
|
||||||
|
}
|
||||||
|
mStartingWindowRecords.remove(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
protected void removeWindowSynced(int taskId, SurfaceControl leash, Rect frame,
|
protected void removeWindowSynced(int taskId, SurfaceControl leash, Rect frame,
|
||||||
boolean playRevealAnimation) {
|
boolean playRevealAnimation) {
|
||||||
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
|
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
|
||||||
@@ -572,14 +581,15 @@ public class StartingSurfaceDrawer {
|
|||||||
Slog.e(TAG, "Found empty splash screen, remove!");
|
Slog.e(TAG, "Found empty splash screen, remove!");
|
||||||
removeWindowInner(record.mDecorView, false);
|
removeWindowInner(record.mDecorView, false);
|
||||||
}
|
}
|
||||||
|
mStartingWindowRecords.remove(taskId);
|
||||||
}
|
}
|
||||||
if (record.mTaskSnapshotWindow != null) {
|
if (record.mTaskSnapshotWindow != null) {
|
||||||
if (DEBUG_TASK_SNAPSHOT) {
|
if (DEBUG_TASK_SNAPSHOT) {
|
||||||
Slog.v(TAG, "Removing task snapshot window for " + taskId);
|
Slog.v(TAG, "Removing task snapshot window for " + taskId);
|
||||||
}
|
}
|
||||||
record.mTaskSnapshotWindow.remove();
|
record.mTaskSnapshotWindow.scheduleRemove(
|
||||||
|
() -> mStartingWindowRecords.remove(taskId));
|
||||||
}
|
}
|
||||||
mStartingWindowRecords.remove(taskId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,6 +176,13 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
() -> mStartingSurfaceDrawer.onAppSplashScreenViewRemoved(taskId));
|
() -> mStartingSurfaceDrawer.onAppSplashScreenViewRemoved(taskId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the IME has drawn on the organized task.
|
||||||
|
*/
|
||||||
|
public void onImeDrawnOnTask(int taskId) {
|
||||||
|
mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.onImeDrawnOnTask(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the content of a task is ready to show, starting window can be removed.
|
* Called when the content of a task is ready to show, starting window can be removed.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ import android.graphics.RectF;
|
|||||||
import android.hardware.HardwareBuffer;
|
import android.hardware.HardwareBuffer;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.util.MergedConfiguration;
|
import android.util.MergedConfiguration;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -119,7 +118,12 @@ public class TaskSnapshotWindow {
|
|||||||
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
|
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
|
||||||
|
|
||||||
private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
|
private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
|
||||||
private static final long DELAY_REMOVAL_TIME_IME_VISIBLE = 350;
|
/**
|
||||||
|
* The max delay time in milliseconds for removing the task snapshot window with IME visible.
|
||||||
|
* Ideally the delay time will be shorter when receiving
|
||||||
|
* {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}.
|
||||||
|
*/
|
||||||
|
private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 450;
|
||||||
|
|
||||||
//tmp vars for unused relayout params
|
//tmp vars for unused relayout params
|
||||||
private static final Point TMP_SURFACE_SIZE = new Point();
|
private static final Point TMP_SURFACE_SIZE = new Point();
|
||||||
@@ -138,7 +142,6 @@ public class TaskSnapshotWindow {
|
|||||||
private final RectF mTmpDstFrame = new RectF();
|
private final RectF mTmpDstFrame = new RectF();
|
||||||
private final CharSequence mTitle;
|
private final CharSequence mTitle;
|
||||||
private boolean mHasDrawn;
|
private boolean mHasDrawn;
|
||||||
private long mShownTime;
|
|
||||||
private boolean mSizeMismatch;
|
private boolean mSizeMismatch;
|
||||||
private final Paint mBackgroundPaint = new Paint();
|
private final Paint mBackgroundPaint = new Paint();
|
||||||
private final int mActivityType;
|
private final int mActivityType;
|
||||||
@@ -148,6 +151,8 @@ public class TaskSnapshotWindow {
|
|||||||
private final SurfaceControl.Transaction mTransaction;
|
private final SurfaceControl.Transaction mTransaction;
|
||||||
private final Matrix mSnapshotMatrix = new Matrix();
|
private final Matrix mSnapshotMatrix = new Matrix();
|
||||||
private final float[] mTmpFloat9 = new float[9];
|
private final float[] mTmpFloat9 = new float[9];
|
||||||
|
private Runnable mScheduledRunnable;
|
||||||
|
private final boolean mHasImeSurface;
|
||||||
|
|
||||||
static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
|
static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
|
||||||
TaskSnapshot snapshot, ShellExecutor splashScreenExecutor,
|
TaskSnapshot snapshot, ShellExecutor splashScreenExecutor,
|
||||||
@@ -216,7 +221,7 @@ public class TaskSnapshotWindow {
|
|||||||
taskDescription.setBackgroundColor(WHITE);
|
taskDescription.setBackgroundColor(WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
final long delayRemovalTime = snapshot.hasImeSurface() ? DELAY_REMOVAL_TIME_IME_VISIBLE
|
final long delayRemovalTime = snapshot.hasImeSurface() ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
|
||||||
: DELAY_REMOVAL_TIME_GENERAL;
|
: DELAY_REMOVAL_TIME_GENERAL;
|
||||||
|
|
||||||
final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
|
final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
|
||||||
@@ -281,12 +286,17 @@ public class TaskSnapshotWindow {
|
|||||||
mDelayRemovalTime = delayRemovalTime;
|
mDelayRemovalTime = delayRemovalTime;
|
||||||
mTransaction = new SurfaceControl.Transaction();
|
mTransaction = new SurfaceControl.Transaction();
|
||||||
mClearWindowHandler = clearWindowHandler;
|
mClearWindowHandler = clearWindowHandler;
|
||||||
|
mHasImeSurface = snapshot.hasImeSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBackgroundColor() {
|
int getBackgroundColor() {
|
||||||
return mBackgroundPaint.getColor();
|
return mBackgroundPaint.getColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean hasImeSurface() {
|
||||||
|
return mHasImeSurface;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask system bar background painter to draw status bar background.
|
* Ask system bar background painter to draw status bar background.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -304,21 +314,32 @@ public class TaskSnapshotWindow {
|
|||||||
mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
|
mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove() {
|
void scheduleRemove(Runnable onRemove) {
|
||||||
final long now = SystemClock.uptimeMillis();
|
// Show the latest content as soon as possible for unlocking to home.
|
||||||
if ((now - mShownTime < mDelayRemovalTime)
|
if (mActivityType == ACTIVITY_TYPE_HOME) {
|
||||||
// Show the latest content as soon as possible for unlocking to home.
|
removeImmediately();
|
||||||
&& mActivityType != ACTIVITY_TYPE_HOME) {
|
onRemove.run();
|
||||||
final long delayTime = mShownTime + mDelayRemovalTime - now;
|
|
||||||
mSplashScreenExecutor.executeDelayed(() -> remove(), delayTime);
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TAG, "Defer removing snapshot surface in " + delayTime);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mScheduledRunnable != null) {
|
||||||
|
mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
|
||||||
|
mScheduledRunnable = null;
|
||||||
|
}
|
||||||
|
mScheduledRunnable = () -> {
|
||||||
|
TaskSnapshotWindow.this.removeImmediately();
|
||||||
|
onRemove.run();
|
||||||
|
};
|
||||||
|
mSplashScreenExecutor.executeDelayed(mScheduledRunnable, mDelayRemovalTime);
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Defer removing snapshot surface in " + mDelayRemovalTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeImmediately() {
|
||||||
|
mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
|
||||||
try {
|
try {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn);
|
Slog.d(TAG, "Removing taskSnapshot surface, mHasDrawn: " + mHasDrawn);
|
||||||
}
|
}
|
||||||
mSession.remove(mWindow);
|
mSession.remove(mWindow);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -356,7 +377,6 @@ public class TaskSnapshotWindow {
|
|||||||
} else {
|
} else {
|
||||||
drawSizeMatchSnapshot();
|
drawSizeMatchSnapshot();
|
||||||
}
|
}
|
||||||
mShownTime = SystemClock.uptimeMillis();
|
|
||||||
mHasDrawn = true;
|
mHasDrawn = true;
|
||||||
reportDrawn();
|
reportDrawn();
|
||||||
|
|
||||||
|
|||||||
@@ -15,38 +15,53 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.wm.shell.startingsurface;
|
package com.android.wm.shell.startingsurface;
|
||||||
|
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.ColorSpace;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.hardware.HardwareBuffer;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.testing.TestableContext;
|
import android.testing.TestableContext;
|
||||||
|
import android.view.IWindowSession;
|
||||||
|
import android.view.InsetsState;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.view.WindowManagerGlobal;
|
||||||
import android.view.WindowMetrics;
|
import android.view.WindowMetrics;
|
||||||
import android.window.StartingWindowInfo;
|
import android.window.StartingWindowInfo;
|
||||||
|
import android.window.TaskSnapshot;
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -61,6 +76,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.MockitoSession;
|
||||||
|
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
@@ -78,6 +94,7 @@ public class StartingSurfaceDrawerTests {
|
|||||||
private TransactionPool mTransactionPool;
|
private TransactionPool mTransactionPool;
|
||||||
|
|
||||||
private final Handler mTestHandler = new Handler(Looper.getMainLooper());
|
private final Handler mTestHandler = new Handler(Looper.getMainLooper());
|
||||||
|
private ShellExecutor mTestExecutor;
|
||||||
private final TestableContext mTestContext = new TestContext(
|
private final TestableContext mTestContext = new TestContext(
|
||||||
InstrumentationRegistry.getInstrumentation().getTargetContext());
|
InstrumentationRegistry.getInstrumentation().getTargetContext());
|
||||||
TestStartingSurfaceDrawer mStartingSurfaceDrawer;
|
TestStartingSurfaceDrawer mStartingSurfaceDrawer;
|
||||||
@@ -138,9 +155,9 @@ public class StartingSurfaceDrawerTests {
|
|||||||
|
|
||||||
doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
|
doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
|
||||||
doNothing().when(mMockWindowManager).addView(any(), any());
|
doNothing().when(mMockWindowManager).addView(any(), any());
|
||||||
|
mTestExecutor = new HandlerExecutor(mTestHandler);
|
||||||
mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(mTestContext,
|
mStartingSurfaceDrawer = spy(
|
||||||
new HandlerExecutor(mTestHandler), mTransactionPool));
|
new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mTransactionPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -205,6 +222,48 @@ public class StartingSurfaceDrawerTests {
|
|||||||
assertEquals(0, windowColor3.mReuseCount);
|
assertEquals(0, windowColor3.mReuseCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveTaskSnapshotWithImeSurfaceWhenOnImeDrawn() throws Exception {
|
||||||
|
final int taskId = 1;
|
||||||
|
final StartingWindowInfo windowInfo =
|
||||||
|
createWindowInfo(taskId, android.R.style.Theme);
|
||||||
|
TaskSnapshot snapshot = createTaskSnapshot(100, 100, new Point(100, 100),
|
||||||
|
new Rect(0, 0, 0, 50), true /* hasImeSurface */);
|
||||||
|
final IWindowSession session = WindowManagerGlobal.getWindowSession();
|
||||||
|
spyOn(session);
|
||||||
|
doReturn(WindowManagerGlobal.ADD_OKAY).when(session).addToDisplay(
|
||||||
|
any() /* window */, any() /* attrs */,
|
||||||
|
anyInt() /* viewVisibility */, anyInt() /* displayId */,
|
||||||
|
any() /* requestedVisibility */, any() /* outInputChannel */,
|
||||||
|
any() /* outInsetsState */, any() /* outActiveControls */);
|
||||||
|
TaskSnapshotWindow mockSnapshotWindow = TaskSnapshotWindow.create(windowInfo,
|
||||||
|
mBinder,
|
||||||
|
snapshot, mTestExecutor, () -> {
|
||||||
|
});
|
||||||
|
spyOn(mockSnapshotWindow);
|
||||||
|
try (AutoCloseable mockTaskSnapshotSession = new AutoCloseable() {
|
||||||
|
MockitoSession mockSession = mockitoSession()
|
||||||
|
.initMocks(this)
|
||||||
|
.mockStatic(TaskSnapshotWindow.class)
|
||||||
|
.startMocking();
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
mockSession.finishMocking();
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
when(TaskSnapshotWindow.create(eq(windowInfo), eq(mBinder), eq(snapshot), any(),
|
||||||
|
any())).thenReturn(mockSnapshotWindow);
|
||||||
|
// Simulate a task snapshot window created with IME snapshot shown.
|
||||||
|
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, mBinder, snapshot);
|
||||||
|
waitHandlerIdle(mTestHandler);
|
||||||
|
|
||||||
|
// Verify the task snapshot with IME snapshot will be removed when received the real IME
|
||||||
|
// drawn callback.
|
||||||
|
mStartingSurfaceDrawer.onImeDrawnOnTask(1);
|
||||||
|
verify(mockSnapshotWindow).removeImmediately();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
|
private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
|
||||||
StartingWindowInfo windowInfo = new StartingWindowInfo();
|
StartingWindowInfo windowInfo = new StartingWindowInfo();
|
||||||
final ActivityInfo info = new ActivityInfo();
|
final ActivityInfo info = new ActivityInfo();
|
||||||
@@ -216,10 +275,27 @@ public class StartingSurfaceDrawerTests {
|
|||||||
taskInfo.taskId = taskId;
|
taskInfo.taskId = taskId;
|
||||||
windowInfo.targetActivityInfo = info;
|
windowInfo.targetActivityInfo = info;
|
||||||
windowInfo.taskInfo = taskInfo;
|
windowInfo.taskInfo = taskInfo;
|
||||||
|
windowInfo.topOpaqueWindowInsetsState = new InsetsState();
|
||||||
|
windowInfo.mainWindowLayoutParams = new WindowManager.LayoutParams();
|
||||||
|
windowInfo.topOpaqueWindowLayoutParams = new WindowManager.LayoutParams();
|
||||||
return windowInfo;
|
return windowInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void waitHandlerIdle(Handler handler) {
|
private static void waitHandlerIdle(Handler handler) {
|
||||||
handler.runWithScissors(() -> { }, 0 /* timeout */);
|
handler.runWithScissors(() -> { }, 0 /* timeout */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
|
||||||
|
Rect contentInsets, boolean hasImeSurface) {
|
||||||
|
final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
|
||||||
|
1, HardwareBuffer.USAGE_CPU_READ_RARELY);
|
||||||
|
return new TaskSnapshot(
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
new ComponentName("", ""), buffer,
|
||||||
|
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
|
||||||
|
Surface.ROTATION_0, taskSize, contentInsets, false,
|
||||||
|
true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
|
||||||
|
0 /* systemUiVisibility */, false /* isTranslucent */,
|
||||||
|
hasImeSurface /* hasImeSurface */);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2253,6 +2253,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeStartingWindowIfNeeded() {
|
||||||
|
// Removing the task snapshot after the task is actually focused (see
|
||||||
|
// Task#onWindowFocusChanged). Since some of the app contents may draw in this time and
|
||||||
|
// requires more times to draw finish, in case flicking may happen when removing the task
|
||||||
|
// snapshot too early. (i.e. Showing IME.)
|
||||||
|
if ((mStartingData instanceof SnapshotStartingData) && !getTask().isFocused()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeStartingWindow();
|
||||||
|
}
|
||||||
|
|
||||||
void removeStartingWindow() {
|
void removeStartingWindow() {
|
||||||
removeStartingWindowAnimation(true /* prepareAnimation */);
|
removeStartingWindowAnimation(true /* prepareAnimation */);
|
||||||
}
|
}
|
||||||
@@ -5824,7 +5835,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
// own stuff.
|
// own stuff.
|
||||||
win.cancelAnimation();
|
win.cancelAnimation();
|
||||||
}
|
}
|
||||||
removeStartingWindow();
|
removeStartingWindowIfNeeded();
|
||||||
updateReportedVisibilityLocked();
|
updateReportedVisibilityLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,24 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
|
|||||||
onSourceChanged();
|
onSourceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean updateClientVisibility(InsetsControlTarget caller) {
|
||||||
|
boolean changed = super.updateClientVisibility(caller);
|
||||||
|
if (changed && caller.getRequestedVisibility(mSource.getType())) {
|
||||||
|
reportImeDrawnForOrganizer(caller);
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reportImeDrawnForOrganizer(InsetsControlTarget caller) {
|
||||||
|
if (caller.getWindow() != null && caller.getWindow().getTask() != null) {
|
||||||
|
if (caller.getWindow().getTask().isOrganized()) {
|
||||||
|
mWin.mWmService.mAtmService.mTaskOrganizerController.reportImeDrawnOnTask(
|
||||||
|
caller.getWindow().getTask());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onSourceChanged() {
|
private void onSourceChanged() {
|
||||||
if (mLastSource.equals(mSource)) {
|
if (mLastSource.equals(mSource)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5144,7 +5144,7 @@ class Task extends WindowContainer<WindowContainer> {
|
|||||||
/**
|
/**
|
||||||
* @return true if the task is currently focused.
|
* @return true if the task is currently focused.
|
||||||
*/
|
*/
|
||||||
private boolean isFocused() {
|
boolean isFocused() {
|
||||||
if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
|
if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5206,6 +5206,10 @@ class Task extends WindowContainer<WindowContainer> {
|
|||||||
* @param hasFocus
|
* @param hasFocus
|
||||||
*/
|
*/
|
||||||
void onWindowFocusChanged(boolean hasFocus) {
|
void onWindowFocusChanged(boolean hasFocus) {
|
||||||
|
final ActivityRecord topAct = getTopVisibleActivity();
|
||||||
|
if (topAct != null && (topAct.mStartingData instanceof SnapshotStartingData)) {
|
||||||
|
topAct.removeStartingWindowIfNeeded();
|
||||||
|
}
|
||||||
updateShadowsRadius(hasFocus, getSyncTransaction());
|
updateShadowsRadius(hasFocus, getSyncTransaction());
|
||||||
// TODO(b/180525887): Un-comment once there is resolution on the bug.
|
// TODO(b/180525887): Un-comment once there is resolution on the bug.
|
||||||
// dispatchTaskInfoChangedIfNeeded(false /* force */);
|
// dispatchTaskInfoChangedIfNeeded(false /* force */);
|
||||||
|
|||||||
@@ -733,6 +733,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
|||||||
mPendingTaskEvents.clear();
|
mPendingTaskEvents.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reportImeDrawnOnTask(Task task) {
|
||||||
|
final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
|
||||||
|
if (state != null) {
|
||||||
|
try {
|
||||||
|
state.mOrganizer.mTaskOrganizer.onImeDrawnOnTask(task.mTaskId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Exception sending onImeDrawnOnTask callback", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onTaskInfoChanged(Task task, boolean force) {
|
void onTaskInfoChanged(Task task, boolean force) {
|
||||||
if (!task.mTaskAppearedSent) {
|
if (!task.mTaskAppearedSent) {
|
||||||
// Skip if task still not appeared.
|
// Skip if task still not appeared.
|
||||||
|
|||||||
@@ -797,6 +797,9 @@ public class WindowOrganizerTests extends WindowTestsBase {
|
|||||||
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
|
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
public void onImeDrawnOnTask(int taskId) throws RemoteException {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public void onAppSplashScreenViewRemoved(int taskId) {
|
public void onAppSplashScreenViewRemoved(int taskId) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user