Switch to using newly exposed method Bubbles#showAppBubble as what FloatingTaskController does is no longer POR. Calling this allows 1 bubble from a specific app to be added to the stack. The only user of this method is NoteTaskController which is guarded by the NOTE_TASK. Bug: 237678727 Test: treehugger Change-Id: I47c5c010a050796eff848ba3fcabc40cf5fbd902
183 lines
7.6 KiB
Java
183 lines
7.6 KiB
Java
/*
|
|
* Copyright (C) 2022 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;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.Resources;
|
|
import android.os.Handler;
|
|
import android.os.HandlerThread;
|
|
import android.util.Log;
|
|
|
|
import com.android.systemui.dagger.GlobalRootComponent;
|
|
import com.android.systemui.dagger.SysUIComponent;
|
|
import com.android.systemui.dagger.WMComponent;
|
|
import com.android.systemui.util.InitializationChecker;
|
|
import com.android.wm.shell.dagger.WMShellConcurrencyModule;
|
|
import com.android.wm.shell.sysui.ShellInterface;
|
|
import com.android.wm.shell.transition.ShellTransitions;
|
|
|
|
import java.util.Optional;
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
/**
|
|
* Initializer that stands up SystemUI.
|
|
*
|
|
* Implementations should override {@link #getGlobalRootComponentBuilder()} to fill in their own
|
|
* Dagger root component.
|
|
*/
|
|
public abstract class SystemUIInitializer {
|
|
private static final String TAG = "SystemUIFactory";
|
|
|
|
private final Context mContext;
|
|
|
|
private GlobalRootComponent mRootComponent;
|
|
private WMComponent mWMComponent;
|
|
private SysUIComponent mSysUIComponent;
|
|
private InitializationChecker mInitializationChecker;
|
|
|
|
public SystemUIInitializer(Context context) {
|
|
mContext = context;
|
|
}
|
|
|
|
protected abstract GlobalRootComponent.Builder getGlobalRootComponentBuilder();
|
|
|
|
/**
|
|
* Prepares the SysUIComponent builder before it is built.
|
|
* @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method
|
|
* @param wm the built WMComponent from the root component's getWMComponent() method
|
|
*/
|
|
protected SysUIComponent.Builder prepareSysUIComponentBuilder(
|
|
SysUIComponent.Builder sysUIBuilder, WMComponent wm) {
|
|
return sysUIBuilder;
|
|
}
|
|
|
|
/**
|
|
* Starts the initialization process. This stands up the Dagger graph.
|
|
*/
|
|
public void init(boolean fromTest) throws ExecutionException, InterruptedException {
|
|
mRootComponent = getGlobalRootComponentBuilder()
|
|
.context(mContext)
|
|
.instrumentationTest(fromTest)
|
|
.build();
|
|
|
|
mInitializationChecker = mRootComponent.getInitializationChecker();
|
|
boolean initializeComponents = mInitializationChecker.initializeComponents();
|
|
|
|
// Stand up WMComponent
|
|
setupWmComponent(mContext);
|
|
|
|
// And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
|
|
SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
|
|
if (initializeComponents) {
|
|
// Only initialize when not starting from tests since this currently initializes some
|
|
// components that shouldn't be run in the test environment
|
|
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
|
|
.setShell(mWMComponent.getShell())
|
|
.setPip(mWMComponent.getPip())
|
|
.setSplitScreen(mWMComponent.getSplitScreen())
|
|
.setOneHanded(mWMComponent.getOneHanded())
|
|
.setBubbles(mWMComponent.getBubbles())
|
|
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
|
|
.setTransitions(mWMComponent.getTransitions())
|
|
.setStartingSurface(mWMComponent.getStartingSurface())
|
|
.setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
|
|
.setRecentTasks(mWMComponent.getRecentTasks())
|
|
.setBackAnimation(mWMComponent.getBackAnimation())
|
|
.setDesktopMode(mWMComponent.getDesktopMode());
|
|
|
|
// Only initialize when not starting from tests since this currently initializes some
|
|
// components that shouldn't be run in the test environment
|
|
mWMComponent.init();
|
|
} else {
|
|
// TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
|
|
// is separating this logic into newly creating SystemUITestsFactory.
|
|
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
|
|
.setShell(new ShellInterface() {})
|
|
.setPip(Optional.ofNullable(null))
|
|
.setSplitScreen(Optional.ofNullable(null))
|
|
.setOneHanded(Optional.ofNullable(null))
|
|
.setBubbles(Optional.ofNullable(null))
|
|
.setTaskViewFactory(Optional.ofNullable(null))
|
|
.setTransitions(new ShellTransitions() {})
|
|
.setDisplayAreaHelper(Optional.ofNullable(null))
|
|
.setStartingSurface(Optional.ofNullable(null))
|
|
.setRecentTasks(Optional.ofNullable(null))
|
|
.setBackAnimation(Optional.ofNullable(null))
|
|
.setDesktopMode(Optional.ofNullable(null));
|
|
}
|
|
mSysUIComponent = builder.build();
|
|
if (initializeComponents) {
|
|
mSysUIComponent.init();
|
|
}
|
|
|
|
// Every other part of our codebase currently relies on Dependency, so we
|
|
// really need to ensure the Dependency gets initialized early on.
|
|
Dependency dependency = mSysUIComponent.createDependency();
|
|
dependency.start();
|
|
}
|
|
|
|
/**
|
|
* Sets up {@link #mWMComponent}. On devices where the Shell runs on its own main thread,
|
|
* this will pre-create the thread to ensure that the components are constructed on the
|
|
* same thread, to reduce the likelihood of side effects from running the constructors on
|
|
* a different thread than the rest of the class logic.
|
|
*/
|
|
private void setupWmComponent(Context context) {
|
|
WMComponent.Builder wmBuilder = mRootComponent.getWMComponentBuilder();
|
|
if (!mInitializationChecker.initializeComponents()
|
|
|| !WMShellConcurrencyModule.enableShellMainThread(context)) {
|
|
// If running under tests or shell thread is not enabled, we don't need anything special
|
|
mWMComponent = wmBuilder.build();
|
|
return;
|
|
}
|
|
|
|
// If the shell main thread is enabled, initialize the component on that thread
|
|
HandlerThread shellThread = WMShellConcurrencyModule.createShellMainThread();
|
|
shellThread.start();
|
|
|
|
// Use an async handler since we don't care about synchronization
|
|
Handler shellHandler = Handler.createAsync(shellThread.getLooper());
|
|
boolean built = shellHandler.runWithScissors(() -> {
|
|
wmBuilder.setShellMainThread(shellThread);
|
|
mWMComponent = wmBuilder.build();
|
|
}, 5000);
|
|
if (!built) {
|
|
Log.w(TAG, "Failed to initialize WMComponent");
|
|
throw new RuntimeException();
|
|
}
|
|
}
|
|
|
|
public GlobalRootComponent getRootComponent() {
|
|
return mRootComponent;
|
|
}
|
|
|
|
public WMComponent getWMComponent() {
|
|
return mWMComponent;
|
|
}
|
|
|
|
public SysUIComponent getSysUIComponent() {
|
|
return mSysUIComponent;
|
|
}
|
|
|
|
/**
|
|
* Returns the list of additional system UI components that should be started.
|
|
*/
|
|
public String getVendorComponent(Resources resources) {
|
|
return resources.getString(R.string.config_systemUIVendorServiceComponent);
|
|
}
|
|
}
|