Loading api/current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -9965,6 +9965,7 @@ package android.content { method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display); method @NonNull public android.content.Context createFeatureContext(@Nullable String); method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public android.content.Context createWindowContext(int); method public abstract String[] databaseList(); method public abstract boolean deleteDatabase(String); method public abstract boolean deleteFile(String); Loading @@ -9989,6 +9990,7 @@ package android.content { method public abstract java.io.File getDataDir(); method public abstract java.io.File getDatabasePath(String); method public abstract java.io.File getDir(String, int); method @Nullable public android.view.Display getDisplay(); method @Nullable public final android.graphics.drawable.Drawable getDrawable(@DrawableRes int); method @Nullable public abstract java.io.File getExternalCacheDir(); method public abstract java.io.File[] getExternalCacheDirs(); Loading Loading @@ -54608,7 +54610,7 @@ package android.view { } public interface WindowManager extends android.view.ViewManager { method public android.view.Display getDefaultDisplay(); method @Deprecated public android.view.Display getDefaultDisplay(); method public void removeViewImmediate(android.view.View); } api/test-current.txt +0 −2 Original line number Diff line number Diff line Loading @@ -758,7 +758,6 @@ package android.content { method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public java.io.File getCrateDir(@NonNull String); method public abstract android.view.Display getDisplay(); method public abstract int getDisplayId(); method public android.os.UserHandle getUser(); method public int getUserId(); Loading @@ -779,7 +778,6 @@ package android.content { } public class ContextWrapper extends android.content.Context { method public android.view.Display getDisplay(); method public int getDisplayId(); } Loading core/java/android/app/ContextImpl.java +56 −22 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package android.app; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -201,7 +200,7 @@ class ContextImpl extends Context { @UnsupportedAppUsage private @Nullable ClassLoader mClassLoader; private final @Nullable IBinder mActivityToken; private final @Nullable IBinder mToken; private final @NonNull UserHandle mUser; Loading @@ -219,7 +218,7 @@ class ContextImpl extends Context { private final @NonNull ResourcesManager mResourcesManager; @UnsupportedAppUsage private @NonNull Resources mResources; private @Nullable Display mDisplay; // may be null if default display private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int mFlags; Loading @@ -244,6 +243,9 @@ class ContextImpl extends Context { private final Object mSync = new Object(); private boolean mIsSystemOrSystemUiContext; private boolean mIsUiContext; @GuardedBy("mSync") private File mDatabasesDir; @GuardedBy("mSync") Loading Loading @@ -1883,6 +1885,9 @@ class ContextImpl extends Context { @Override public Object getSystemService(String name) { if (isUiComponent(name) && !isUiContext()) { Log.w(TAG, name + " should be accessed from Activity or other visual Context"); } return SystemServiceRegistry.getSystemService(this, name); } Loading @@ -1891,6 +1896,15 @@ class ContextImpl extends Context { return SystemServiceRegistry.getSystemServiceName(serviceClass); } boolean isUiContext() { return mIsSystemOrSystemUiContext || mIsUiContext; } private static boolean isUiComponent(String name) { return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name) || WALLPAPER_SERVICE.equals(name); } @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { Loading Loading @@ -2229,12 +2243,12 @@ class ContextImpl extends Context { LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mActivityToken, ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mToken, new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null); final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, c.setResources(createResources(mToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; Loading @@ -2258,18 +2272,18 @@ class ContextImpl extends Context { // The system resources are loaded in every application, so we can safely copy // the context without reloading Resources. return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null, mActivityToken, user, flags, null, null); mToken, user, flags, null, null); } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null, mActivityToken, user, flags, null, null); mToken, user, flags, null, null); final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, c.setResources(createResources(mToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; Loading Loading @@ -2301,12 +2315,12 @@ class ContextImpl extends Context { final String[] paths = mPackageInfo.getSplitPaths(splitName); final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, splitName, mActivityToken, mUser, mFlags, classLoader, null); mFeatureId, splitName, mToken, mUser, mFlags, classLoader, null); final int displayId = getDisplayId(); context.setResources(ResourcesManager.getInstance().getResources( mActivityToken, mToken, mPackageInfo.getResDir(), paths, mPackageInfo.getOverlayDirs(), Loading @@ -2325,10 +2339,10 @@ class ContextImpl extends Context { } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mSplitName, mToken, mUser, mFlags, mClassLoader, null); final int displayId = getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId, overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo())); return context; } Loading @@ -2340,19 +2354,36 @@ class ContextImpl extends Context { } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mSplitName, mToken, mUser, mFlags, mClassLoader, null); final int displayId = display.getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); context.mDisplay = display; return context; } @Override public @NonNull WindowContext createWindowContext(int type) { 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)"); } return new WindowContext(this, null /* token */, type); } ContextImpl createBaseWindowContext(IBinder token) { ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, token, mUser, mFlags, mClassLoader, null); context.mIsUiContext = true; return context; } @Override public @NonNull Context createFeatureContext(@Nullable String featureId) { return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mToken, mUser, mFlags, mClassLoader, null); } @Override Loading @@ -2360,7 +2391,7 @@ class ContextImpl extends Context { final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) | Context.CONTEXT_DEVICE_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, flags, mClassLoader, null); mToken, mUser, flags, mClassLoader, null); } @Override Loading @@ -2368,7 +2399,7 @@ class ContextImpl extends Context { final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE) | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, flags, mClassLoader, null); mToken, mUser, flags, mClassLoader, null); } @Override Loading @@ -2394,8 +2425,6 @@ class ContextImpl extends Context { return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0; } @UnsupportedAppUsage @TestApi @Override public Display getDisplay() { if (mDisplay == null) { Loading @@ -2408,7 +2437,8 @@ class ContextImpl extends Context { @Override public int getDisplayId() { return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; final Display display = getDisplay(); return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY; } @Override Loading Loading @@ -2518,6 +2548,7 @@ class ContextImpl extends Context { context.setResources(packageInfo.getResources()); context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(), context.mResourcesManager.getDisplayMetrics()); context.mIsSystemOrSystemUiContext = true; return context; } Loading @@ -2535,6 +2566,7 @@ class ContextImpl extends Context { context.setResources(createResources(null, packageInfo, null, displayId, null, packageInfo.getCompatibilityInfo())); context.updateDisplay(displayId); context.mIsSystemOrSystemUiContext = true; return context; } Loading Loading @@ -2584,6 +2616,7 @@ class ContextImpl extends Context { ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, activityInfo.splitName, activityToken, null, 0, classLoader, null); context.mIsUiContext = true; // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; Loading Loading @@ -2629,7 +2662,7 @@ class ContextImpl extends Context { } mMainThread = mainThread; mActivityToken = activityToken; mToken = activityToken; mFlags = flags; if (user == null) { Loading @@ -2649,6 +2682,7 @@ class ContextImpl extends Context { opPackageName = container.mOpPackageName; setResources(container.mResources); mDisplay = container.mDisplay; mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext; } else { mBasePackageName = packageInfo.mPackageName; ApplicationInfo ainfo = packageInfo.getApplicationInfo(); Loading Loading @@ -2710,7 +2744,7 @@ class ContextImpl extends Context { @Override @UnsupportedAppUsage public IBinder getActivityToken() { return mActivityToken; return mToken; } private void checkMode(int mode) { Loading core/java/android/app/WindowContext.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * 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 android.app; import android.annotation.NonNull; import android.content.Context; import android.content.ContextWrapper; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerImpl; /** * {@link WindowContext} is a context for non-activity windows such as * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} windows or system * windows. Its resources and configuration are adjusted to the area of the display that will be * used when a new window is added via {@link android.view.WindowManager.addView}. * * @see Context#createWindowContext(int) * @hide */ // TODO(b/128338354): Handle config/display changes from server side. public class WindowContext extends ContextWrapper { private final WindowManagerImpl mWindowManager; private final IWindowManager mWms; private final IBinder mToken; private final int mDisplayId; private boolean mOwnsToken; /** * Default constructor. Can either accept an existing token or generate one and registers it * with the server if necessary. * * @param base Base {@link Context} for this new instance. * @param token A valid {@link com.android.server.wm.WindowToken}. Pass {@code null} to generate * one. * @param type Window type to be used with this context. * @hide */ public WindowContext(Context base, IBinder token, int type) { super(null /* base */); mWms = WindowManagerGlobal.getWindowManagerService(); if (token != null && !isWindowToken(token)) { throw new IllegalArgumentException("Token must be registered to server."); } final ContextImpl contextImpl = createBaseWindowContext(base, token); attachBaseContext(contextImpl); contextImpl.setOuterContext(this); mToken = token != null ? token : new Binder(); mDisplayId = getDisplayId(); mWindowManager = new WindowManagerImpl(this); mWindowManager.setDefaultToken(mToken); // TODO(b/128338354): Obtain the correct config from WM and adjust resources. if (token != null) { mOwnsToken = false; return; } try { mWms.addWindowContextToken(mToken, type, mDisplayId, getPackageName()); // TODO(window-context): remove token with a DeathObserver } catch (RemoteException e) { mOwnsToken = false; throw e.rethrowFromSystemServer(); } mOwnsToken = true; } /** Check if the passed window token is registered with the server. */ private boolean isWindowToken(@NonNull IBinder token) { try { return mWms.isWindowToken(token); } catch (RemoteException e) { e.rethrowFromSystemServer(); } return false; } private static ContextImpl createBaseWindowContext(Context outer, IBinder token) { final ContextImpl contextImpl = ContextImpl.getImpl(outer); return contextImpl.createBaseWindowContext(token); } @Override public Object getSystemService(String name) { if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } return super.getSystemService(name); } @Override protected void finalize() throws Throwable { if (mOwnsToken) { try { mWms.removeWindowToken(mToken, mDisplayId); mOwnsToken = false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } super.finalize(); } } core/java/android/content/Context.java +67 −5 Original line number Diff line number Diff line Loading @@ -5729,6 +5729,63 @@ public abstract class Context { */ public abstract Context createDisplayContext(@NonNull Display display); /** * Creates a Context for a non-activity window. * * <p> * A window context is a context that can be used to add non-activity windows, such as * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}. A window context * must be created from a context that has an associated {@link Display}, such as * {@link android.app.Activity Activity} or a context created with * {@link #createDisplayContext(Display)}. * * <p> * The window context is created with the appropriate {@link Configuration} for the area of the * display that the windows created with it can occupy; it must be used when * {@link android.view.LayoutInflater inflating} views, such that they can be inflated with * proper {@link Resources}. * * Below is a sample code to <b>add an application overlay window on the primary display:<b/> * <pre class="prettyprint"> * ... * final DisplayManager dm = anyContext.getSystemService(DisplayManager.class); * final Display primaryDisplay = dm.getDisplay(DEFAULT_DISPLAY); * final Context windowContext = anyContext.createDisplayContext(primaryDisplay) * .createWindowContext(TYPE_APPLICATION_OVERLAY); * final View overlayView = Inflater.from(windowContext).inflate(someLayoutXml, null); * * // WindowManager.LayoutParams initialization * ... * mParams.type = TYPE_APPLICATION_OVERLAY; * ... * * mWindowContext.getSystemService(WindowManager.class).addView(overlayView, mParams); * </pre> * * <p> * This context's configuration and resources are adjusted to a display area where the windows * with provided type will be added. <b>Note that all windows associated with the same context * will have an affinity and can only be moved together between different displays or areas on a * display.</b> If there is a need to add different window types, or non-associated windows, * separate Contexts should be used. * </p> * * @param type Window type in {@link WindowManager.LayoutParams} * @return A {@link Context} that can be used to create windows. * @throws UnsupportedOperationException if this is called on a non-UI context, such as * {@link android.app.Application Application} or {@link android.app.Service Service}. * * @see #getSystemService(String) * @see #getSystemService(Class) * @see #WINDOW_SERVICE * @see #LAYOUT_INFLATER_SERVICE * @see #WALLPAPER_SERVICE * @throws IllegalArgumentException if token is invalid */ public @NonNull Context createWindowContext(int type) { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Return a new Context object for the current Context but for a different feature in the app. * Features can be used by complex apps to separate logical parts. Loading Loading @@ -5813,17 +5870,22 @@ public abstract class Context { public abstract DisplayAdjustments getDisplayAdjustments(int displayId); /** * Get the display this context is associated with. Applications should use this method with * {@link android.app.Activity} or a context associated with a {@link Display} via * {@link #createDisplayContext(Display)} to get a display object associated with a Context, or * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id. * @return Returns the {@link Display} object this context is associated with. * @hide */ @UnsupportedAppUsage @TestApi public abstract Display getDisplay(); @Nullable public Display getDisplay() { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Gets the display ID. * Gets the ID of the display this context is associated with. * * @return display ID associated with this {@link Context}. * @see #getDisplay() * @hide */ @TestApi Loading Loading
api/current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -9965,6 +9965,7 @@ package android.content { method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display); method @NonNull public android.content.Context createFeatureContext(@Nullable String); method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public android.content.Context createWindowContext(int); method public abstract String[] databaseList(); method public abstract boolean deleteDatabase(String); method public abstract boolean deleteFile(String); Loading @@ -9989,6 +9990,7 @@ package android.content { method public abstract java.io.File getDataDir(); method public abstract java.io.File getDatabasePath(String); method public abstract java.io.File getDir(String, int); method @Nullable public android.view.Display getDisplay(); method @Nullable public final android.graphics.drawable.Drawable getDrawable(@DrawableRes int); method @Nullable public abstract java.io.File getExternalCacheDir(); method public abstract java.io.File[] getExternalCacheDirs(); Loading Loading @@ -54608,7 +54610,7 @@ package android.view { } public interface WindowManager extends android.view.ViewManager { method public android.view.Display getDefaultDisplay(); method @Deprecated public android.view.Display getDefaultDisplay(); method public void removeViewImmediate(android.view.View); }
api/test-current.txt +0 −2 Original line number Diff line number Diff line Loading @@ -758,7 +758,6 @@ package android.content { method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public java.io.File getCrateDir(@NonNull String); method public abstract android.view.Display getDisplay(); method public abstract int getDisplayId(); method public android.os.UserHandle getUser(); method public int getUserId(); Loading @@ -779,7 +778,6 @@ package android.content { } public class ContextWrapper extends android.content.Context { method public android.view.Display getDisplay(); method public int getDisplayId(); } Loading
core/java/android/app/ContextImpl.java +56 −22 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package android.app; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.AutofillOptions; import android.content.BroadcastReceiver; Loading Loading @@ -201,7 +200,7 @@ class ContextImpl extends Context { @UnsupportedAppUsage private @Nullable ClassLoader mClassLoader; private final @Nullable IBinder mActivityToken; private final @Nullable IBinder mToken; private final @NonNull UserHandle mUser; Loading @@ -219,7 +218,7 @@ class ContextImpl extends Context { private final @NonNull ResourcesManager mResourcesManager; @UnsupportedAppUsage private @NonNull Resources mResources; private @Nullable Display mDisplay; // may be null if default display private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int mFlags; Loading @@ -244,6 +243,9 @@ class ContextImpl extends Context { private final Object mSync = new Object(); private boolean mIsSystemOrSystemUiContext; private boolean mIsUiContext; @GuardedBy("mSync") private File mDatabasesDir; @GuardedBy("mSync") Loading Loading @@ -1883,6 +1885,9 @@ class ContextImpl extends Context { @Override public Object getSystemService(String name) { if (isUiComponent(name) && !isUiContext()) { Log.w(TAG, name + " should be accessed from Activity or other visual Context"); } return SystemServiceRegistry.getSystemService(this, name); } Loading @@ -1891,6 +1896,15 @@ class ContextImpl extends Context { return SystemServiceRegistry.getSystemServiceName(serviceClass); } boolean isUiContext() { return mIsSystemOrSystemUiContext || mIsUiContext; } private static boolean isUiComponent(String name) { return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name) || WALLPAPER_SERVICE.equals(name); } @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { Loading Loading @@ -2229,12 +2243,12 @@ class ContextImpl extends Context { LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mActivityToken, ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mToken, new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null); final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, c.setResources(createResources(mToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; Loading @@ -2258,18 +2272,18 @@ class ContextImpl extends Context { // The system resources are loaded in every application, so we can safely copy // the context without reloading Resources. return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null, mActivityToken, user, flags, null, null); mToken, user, flags, null, null); } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null, mActivityToken, user, flags, null, null); mToken, user, flags, null, null); final int displayId = getDisplayId(); c.setResources(createResources(mActivityToken, pi, null, displayId, null, c.setResources(createResources(mToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; Loading Loading @@ -2301,12 +2315,12 @@ class ContextImpl extends Context { final String[] paths = mPackageInfo.getSplitPaths(splitName); final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, splitName, mActivityToken, mUser, mFlags, classLoader, null); mFeatureId, splitName, mToken, mUser, mFlags, classLoader, null); final int displayId = getDisplayId(); context.setResources(ResourcesManager.getInstance().getResources( mActivityToken, mToken, mPackageInfo.getResDir(), paths, mPackageInfo.getOverlayDirs(), Loading @@ -2325,10 +2339,10 @@ class ContextImpl extends Context { } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mSplitName, mToken, mUser, mFlags, mClassLoader, null); final int displayId = getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId, overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo())); return context; } Loading @@ -2340,19 +2354,36 @@ class ContextImpl extends Context { } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mSplitName, mToken, mUser, mFlags, mClassLoader, null); final int displayId = display.getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); context.mDisplay = display; return context; } @Override public @NonNull WindowContext createWindowContext(int type) { 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)"); } return new WindowContext(this, null /* token */, type); } ContextImpl createBaseWindowContext(IBinder token) { ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, token, mUser, mFlags, mClassLoader, null); context.mIsUiContext = true; return context; } @Override public @NonNull Context createFeatureContext(@Nullable String featureId) { return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null); mToken, mUser, mFlags, mClassLoader, null); } @Override Loading @@ -2360,7 +2391,7 @@ class ContextImpl extends Context { final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) | Context.CONTEXT_DEVICE_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, flags, mClassLoader, null); mToken, mUser, flags, mClassLoader, null); } @Override Loading @@ -2368,7 +2399,7 @@ class ContextImpl extends Context { final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE) | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName, mActivityToken, mUser, flags, mClassLoader, null); mToken, mUser, flags, mClassLoader, null); } @Override Loading @@ -2394,8 +2425,6 @@ class ContextImpl extends Context { return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0; } @UnsupportedAppUsage @TestApi @Override public Display getDisplay() { if (mDisplay == null) { Loading @@ -2408,7 +2437,8 @@ class ContextImpl extends Context { @Override public int getDisplayId() { return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; final Display display = getDisplay(); return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY; } @Override Loading Loading @@ -2518,6 +2548,7 @@ class ContextImpl extends Context { context.setResources(packageInfo.getResources()); context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(), context.mResourcesManager.getDisplayMetrics()); context.mIsSystemOrSystemUiContext = true; return context; } Loading @@ -2535,6 +2566,7 @@ class ContextImpl extends Context { context.setResources(createResources(null, packageInfo, null, displayId, null, packageInfo.getCompatibilityInfo())); context.updateDisplay(displayId); context.mIsSystemOrSystemUiContext = true; return context; } Loading Loading @@ -2584,6 +2616,7 @@ class ContextImpl extends Context { ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, activityInfo.splitName, activityToken, null, 0, classLoader, null); context.mIsUiContext = true; // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; Loading Loading @@ -2629,7 +2662,7 @@ class ContextImpl extends Context { } mMainThread = mainThread; mActivityToken = activityToken; mToken = activityToken; mFlags = flags; if (user == null) { Loading @@ -2649,6 +2682,7 @@ class ContextImpl extends Context { opPackageName = container.mOpPackageName; setResources(container.mResources); mDisplay = container.mDisplay; mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext; } else { mBasePackageName = packageInfo.mPackageName; ApplicationInfo ainfo = packageInfo.getApplicationInfo(); Loading Loading @@ -2710,7 +2744,7 @@ class ContextImpl extends Context { @Override @UnsupportedAppUsage public IBinder getActivityToken() { return mActivityToken; return mToken; } private void checkMode(int mode) { Loading
core/java/android/app/WindowContext.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * 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 android.app; import android.annotation.NonNull; import android.content.Context; import android.content.ContextWrapper; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerImpl; /** * {@link WindowContext} is a context for non-activity windows such as * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} windows or system * windows. Its resources and configuration are adjusted to the area of the display that will be * used when a new window is added via {@link android.view.WindowManager.addView}. * * @see Context#createWindowContext(int) * @hide */ // TODO(b/128338354): Handle config/display changes from server side. public class WindowContext extends ContextWrapper { private final WindowManagerImpl mWindowManager; private final IWindowManager mWms; private final IBinder mToken; private final int mDisplayId; private boolean mOwnsToken; /** * Default constructor. Can either accept an existing token or generate one and registers it * with the server if necessary. * * @param base Base {@link Context} for this new instance. * @param token A valid {@link com.android.server.wm.WindowToken}. Pass {@code null} to generate * one. * @param type Window type to be used with this context. * @hide */ public WindowContext(Context base, IBinder token, int type) { super(null /* base */); mWms = WindowManagerGlobal.getWindowManagerService(); if (token != null && !isWindowToken(token)) { throw new IllegalArgumentException("Token must be registered to server."); } final ContextImpl contextImpl = createBaseWindowContext(base, token); attachBaseContext(contextImpl); contextImpl.setOuterContext(this); mToken = token != null ? token : new Binder(); mDisplayId = getDisplayId(); mWindowManager = new WindowManagerImpl(this); mWindowManager.setDefaultToken(mToken); // TODO(b/128338354): Obtain the correct config from WM and adjust resources. if (token != null) { mOwnsToken = false; return; } try { mWms.addWindowContextToken(mToken, type, mDisplayId, getPackageName()); // TODO(window-context): remove token with a DeathObserver } catch (RemoteException e) { mOwnsToken = false; throw e.rethrowFromSystemServer(); } mOwnsToken = true; } /** Check if the passed window token is registered with the server. */ private boolean isWindowToken(@NonNull IBinder token) { try { return mWms.isWindowToken(token); } catch (RemoteException e) { e.rethrowFromSystemServer(); } return false; } private static ContextImpl createBaseWindowContext(Context outer, IBinder token) { final ContextImpl contextImpl = ContextImpl.getImpl(outer); return contextImpl.createBaseWindowContext(token); } @Override public Object getSystemService(String name) { if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } return super.getSystemService(name); } @Override protected void finalize() throws Throwable { if (mOwnsToken) { try { mWms.removeWindowToken(mToken, mDisplayId); mOwnsToken = false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } super.finalize(); } }
core/java/android/content/Context.java +67 −5 Original line number Diff line number Diff line Loading @@ -5729,6 +5729,63 @@ public abstract class Context { */ public abstract Context createDisplayContext(@NonNull Display display); /** * Creates a Context for a non-activity window. * * <p> * A window context is a context that can be used to add non-activity windows, such as * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}. A window context * must be created from a context that has an associated {@link Display}, such as * {@link android.app.Activity Activity} or a context created with * {@link #createDisplayContext(Display)}. * * <p> * The window context is created with the appropriate {@link Configuration} for the area of the * display that the windows created with it can occupy; it must be used when * {@link android.view.LayoutInflater inflating} views, such that they can be inflated with * proper {@link Resources}. * * Below is a sample code to <b>add an application overlay window on the primary display:<b/> * <pre class="prettyprint"> * ... * final DisplayManager dm = anyContext.getSystemService(DisplayManager.class); * final Display primaryDisplay = dm.getDisplay(DEFAULT_DISPLAY); * final Context windowContext = anyContext.createDisplayContext(primaryDisplay) * .createWindowContext(TYPE_APPLICATION_OVERLAY); * final View overlayView = Inflater.from(windowContext).inflate(someLayoutXml, null); * * // WindowManager.LayoutParams initialization * ... * mParams.type = TYPE_APPLICATION_OVERLAY; * ... * * mWindowContext.getSystemService(WindowManager.class).addView(overlayView, mParams); * </pre> * * <p> * This context's configuration and resources are adjusted to a display area where the windows * with provided type will be added. <b>Note that all windows associated with the same context * will have an affinity and can only be moved together between different displays or areas on a * display.</b> If there is a need to add different window types, or non-associated windows, * separate Contexts should be used. * </p> * * @param type Window type in {@link WindowManager.LayoutParams} * @return A {@link Context} that can be used to create windows. * @throws UnsupportedOperationException if this is called on a non-UI context, such as * {@link android.app.Application Application} or {@link android.app.Service Service}. * * @see #getSystemService(String) * @see #getSystemService(Class) * @see #WINDOW_SERVICE * @see #LAYOUT_INFLATER_SERVICE * @see #WALLPAPER_SERVICE * @throws IllegalArgumentException if token is invalid */ public @NonNull Context createWindowContext(int type) { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Return a new Context object for the current Context but for a different feature in the app. * Features can be used by complex apps to separate logical parts. Loading Loading @@ -5813,17 +5870,22 @@ public abstract class Context { public abstract DisplayAdjustments getDisplayAdjustments(int displayId); /** * Get the display this context is associated with. Applications should use this method with * {@link android.app.Activity} or a context associated with a {@link Display} via * {@link #createDisplayContext(Display)} to get a display object associated with a Context, or * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id. * @return Returns the {@link Display} object this context is associated with. * @hide */ @UnsupportedAppUsage @TestApi public abstract Display getDisplay(); @Nullable public Display getDisplay() { throw new RuntimeException("Not implemented. Must override in a subclass."); } /** * Gets the display ID. * Gets the ID of the display this context is associated with. * * @return display ID associated with this {@link Context}. * @see #getDisplay() * @hide */ @TestApi Loading