Let Launcher able to receive task launching callback(3/N)

When StartingWindowController receive addStartingWindow, send a callback
out so a listener can know whether current launch cold or warm.

Ref doc: go/starting_window_android_s

Bug: 131311659
Bug: 131727939
Bug: 152480470

Test: atest WindowOrganizerTests StartingSurfaceDrawerTests
SplashscreenTests

Change-Id: Ic9f02f51d5de141b56a8f28003bf1cb1a5a63f22
This commit is contained in:
wilsonshih
2020-11-05 15:00:54 +08:00
parent 1623f60d39
commit 8b7b5e6781
6 changed files with 107 additions and 3 deletions

View File

@@ -19,6 +19,7 @@ package com.android.wm.shell.startingsurface;
import android.os.IBinder;
import android.window.StartingWindowInfo;
import java.util.function.BiConsumer;
/**
* Interface to engage starting window feature.
*/
@@ -36,4 +37,11 @@ public interface StartingSurface {
* @param taskId
*/
void copySplashScreenView(int taskId);
/**
* Registers the starting window listener.
*
* @param listener The callback when need a starting window.
*/
void setStartingWindowListener(BiConsumer<Integer, Integer> listener);
}

View File

@@ -25,6 +25,7 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.os.IBinder;
@@ -36,6 +37,8 @@ import android.window.TaskSnapshot;
import com.android.wm.shell.common.ShellExecutor;
import java.util.function.BiConsumer;
/**
* Implementation to draw the starting window to an application, and remove the starting window
* until the application displays its own window.
@@ -53,6 +56,8 @@ public class StartingWindowController {
private final StartingSurfaceDrawer mStartingSurfaceDrawer;
private final StartingTypeChecker mStartingTypeChecker = new StartingTypeChecker();
private BiConsumer<Integer, Integer> mTaskLaunchingCallback;
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
public StartingWindowController(Context context, ShellExecutor mainExecutor) {
@@ -151,11 +156,24 @@ public class StartingWindowController {
}
}
/*
* Registers the starting window listener.
*
* @param listener The callback when need a starting window.
*/
void setStartingWindowListener(BiConsumer<Integer, Integer> listener) {
mTaskLaunchingCallback = listener;
}
/**
* Called when a task need a starting window.
*/
void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
if (mTaskLaunchingCallback != null) {
mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
}
if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
@@ -192,5 +210,10 @@ public class StartingWindowController {
public void copySplashScreenView(int taskId) {
StartingWindowController.this.copySplashScreenView(taskId);
}
@Override
public void setStartingWindowListener(BiConsumer<Integer, Integer> listener) {
StartingWindowController.this.setStartingWindowListener(listener);
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.shared.recents;
/**
* Listener interface that Launcher attaches to SystemUI to get
* callbacks when need a new starting window.
*/
interface IStartingWindowListener {
/**
* Notifies when Shell going to create a new starting window.
* @param taskId The task Id
* @param supportedType The starting window type
*/
oneway void onTaskLaunching(int taskId, int supportedType);
}

View File

@@ -30,12 +30,13 @@ import android.view.MotionEvent;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISplitScreenListener;
import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;
/**
* Temporary callbacks into SystemUI.
* Next id = 43
* Next id = 44
*/
interface ISystemUiProxy {
@@ -255,4 +256,8 @@ interface ISystemUiProxy {
in PendingIntent intent, in Intent fillInIntent, in int stage, in int position,
in Bundle options) = 41;
void removeFromSideStage(in int taskId) = 42;
/**
* Sets listener to get task launching callbacks.
*/
void setStartingWindowListener(IStartingWindowListener listener) = 43;
}

View File

@@ -85,6 +85,7 @@ import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISplitScreenListener;
import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,6 +102,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.transition.RemoteTransitions;
import java.io.FileDescriptor;
@@ -150,6 +152,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final Optional<OneHanded> mOneHandedOptional;
private final CommandQueue mCommandQueue;
private final RemoteTransitions mShellTransitions;
private final Optional<StartingSurface> mStartingSurface;
private Region mActiveNavBarRegion;
@@ -167,6 +170,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private final ArraySet<IRemoteTransition> mRemoteTransitions = new ArraySet<>();
private IStartingWindowListener mIStartingWindowListener;
@VisibleForTesting
public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@@ -439,6 +443,21 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
@Override
public void setStartingWindowListener(IStartingWindowListener listener) {
if (!verifyCaller("setStartingWindowListener")) {
return;
}
mIStartingWindowListener = listener;
final long token = Binder.clearCallingIdentity();
try {
mStartingSurface.ifPresent(s ->
s.setStartingWindowListener(mStartingWindowListener));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
if (!verifyCaller("onQuickSwitchToNewTask")) {
@@ -785,6 +804,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final Consumer<Boolean> mPinnedStackAnimationCallback =
this::notifyPinnedStackAnimationStarted;
private final BiConsumer<Integer, Integer> mStartingWindowListener =
this::notifyTaskLaunching;
// This is the death handler for the binder from the launcher service
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
@@ -827,7 +849,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
Optional<Lazy<StatusBar>> statusBarOptionalLazy,
Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher,
RemoteTransitions shellTransitions) {
RemoteTransitions shellTransitions,
Optional<StartingSurface> startingSurface) {
super(broadcastDispatcher);
mContext = context;
mPipOptional = pipOptional;
@@ -887,6 +910,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
// Connect to the service
updateEnabledState();
startConnectionToCurrentUser();
mStartingSurface = startingSurface;
}
@Override
@@ -953,6 +977,18 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
private void notifyTaskLaunching(int taskId, int supportedType) {
if (mIStartingWindowListener == null) {
return;
}
try {
mIStartingWindowListener.onTaskLaunching(taskId, supportedType);
} catch (RemoteException e) {
Log.e(TAG_OPS, "Failed to call notifyTaskLaunching()", e);
}
}
private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
boolean bouncerShowing) {
mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,

View File

@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.transition.RemoteTransitions;
import org.junit.Before;
@@ -79,6 +80,7 @@ public class OverviewProxyServiceTest extends SysuiTestCase {
@Mock private PackageManager mPackageManager;
@Mock private SysUiState mMockSysUiState;
@Mock private RemoteTransitions mMockTransitions;
@Mock private Optional<StartingSurface> mStartingSurface;
@Before
public void setUp() throws RemoteException {
@@ -93,7 +95,7 @@ public class OverviewProxyServiceTest extends SysuiTestCase {
mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController,
mMockSysUiState, mMockPipOptional, mMockLegacySplitScreenOptional,
mMockSplitScreenOptional, mMockStatusBarOptionalLazy, mMockOneHandedOptional,
mMockBroadcastDispatcher, mMockTransitions));
mMockBroadcastDispatcher, mMockTransitions, mStartingSurface));
}
@Test