Add a UI Context for RootTaskDisplayAreaOrganizer
Bug: 175416931 Test: atest SplitScreenTests WMShellUnitTests Change-Id: Id11bfef19076840e46222014e268a553bd94f2ef
This commit is contained in:
parent
f749076910
commit
74e1d37cad
@ -2489,6 +2489,20 @@ class ContextImpl extends Context {
|
||||
return new WindowContext(this, display, type, options);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Context createTokenContext(@NonNull IBinder token, @NonNull Display display) {
|
||||
if (display == null) {
|
||||
throw new UnsupportedOperationException("Token context can only be created from "
|
||||
+ "other visual contexts, such as Activity or one created with "
|
||||
+ "Context#createDisplayContext(Display)");
|
||||
}
|
||||
final ContextImpl tokenContext = createBaseWindowContext(token, display);
|
||||
tokenContext.setResources(createWindowContextResources());
|
||||
return tokenContext;
|
||||
}
|
||||
|
||||
|
||||
ContextImpl createBaseWindowContext(IBinder token, Display display) {
|
||||
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
|
||||
mSplitName, token, mUser, mFlags, mClassLoader, null);
|
||||
|
@ -6014,10 +6014,13 @@ public abstract class Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* A special version of {@link #createWindowContext(int, Bundle)} which also takes
|
||||
* {@link Display}. The only difference between this API and
|
||||
* {@link #createWindowContext(int, Bundle)} is that this API can create window context from
|
||||
* any context even if the context which is not associated to a {@link Display} instance.
|
||||
* Creates a {@code Context} for a non-{@link android.app.Activity activity} window on the given
|
||||
* {@link Display}.
|
||||
*
|
||||
* <p>
|
||||
* Similar to {@link #createWindowContext(int, Bundle)}, but the {@code display} is passed in,
|
||||
* instead of implicitly using the {@link #getDisplay() original Context's Display}.
|
||||
* </p>
|
||||
*
|
||||
* @param display The {@link Display} to associate with
|
||||
* @param type Window type in {@link WindowManager.LayoutParams}
|
||||
@ -6122,6 +6125,21 @@ public abstract class Context {
|
||||
@SystemApi
|
||||
public abstract Context createCredentialProtectedStorageContext();
|
||||
|
||||
/**
|
||||
* Creates a UI context with a {@code token}. The users of this API should handle this context's
|
||||
* configuration changes.
|
||||
*
|
||||
* @param token The token to associate with the {@link Resources}
|
||||
* @param display The display to associate with the token context
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@UiContext
|
||||
@NonNull
|
||||
public Context createTokenContext(@NonNull IBinder token, @NonNull Display display) {
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display adjustments holder for this context. This information
|
||||
* is provided on a per-application or activity basis and is used to simulate lower density
|
||||
|
@ -21,6 +21,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.annotation.UiContext;
|
||||
import android.app.IApplicationThread;
|
||||
import android.app.IServiceConnection;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
@ -1049,6 +1050,14 @@ public class ContextWrapper extends Context {
|
||||
return mBase.createCredentialProtectedStorageContext();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@UiContext
|
||||
@NonNull
|
||||
@Override
|
||||
public Context createTokenContext(@NonNull IBinder token, @NonNull Display display) {
|
||||
return mBase.createTokenContext(token, display);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceProtectedStorage() {
|
||||
return mBase.isDeviceProtectedStorage();
|
||||
|
@ -16,13 +16,23 @@
|
||||
|
||||
package com.android.wm.shell;
|
||||
|
||||
import android.annotation.UiContext;
|
||||
import android.app.ResourcesManager;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.DisplayAreaAppearedInfo;
|
||||
import android.window.DisplayAreaInfo;
|
||||
import android.window.DisplayAreaOrganizer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@ -42,8 +52,13 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
private final SparseArray<ArrayList<RootTaskDisplayAreaListener>> mListeners =
|
||||
new SparseArray<>();
|
||||
|
||||
public RootTaskDisplayAreaOrganizer(Executor executor) {
|
||||
private final SparseArray<DisplayAreaContext> mDisplayAreaContexts = new SparseArray<>();
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public RootTaskDisplayAreaOrganizer(Executor executor, Context context) {
|
||||
super(executor);
|
||||
mContext = context;
|
||||
List<DisplayAreaAppearedInfo> infos = registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
|
||||
for (int i = infos.size() - 1; i >= 0; --i) {
|
||||
onDisplayAreaAppeared(infos.get(i).getDisplayAreaInfo(), infos.get(i).getLeash());
|
||||
@ -103,6 +118,7 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
listeners.get(i).onDisplayAreaAppeared(displayAreaInfo);
|
||||
}
|
||||
}
|
||||
applyConfigChangesToContext(displayId, displayAreaInfo.configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,6 +139,7 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
listeners.get(i).onDisplayAreaVanished(displayAreaInfo);
|
||||
}
|
||||
}
|
||||
mDisplayAreaContexts.remove(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -143,6 +160,33 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
listeners.get(i).onDisplayAreaInfoChanged(displayAreaInfo);
|
||||
}
|
||||
}
|
||||
applyConfigChangesToContext(displayId, displayAreaInfo.configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@link Configuration} to the {@link DisplayAreaContext} specified by
|
||||
* {@code displayId}.
|
||||
*
|
||||
* @param displayId The ID of the {@link Display} which the {@link DisplayAreaContext} is
|
||||
* associated with
|
||||
* @param newConfig The propagated configuration
|
||||
*/
|
||||
private void applyConfigChangesToContext(int displayId, @NonNull Configuration newConfig) {
|
||||
DisplayAreaContext daContext = mDisplayAreaContexts.get(displayId);
|
||||
if (daContext == null) {
|
||||
daContext = new DisplayAreaContext(mContext, displayId);
|
||||
mDisplayAreaContexts.put(displayId, daContext);
|
||||
}
|
||||
daContext.updateConfigurationChanges(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UI context associated with RootTaskDisplayArea specified by {@code displayId}.
|
||||
*/
|
||||
@Nullable
|
||||
@UiContext
|
||||
public Context getContext(int displayId) {
|
||||
return mDisplayAreaContexts.get(displayId);
|
||||
}
|
||||
|
||||
public void dump(@NonNull PrintWriter pw, String prefix) {
|
||||
@ -170,4 +214,32 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
default void dump(@NonNull PrintWriter pw, String prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A UI context to associate with a {@link com.android.server.wm.DisplayArea}.
|
||||
*
|
||||
* This context receives configuration changes through {@link DisplayAreaOrganizer} callbacks
|
||||
* and the core implementation is {@link Context#createTokenContext(IBinder, Display)} to apply
|
||||
* the configuration updates to the {@link android.content.res.Resources}.
|
||||
*/
|
||||
@UiContext
|
||||
public static class DisplayAreaContext extends ContextWrapper {
|
||||
private final IBinder mToken = new Binder();
|
||||
private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();
|
||||
|
||||
public DisplayAreaContext(@NonNull Context context, int displayId) {
|
||||
super(null);
|
||||
final Display display = context.getSystemService(DisplayManager.class)
|
||||
.getDisplay(displayId);
|
||||
attachBaseContext(context.createTokenContext(mToken, display));
|
||||
}
|
||||
|
||||
private void updateConfigurationChanges(@NonNull Configuration newConfig) {
|
||||
final Configuration config = getResources().getConfiguration();
|
||||
final boolean configChanged = config.diff(newConfig) != 0;
|
||||
if (configChanged) {
|
||||
mResourcesManager.updateResourcesForActivity(mToken, newConfig, getDisplayId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -285,7 +285,7 @@ public abstract class WMShellBaseModule {
|
||||
@Provides
|
||||
static RootTaskDisplayAreaOrganizer provideRootTaskDisplayAreaOrganizer(
|
||||
@ShellMainThread ShellExecutor mainExecutor, Context context) {
|
||||
return new RootTaskDisplayAreaOrganizer(mainExecutor);
|
||||
return new RootTaskDisplayAreaOrganizer(mainExecutor, context);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
@ -891,6 +891,12 @@ public class MockContext extends Context {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public Context createTokenContext(@NonNull IBinder token, @NonNull Display display) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceProtectedStorage() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
Loading…
x
Reference in New Issue
Block a user