Loading core/java/android/app/ActivityThread.java +1 −1 Original line number Diff line number Diff line Loading @@ -2328,7 +2328,7 @@ public final class ActivityThread extends ClientTransactionHandler } @UnsupportedAppUsage final Handler getHandler() { public Handler getHandler() { return mH; } Loading core/java/android/app/ContextImpl.java +108 −31 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package android.app; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.StrictMode.vmIncorrectContextUseEnabled; import static android.view.WindowManager.LayoutParams.WindowType; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.compat.annotation.UnsupportedAppUsage; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -87,6 +89,8 @@ import android.util.Slog; import android.view.Display; import android.view.DisplayAdjustments; import android.view.autofill.AutofillManager.AutofillClient; import android.window.WindowContext; import android.window.WindowTokenClient; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; Loading Loading @@ -2563,23 +2567,63 @@ class ContextImpl extends Context { @NonNull @Override public WindowContext createWindowContext(int type, @NonNull Bundle options) { public WindowContext createWindowContext(@WindowType int type, @Nullable Bundle options) { if (getDisplay() == null) { throw new UnsupportedOperationException("WindowContext can only be created from " + "other visual contexts, such as Activity or one created with " + "Context#createDisplayContext(Display)"); throw new UnsupportedOperationException("Please call this API with context associated" + " with a display instance, such as Activity or context created via" + " Context#createDisplayContext(Display), or try to invoke" + " Context#createWindowContext(Display, int, Bundle)"); } return new WindowContext(this, type, options); return createWindowContextInternal(getDisplay(), type, options); } @NonNull @Override public WindowContext createWindowContext(@NonNull Display display, int type, @NonNull Bundle options) { public WindowContext createWindowContext(@NonNull Display display, @WindowType int type, @Nullable Bundle options) { if (display == null) { throw new IllegalArgumentException("Display must not be null"); } return new WindowContext(this, display, type, options); return createWindowContextInternal(display, type, options); } /** * The internal implementation of {@link Context#createWindowContext(int, Bundle)} and * {@link Context#createWindowContext(Display, int, Bundle)}. * * @param display The {@link Display} instance to be associated with. * * @see Context#createWindowContext(Display, int, Bundle) * @see Context#createWindowContext(int, Bundle) */ private WindowContext createWindowContextInternal(@NonNull Display display, @WindowType int type, @Nullable Bundle options) { // Step 1. Create a WindowTokenClient to associate with the WindowContext's Resources // instance and it will be later used to receive configuration updates from the // server side. final WindowTokenClient windowTokenClient = new WindowTokenClient(); // Step 2. Create the base context of the window context, it will also create a Resources // associated with the WindowTokenClient and set the token to the base context. final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient, display); // Step 3. Create a WindowContext instance and set it as the outer context of the base // context to make the service obtained by #getSystemService(String) able to query // the WindowContext's WindowManager instead of the default one. final WindowContext windowContext = new WindowContext(windowContextBase, type, options); windowContextBase.setOuterContext(windowContext); // Step 4. Attach the WindowContext to the WindowTokenClient. In this way, when there's a // configuration update from the server side, the update will then apply to // WindowContext's resources. windowTokenClient.attachContext(windowContext); // Step 5. Register the window context's token to the server side to associate with a // window manager node. windowContext.registerWithServer(); return windowContext; } @NonNull Loading @@ -2588,40 +2632,65 @@ class ContextImpl extends Context { if (display == null) { throw new IllegalArgumentException("Display must not be null"); } final ContextImpl tokenContext = createBaseWindowContext(token, display); tokenContext.setResources(createWindowContextResources()); final ContextImpl tokenContext = createWindowContextBase(token, display); tokenContext.setResources(createWindowContextResources(tokenContext)); return tokenContext; } ContextImpl createBaseWindowContext(IBinder token, Display display) { ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams, /** * Creates the base {@link Context} for UI context to associate with a non-{@link Activity} * window. * * @param token The token to associate with {@link Resources} * @param display The {@link Display} to associate with. * * @see #createWindowContext(Display, int, Bundle) * @see #createTokenContext(IBinder, Display) */ @UiContext ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) { ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName, token, mUser, mFlags, mClassLoader, null); // Window contexts receive configurations directly from the server and as such do not // need to override their display in ResourcesManager. context.mForceDisplayOverrideInResources = false; context.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; if (display != null) { context.mDisplay = display; } return context; baseContext.mForceDisplayOverrideInResources = false; baseContext.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; baseContext.mDisplay = display; final Resources windowContextResources = createWindowContextResources(baseContext); baseContext.setResources(windowContextResources); return baseContext; } Resources createWindowContextResources() { final String resDir = mPackageInfo.getResDir(); final String[] splitResDirs = mPackageInfo.getSplitResDirs(); final String[] legacyOverlayDirs = mPackageInfo.getOverlayDirs(); final String[] overlayPaths = mPackageInfo.getOverlayPaths(); final String[] libDirs = mPackageInfo.getApplicationInfo().sharedLibraryFiles; final int displayId = getDisplayId(); /** * Creates the {@link Resources} to associate with the {@link WindowContext}'s token. * * When there's a {@link Configuration} update, this Resources instance will be updated to match * the new configuration. * * @see WindowTokenClient * @see #getWindowContextToken() */ private static Resources createWindowContextResources(@NonNull ContextImpl windowContextBase) { final LoadedApk packageInfo = windowContextBase.mPackageInfo; final ClassLoader classLoader = windowContextBase.mClassLoader; final IBinder token = windowContextBase.getWindowContextToken(); final String resDir = packageInfo.getResDir(); final String[] splitResDirs = packageInfo.getSplitResDirs(); final String[] legacyOverlayDirs = packageInfo.getOverlayDirs(); final String[] overlayPaths = packageInfo.getOverlayPaths(); final String[] libDirs = packageInfo.getApplicationInfo().sharedLibraryFiles; final int displayId = windowContextBase.getDisplayId(); final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY) ? mPackageInfo.getCompatibilityInfo() ? packageInfo.getCompatibilityInfo() : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; final List<ResourcesLoader> loaders = mResources.getLoaders(); final List<ResourcesLoader> loaders = windowContextBase.mResources.getLoaders(); return mResourcesManager.createBaseTokenResources(mToken, resDir, splitResDirs, legacyOverlayDirs, overlayPaths, libDirs, displayId, null /* overrideConfig */, compatInfo, mClassLoader, loaders); return windowContextBase.mResourcesManager.createBaseTokenResources(token, resDir, splitResDirs, legacyOverlayDirs, overlayPaths, libDirs, displayId, null /* overrideConfig */, compatInfo, classLoader, loaders); } @NonNull Loading Loading @@ -3114,6 +3183,14 @@ class ContextImpl extends Context { return result; } @Override public void destroy() { // The final clean-up is to release BroadcastReceiver registrations. It is called in // ActivityThread for Activity and Service. For the context, such as WindowContext, // without lifecycle concept, it should be called once the context is released. scheduleFinalCleanup(getClass().getName(), getOuterContext().getClass().getSimpleName()); } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- Loading core/java/android/app/ResourcesManager.java +2 −3 Original line number Diff line number Diff line Loading @@ -39,13 +39,13 @@ import android.os.IBinder; import android.os.Process; import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.view.Display; import android.view.DisplayAdjustments; import android.window.WindowContext; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; Loading @@ -61,7 +61,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.WeakHashMap; Loading Loading @@ -168,7 +167,7 @@ public class ResourcesManager { /** * Class containing the base configuration override and set of resources associated with an * Activity or {@link WindowContext}. * {@link Activity} or a {@link WindowContext}. */ private static class ActivityResources { /** Loading core/java/android/content/Context.java +12 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.view.WindowManager.LayoutParams.WindowType; import android.view.autofill.AutofillManager.AutofillClient; import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient; import android.view.textclassifier.TextClassificationManager; import android.window.WindowContext; import com.android.internal.compat.IPlatformCompat; import com.android.internal.compat.IPlatformCompatNative; Loading Loading @@ -6793,4 +6794,15 @@ public abstract class Context { public boolean isUiContext() { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Called when a {@link Context} is going to be released. * This method can be overridden to perform the final cleanups, such as release * {@link BroadcastReceiver} registrations. * * @see WindowContext#destroy() * * @hide */ public void destroy() { } } core/java/android/view/IWindowManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -777,11 +777,11 @@ interface IWindowManager VerifiedDisplayHash verifyDisplayHash(in DisplayHash displayHash); /** * Registers a listener for a {@link android.app.WindowContext} to handle configuration changes * from the server side. * Registers a listener for a {@link android.window.WindowContext} to handle configuration * changes from the server side. * <p> * Note that this API should be invoked after calling * {@link android.app.WindowTokenClient#attachContext(WindowContext)} * {@link android.window.WindowTokenClient#attachContext(Context)} * </p> * * @param clientToken the window context's token Loading Loading
core/java/android/app/ActivityThread.java +1 −1 Original line number Diff line number Diff line Loading @@ -2328,7 +2328,7 @@ public final class ActivityThread extends ClientTransactionHandler } @UnsupportedAppUsage final Handler getHandler() { public Handler getHandler() { return mH; } Loading
core/java/android/app/ContextImpl.java +108 −31 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package android.app; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.StrictMode.vmIncorrectContextUseEnabled; import static android.view.WindowManager.LayoutParams.WindowType; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.compat.annotation.UnsupportedAppUsage; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -87,6 +89,8 @@ import android.util.Slog; import android.view.Display; import android.view.DisplayAdjustments; import android.view.autofill.AutofillManager.AutofillClient; import android.window.WindowContext; import android.window.WindowTokenClient; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; Loading Loading @@ -2563,23 +2567,63 @@ class ContextImpl extends Context { @NonNull @Override public WindowContext createWindowContext(int type, @NonNull Bundle options) { public WindowContext createWindowContext(@WindowType int type, @Nullable Bundle options) { if (getDisplay() == null) { throw new UnsupportedOperationException("WindowContext can only be created from " + "other visual contexts, such as Activity or one created with " + "Context#createDisplayContext(Display)"); throw new UnsupportedOperationException("Please call this API with context associated" + " with a display instance, such as Activity or context created via" + " Context#createDisplayContext(Display), or try to invoke" + " Context#createWindowContext(Display, int, Bundle)"); } return new WindowContext(this, type, options); return createWindowContextInternal(getDisplay(), type, options); } @NonNull @Override public WindowContext createWindowContext(@NonNull Display display, int type, @NonNull Bundle options) { public WindowContext createWindowContext(@NonNull Display display, @WindowType int type, @Nullable Bundle options) { if (display == null) { throw new IllegalArgumentException("Display must not be null"); } return new WindowContext(this, display, type, options); return createWindowContextInternal(display, type, options); } /** * The internal implementation of {@link Context#createWindowContext(int, Bundle)} and * {@link Context#createWindowContext(Display, int, Bundle)}. * * @param display The {@link Display} instance to be associated with. * * @see Context#createWindowContext(Display, int, Bundle) * @see Context#createWindowContext(int, Bundle) */ private WindowContext createWindowContextInternal(@NonNull Display display, @WindowType int type, @Nullable Bundle options) { // Step 1. Create a WindowTokenClient to associate with the WindowContext's Resources // instance and it will be later used to receive configuration updates from the // server side. final WindowTokenClient windowTokenClient = new WindowTokenClient(); // Step 2. Create the base context of the window context, it will also create a Resources // associated with the WindowTokenClient and set the token to the base context. final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient, display); // Step 3. Create a WindowContext instance and set it as the outer context of the base // context to make the service obtained by #getSystemService(String) able to query // the WindowContext's WindowManager instead of the default one. final WindowContext windowContext = new WindowContext(windowContextBase, type, options); windowContextBase.setOuterContext(windowContext); // Step 4. Attach the WindowContext to the WindowTokenClient. In this way, when there's a // configuration update from the server side, the update will then apply to // WindowContext's resources. windowTokenClient.attachContext(windowContext); // Step 5. Register the window context's token to the server side to associate with a // window manager node. windowContext.registerWithServer(); return windowContext; } @NonNull Loading @@ -2588,40 +2632,65 @@ class ContextImpl extends Context { if (display == null) { throw new IllegalArgumentException("Display must not be null"); } final ContextImpl tokenContext = createBaseWindowContext(token, display); tokenContext.setResources(createWindowContextResources()); final ContextImpl tokenContext = createWindowContextBase(token, display); tokenContext.setResources(createWindowContextResources(tokenContext)); return tokenContext; } ContextImpl createBaseWindowContext(IBinder token, Display display) { ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mParams, /** * Creates the base {@link Context} for UI context to associate with a non-{@link Activity} * window. * * @param token The token to associate with {@link Resources} * @param display The {@link Display} to associate with. * * @see #createWindowContext(Display, int, Bundle) * @see #createTokenContext(IBinder, Display) */ @UiContext ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) { ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams, mSplitName, token, mUser, mFlags, mClassLoader, null); // Window contexts receive configurations directly from the server and as such do not // need to override their display in ResourcesManager. context.mForceDisplayOverrideInResources = false; context.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; if (display != null) { context.mDisplay = display; } return context; baseContext.mForceDisplayOverrideInResources = false; baseContext.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; baseContext.mDisplay = display; final Resources windowContextResources = createWindowContextResources(baseContext); baseContext.setResources(windowContextResources); return baseContext; } Resources createWindowContextResources() { final String resDir = mPackageInfo.getResDir(); final String[] splitResDirs = mPackageInfo.getSplitResDirs(); final String[] legacyOverlayDirs = mPackageInfo.getOverlayDirs(); final String[] overlayPaths = mPackageInfo.getOverlayPaths(); final String[] libDirs = mPackageInfo.getApplicationInfo().sharedLibraryFiles; final int displayId = getDisplayId(); /** * Creates the {@link Resources} to associate with the {@link WindowContext}'s token. * * When there's a {@link Configuration} update, this Resources instance will be updated to match * the new configuration. * * @see WindowTokenClient * @see #getWindowContextToken() */ private static Resources createWindowContextResources(@NonNull ContextImpl windowContextBase) { final LoadedApk packageInfo = windowContextBase.mPackageInfo; final ClassLoader classLoader = windowContextBase.mClassLoader; final IBinder token = windowContextBase.getWindowContextToken(); final String resDir = packageInfo.getResDir(); final String[] splitResDirs = packageInfo.getSplitResDirs(); final String[] legacyOverlayDirs = packageInfo.getOverlayDirs(); final String[] overlayPaths = packageInfo.getOverlayPaths(); final String[] libDirs = packageInfo.getApplicationInfo().sharedLibraryFiles; final int displayId = windowContextBase.getDisplayId(); final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY) ? mPackageInfo.getCompatibilityInfo() ? packageInfo.getCompatibilityInfo() : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; final List<ResourcesLoader> loaders = mResources.getLoaders(); final List<ResourcesLoader> loaders = windowContextBase.mResources.getLoaders(); return mResourcesManager.createBaseTokenResources(mToken, resDir, splitResDirs, legacyOverlayDirs, overlayPaths, libDirs, displayId, null /* overrideConfig */, compatInfo, mClassLoader, loaders); return windowContextBase.mResourcesManager.createBaseTokenResources(token, resDir, splitResDirs, legacyOverlayDirs, overlayPaths, libDirs, displayId, null /* overrideConfig */, compatInfo, classLoader, loaders); } @NonNull Loading Loading @@ -3114,6 +3183,14 @@ class ContextImpl extends Context { return result; } @Override public void destroy() { // The final clean-up is to release BroadcastReceiver registrations. It is called in // ActivityThread for Activity and Service. For the context, such as WindowContext, // without lifecycle concept, it should be called once the context is released. scheduleFinalCleanup(getClass().getName(), getOuterContext().getClass().getSimpleName()); } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- Loading
core/java/android/app/ResourcesManager.java +2 −3 Original line number Diff line number Diff line Loading @@ -39,13 +39,13 @@ import android.os.IBinder; import android.os.Process; import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.view.Display; import android.view.DisplayAdjustments; import android.window.WindowContext; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; Loading @@ -61,7 +61,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.WeakHashMap; Loading Loading @@ -168,7 +167,7 @@ public class ResourcesManager { /** * Class containing the base configuration override and set of resources associated with an * Activity or {@link WindowContext}. * {@link Activity} or a {@link WindowContext}. */ private static class ActivityResources { /** Loading
core/java/android/content/Context.java +12 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.view.WindowManager.LayoutParams.WindowType; import android.view.autofill.AutofillManager.AutofillClient; import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient; import android.view.textclassifier.TextClassificationManager; import android.window.WindowContext; import com.android.internal.compat.IPlatformCompat; import com.android.internal.compat.IPlatformCompatNative; Loading Loading @@ -6793,4 +6794,15 @@ public abstract class Context { public boolean isUiContext() { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Called when a {@link Context} is going to be released. * This method can be overridden to perform the final cleanups, such as release * {@link BroadcastReceiver} registrations. * * @see WindowContext#destroy() * * @hide */ public void destroy() { } }
core/java/android/view/IWindowManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -777,11 +777,11 @@ interface IWindowManager VerifiedDisplayHash verifyDisplayHash(in DisplayHash displayHash); /** * Registers a listener for a {@link android.app.WindowContext} to handle configuration changes * from the server side. * Registers a listener for a {@link android.window.WindowContext} to handle configuration * changes from the server side. * <p> * Note that this API should be invoked after calling * {@link android.app.WindowTokenClient#attachContext(WindowContext)} * {@link android.window.WindowTokenClient#attachContext(Context)} * </p> * * @param clientToken the window context's token Loading