diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/Activity.java | 23 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 242 | ||||
| -rw-r--r-- | core/java/android/app/ContextImpl.java | 7 | ||||
| -rw-r--r-- | core/java/android/app/IApplicationThread.aidl | 5 | ||||
| -rw-r--r-- | core/java/android/app/ResourcesManager.java | 19 | ||||
| -rw-r--r-- | core/java/android/content/Context.java | 5 | ||||
| -rw-r--r-- | core/java/android/content/ContextWrapper.java | 8 | ||||
| -rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/IWindow.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 28 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 11 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 34 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/BaseIWindow.java | 2 |
14 files changed, 292 insertions, 98 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 44494541c1a7..c56772ead97b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1980,6 +1980,29 @@ public class Activity extends ContextThemeWrapper } } + void dispatchMovedToDisplay(int displayId) { + updateDisplay(displayId); + onMovedToDisplay(displayId); + } + + /** + * Called by the system when the activity is moved from one display to another without + * recreation. This means that this activity is declared to handle all changes to configuration + * that happened when it was switched to another display, so it wasn't destroyed and created + * again. This call will be followed by {@link #onConfigurationChanged(Configuration)} if the + * applied configuration actually changed. + * + * <p>Use this callback to track changes to the displays if some activity functionality relies + * on an association with some display properties. + * + * @param displayId The id of the display to which activity was moved. + * + * @see #onConfigurationChanged(Configuration) + * @see View#onMovedToDisplay(int) + */ + public void onMovedToDisplay(int displayId) { + } + /** * Called by the system when the device configuration changes while your * activity is running. Note that this will <em>only</em> be called if diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 1f8e6db236ae..be70dcd204ca 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -16,6 +16,8 @@ package android.app; +import static android.view.Display.INVALID_DISPLAY; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.assist.AssistContent; @@ -1017,9 +1019,16 @@ public final class ActivityThread { @Override public void scheduleActivityConfigurationChanged( - IBinder token, Configuration overrideConfig, boolean reportToActivity) { + IBinder token, Configuration overrideConfig) { sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, - new ActivityConfigChangeData(token, overrideConfig), reportToActivity ? 1 : 0); + new ActivityConfigChangeData(token, overrideConfig)); + } + + @Override + public void scheduleActivityMovedToDisplay(IBinder token, int displayId, + Configuration overrideConfig) { + sendMessage(H.ACTIVITY_MOVED_TO_DISPLAY, + new ActivityConfigChangeData(token, overrideConfig), displayId); } @Override @@ -1521,6 +1530,7 @@ public final class ActivityThread { public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; public static final int ATTACH_AGENT = 155; public static final int APPLICATION_INFO_CHANGED = 156; + public static final int ACTIVITY_MOVED_TO_DISPLAY = 157; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1550,6 +1560,7 @@ public final class ActivityThread { case DUMP_SERVICE: return "DUMP_SERVICE"; case LOW_MEMORY: return "LOW_MEMORY"; case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; + case ACTIVITY_MOVED_TO_DISPLAY: return "ACTIVITY_MOVED_TO_DISPLAY"; case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; case PROFILER_CONTROL: return "PROFILER_CONTROL"; case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; @@ -1735,7 +1746,13 @@ public final class ActivityThread { case ACTIVITY_CONFIGURATION_CHANGED: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged"); handleActivityConfigurationChanged((ActivityConfigChangeData) msg.obj, - msg.arg1 == 1 ? REPORT_TO_ACTIVITY : !REPORT_TO_ACTIVITY); + INVALID_DISPLAY); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + break; + case ACTIVITY_MOVED_TO_DISPLAY: + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityMovedToDisplay"); + handleActivityConfigurationChanged((ActivityConfigChangeData) msg.obj, + msg.arg1 /* displayId */); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PROFILER_CONTROL: @@ -3775,7 +3792,7 @@ public final class ActivityThread { if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { if (r.newConfig != null) { - performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY); + performConfigurationChangedForActivity(r, r.newConfig); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig); r.newConfig = null; @@ -4129,7 +4146,7 @@ public final class ActivityThread { } } if (r.newConfig != null) { - performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY); + performConfigurationChangedForActivity(r, r.newConfig); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis " + r.activityInfo.name + " with new config " + r.activity.mCurrentConfig); @@ -4842,17 +4859,32 @@ public final class ActivityThread { * @param r ActivityClientRecord representing the Activity. * @param newBaseConfig The new configuration to use. This may be augmented with * {@link ActivityClientRecord#overrideConfig}. - * @param reportToActivity true if the change should be reported to the Activity's callback. */ private void performConfigurationChangedForActivity(ActivityClientRecord r, - Configuration newBaseConfig, - boolean reportToActivity) { + Configuration newBaseConfig) { + performConfigurationChangedForActivity(r, newBaseConfig, + r.activity.getDisplay().getDisplayId(), false /* movedToDifferentDisplay */); + } + + /** + * Updates the configuration for an Activity. The ActivityClientRecord's + * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for + * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering + * the updated Configuration. + * @param r ActivityClientRecord representing the Activity. + * @param newBaseConfig The new configuration to use. This may be augmented with + * {@link ActivityClientRecord#overrideConfig}. + * @param displayId The id of the display where the Activity currently resides. + * @param movedToDifferentDisplay Indicates if the activity was moved to different display. + */ + private void performConfigurationChangedForActivity(ActivityClientRecord r, + Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay) { r.tmpConfig.setTo(newBaseConfig); if (r.overrideConfig != null) { r.tmpConfig.updateFrom(r.overrideConfig); } - performConfigurationChanged(r.activity, r.token, r.tmpConfig, r.overrideConfig, - reportToActivity); + performActivityConfigurationChanged(r.activity, r.tmpConfig, r.overrideConfig, displayId, + movedToDifferentDisplay); freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig)); } @@ -4873,37 +4905,58 @@ public final class ActivityThread { } /** - * Decides whether to update an Activity's configuration and whether to tell the - * Activity/Component about it. + * Decides whether to update a component's configuration and whether to inform it. * @param cb The component callback to notify of configuration change. - * @param activityToken The Activity binder token for which this configuration change happened. - * If the change is global, this is null. + * @param newConfig The new configuration. + */ + private void performConfigurationChanged(ComponentCallbacks2 cb, Configuration newConfig) { + if (!REPORT_TO_ACTIVITY) { + return; + } + + // ContextThemeWrappers may override the configuration for that context. We must check and + // apply any overrides defined. + Configuration contextThemeWrapperOverrideConfig = null; + if (cb instanceof ContextThemeWrapper) { + final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb; + contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration(); + } + + // Apply the ContextThemeWrapper override if necessary. + // NOTE: Make sure the configurations are not modified, as they are treated as immutable + // in many places. + final Configuration configToReport = createNewConfigAndUpdateIfNotNull( + newConfig, contextThemeWrapperOverrideConfig); + cb.onConfigurationChanged(configToReport); + } + + /** + * Decides whether to update an Activity's configuration and whether to inform it. + * @param activity The activity to notify of configuration change. * @param newConfig The new configuration. * @param amOverrideConfig The override config that differentiates the Activity's configuration - * from the base global configuration. - * This is supplied by ActivityManager. - * @param reportToActivity Notify the Activity of the change. + * from the base global configuration. This is supplied by + * ActivityManager. + * @param displayId Id of the display where activity currently resides. + * @param movedToDifferentDisplay Indicates if the activity was moved to different display. */ - private void performConfigurationChanged(ComponentCallbacks2 cb, - IBinder activityToken, - Configuration newConfig, - Configuration amOverrideConfig, - boolean reportToActivity) { - // Only for Activity objects, check that they actually call up to their - // superclass implementation. ComponentCallbacks2 is an interface, so - // we check the runtime type and act accordingly. - Activity activity = (cb instanceof Activity) ? (Activity) cb : null; - if (activity != null) { - activity.mCalled = false; + private void performActivityConfigurationChanged(Activity activity, Configuration newConfig, + Configuration amOverrideConfig, int displayId, boolean movedToDifferentDisplay) { + if (activity == null) { + throw new IllegalArgumentException("No activity provided."); + } + final IBinder activityToken = activity.getActivityToken(); + if (activityToken == null) { + throw new IllegalArgumentException("Activity token not set. Is the activity attached?"); } boolean shouldChangeConfig = false; - if ((activity == null) || (activity.mCurrentConfig == null)) { + if (activity.mCurrentConfig == null) { shouldChangeConfig = true; } else { - // If the new config is the same as the config this Activity is already - // running with and the override config also didn't change, then don't - // bother calling onConfigurationChanged. + // If the new config is the same as the config this Activity is already running with and + // the override config also didn't change, then don't bother calling + // onConfigurationChanged. int diff = activity.mCurrentConfig.diff(newConfig); if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken, amOverrideConfig)) { @@ -4912,53 +4965,57 @@ public final class ActivityThread { // calling onConfigurationChanged as we're going to destroy it. if (!mUpdatingSystemConfig || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0 - || !reportToActivity) { + || !REPORT_TO_ACTIVITY) { shouldChangeConfig = true; } } } + if (!shouldChangeConfig && !movedToDifferentDisplay) { + // Nothing significant, don't proceed with updating and reporting. + return; + } + + // Propagate the configuration change to ResourcesManager and Activity. + + // ContextThemeWrappers may override the configuration for that context. We must check and + // apply any overrides defined. + Configuration contextThemeWrapperOverrideConfig = activity.getOverrideConfiguration(); + + // We only update an Activity's configuration if this is not a global configuration change. + // This must also be done before the callback, or else we violate the contract that the new + // resources are available in ComponentCallbacks2#onConfigurationChanged(Configuration). + // Also apply the ContextThemeWrapper override if necessary. + // NOTE: Make sure the configurations are not modified, as they are treated as immutable in + // many places. + final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull( + amOverrideConfig, contextThemeWrapperOverrideConfig); + mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig, + displayId, movedToDifferentDisplay); + + activity.mConfigChangeFlags = 0; + activity.mCurrentConfig = new Configuration(newConfig); + + if (!REPORT_TO_ACTIVITY) { + // Not configured to report to activity. + return; + } + + if (movedToDifferentDisplay) { + activity.dispatchMovedToDisplay(displayId); + } if (shouldChangeConfig) { - // Propagate the configuration change to the Activity and ResourcesManager. - - // ContextThemeWrappers may override the configuration for that context. - // We must check and apply any overrides defined. - Configuration contextThemeWrapperOverrideConfig = null; - if (cb instanceof ContextThemeWrapper) { - final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb; - contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration(); - } - - // We only update an Activity's configuration if this is not a global - // configuration change. This must also be done before the callback, - // or else we violate the contract that the new resources are available - // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}. - if (activityToken != null) { - // Apply the ContextThemeWrapper override if necessary. - // NOTE: Make sure the configurations are not modified, as they are treated - // as immutable in many places. - final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull( - amOverrideConfig, contextThemeWrapperOverrideConfig); - mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig); - } - - if (reportToActivity) { - // Apply the ContextThemeWrapper override if necessary. - // NOTE: Make sure the configurations are not modified, as they are treated - // as immutable in many places. - final Configuration configToReport = createNewConfigAndUpdateIfNotNull( - newConfig, contextThemeWrapperOverrideConfig); - cb.onConfigurationChanged(configToReport); - } + // Apply the ContextThemeWrapper override if necessary. + // NOTE: Make sure the configurations are not modified, as they are treated as immutable + // in many places. + final Configuration configToReport = createNewConfigAndUpdateIfNotNull( + newConfig, contextThemeWrapperOverrideConfig); - if (activity != null) { - if (reportToActivity && !activity.mCalled) { - throw new SuperNotCalledException( - "Activity " + activity.getLocalClassName() + - " did not call through to super.onConfigurationChanged()"); - } - activity.mConfigChangeFlags = 0; - activity.mCurrentConfig = new Configuration(newConfig); + activity.mCalled = false; + activity.onConfigurationChanged(configToReport); + if (!activity.mCalled) { + throw new SuperNotCalledException("Activity " + activity.getLocalClassName() + + " did not call through to super.onConfigurationChanged()"); } } } @@ -5036,9 +5093,9 @@ public final class ActivityThread { // config and avoid onConfigurationChanged if it hasn't changed. Activity a = (Activity) cb; performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()), - config, REPORT_TO_ACTIVITY); + config); } else { - performConfigurationChanged(cb, null, config, null, REPORT_TO_ACTIVITY); + performConfigurationChanged(cb, config); } } } @@ -5102,18 +5159,43 @@ public final class ActivityThread { } } - final void handleActivityConfigurationChanged(ActivityConfigChangeData data, - boolean reportToActivity) { + /** + * Handle new activity configuration and/or move to a different display. + * @param data Configuration update data. + * @param displayId Id of the display where activity was moved to, -1 if there was no move and + * value didn't change. + */ + private void handleActivityConfigurationChanged(ActivityConfigChangeData data, int displayId) { ActivityClientRecord r = mActivities.get(data.activityToken); + // Check input params. if (r == null || r.activity == null) { + if (DEBUG_CONFIGURATION) Slog.w(TAG, "Not found target activity to report to: " + r); return; } + final boolean movedToDifferentDisplay = displayId != INVALID_DISPLAY; + if (movedToDifferentDisplay) { + if (r.activity.getDisplay().getDisplayId() == displayId) { + throw new IllegalArgumentException("Activity is already on the target display: " + + displayId); + } + } - if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " - + r.activityInfo.name + ", with callback=" + reportToActivity); - + // Perform updates. r.overrideConfig = data.overrideConfig; - performConfigurationChangedForActivity(r, mCompatConfiguration, reportToActivity); + if (movedToDifferentDisplay) { + if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity moved to display, activity:" + + r.activityInfo.name + ", displayId=" + displayId + + ", config=" + data.overrideConfig); + + performConfigurationChangedForActivity(r, mCompatConfiguration, displayId, + true /* movedToDifferentDisplay */); + final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl(); + viewRoot.onMovedToDisplay(displayId); + } else { + if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: " + + r.activityInfo.name + ", config=" + data.overrideConfig); + performConfigurationChangedForActivity(r, mCompatConfiguration); + } mSomeActivitiesChanged = true; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 16989c060bc4..e154d2bdfa7b 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2072,6 +2072,13 @@ class ContextImpl extends Context { } @Override + public void updateDisplay(int displayId) { + final DisplayAdjustments displayAdjustments = mResources.getDisplayAdjustments(); + mDisplay = mResourcesManager.getAdjustedDisplay(displayId, + displayAdjustments); + } + + @Override public DisplayAdjustments getDisplayAdjustments(int displayId) { return mResources.getDisplayAdjustments(); } diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 7378e2b9f7d0..1735572a985f 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -100,8 +100,9 @@ oneway interface IApplicationThread { int resultCode, in String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState); void scheduleLowMemory(); - void scheduleActivityConfigurationChanged(IBinder token, in Configuration overrideConfig, - boolean reportToActivity); + void scheduleActivityConfigurationChanged(IBinder token, in Configuration overrideConfig); + void scheduleActivityMovedToDisplay(IBinder token, int displayId, + in Configuration overrideConfig); void scheduleRelaunchActivity(IBinder token, in List<ResultInfo> pendingResults, in List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, in Configuration config, in Configuration overrideConfig, boolean preserveWindow); diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 94a899037c56..55f7df36ad70 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -521,7 +521,8 @@ public class ResourcesManager { } // Update any existing Activity Resources references. - updateResourcesForActivity(activityToken, overrideConfig); + updateResourcesForActivity(activityToken, overrideConfig, displayId, + false /* movedToDifferentDisplay */); // Now request an actual Resources object. return getOrCreateResources(activityToken, key, classLoader); @@ -687,9 +688,12 @@ public class ResourcesManager { * still valid and will have the updated configuration. * @param activityToken The Activity token. * @param overrideConfig The configuration override to update. + * @param displayId Id of the display where activity currently resides. + * @param movedToDifferentDisplay Indicates if the activity was moved to different display. */ public void updateResourcesForActivity(@NonNull IBinder activityToken, - @Nullable Configuration overrideConfig) { + @Nullable Configuration overrideConfig, int displayId, + boolean movedToDifferentDisplay) { try { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#updateResourcesForActivity"); @@ -697,8 +701,9 @@ public class ResourcesManager { final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(activityToken); - if (Objects.equals(activityResources.overrideConfig, overrideConfig)) { - // They are the same, no work to do. + if (Objects.equals(activityResources.overrideConfig, overrideConfig) + && !movedToDifferentDisplay) { + // They are the same and no change of display id, no work to do. return; } @@ -721,7 +726,7 @@ public class ResourcesManager { + Configuration.resourceQualifierString(oldConfig) + " to newConfig=" + Configuration.resourceQualifierString( - activityResources.overrideConfig), + activityResources.overrideConfig) + " displayId=" + displayId, here); } @@ -765,12 +770,12 @@ public class ResourcesManager { // Create the new ResourcesKey with the rebased override config. final ResourcesKey newKey = new ResourcesKey(oldKey.mResDir, oldKey.mSplitResDirs, - oldKey.mOverlayDirs, oldKey.mLibDirs, oldKey.mDisplayId, + oldKey.mOverlayDirs, oldKey.mLibDirs, displayId, rebasedOverrideConfig, oldKey.mCompatInfo); if (DEBUG) { Slog.d(TAG, "rebasing ref=" + resources + " from oldKey=" + oldKey - + " to newKey=" + newKey); + + " to newKey=" + newKey + ", displayId=" + displayId); } ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 06f73033acd5..44e6ac59e68d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4429,6 +4429,11 @@ public abstract class Context { public abstract Display getDisplay(); /** + * @hide + */ + public abstract void updateDisplay(int displayId); + + /** * Indicates whether this Context is restricted. * * @return {@code true} if this Context is restricted, {@code false} otherwise. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 546bfc404d56..38cdbb4ef1b8 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -865,6 +865,14 @@ public class ContextWrapper extends Context { return mBase.getDisplay(); } + /** + * @hide + */ + @Override + public void updateDisplay(int displayId) { + mBase.updateDisplay(displayId); + } + @Override public Context createDeviceProtectedStorageContext() { return mBase.createDeviceProtectedStorageContext(); diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 64f02224ae37..483a49ba1697 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -289,7 +289,7 @@ public abstract class WallpaperService extends Service { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, Rect backDropRect, boolean forceLayout, - boolean alwaysConsumeNavBar) { + boolean alwaysConsumeNavBar, int displayId) { Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0, outsets); mCaller.sendMessage(msg); diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 10b1e1948a6a..14b2abec2adb 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -50,7 +50,7 @@ oneway interface IWindow { void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets, in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw, in Configuration newConfig, in Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar); + boolean alwaysConsumeNavBar, int displayId); void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); void dispatchGetNewSurface(); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 018be866cd8b..d2577d48c3d1 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -818,7 +818,7 @@ public class SurfaceView extends View { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, Rect backDropRect, boolean forceLayout, - boolean alwaysConsumeNavBar) { + boolean alwaysConsumeNavBar, int displayId) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width() diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ef5dc337290a..97f46fad603a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15869,6 +15869,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * @see #onMovedToDisplay(int) + */ + void dispatchMovedToDisplay(Display display) { + mAttachInfo.mDisplay = display; + mAttachInfo.mDisplayState = display.getState(); + onMovedToDisplay(display.getDisplayId()); + } + + /** + * Called by the system when the hosting activity is moved from one display to another without + * recreation. This means that the activity is declared to handle all changes to configuration + * that happened when it was switched to another display, so it wasn't destroyed and created + * again. This call will be followed by {@link #onConfigurationChanged(Configuration)} if the + * applied configuration actually changed. + * + * <p>Use this callback to track changes to the displays if some functionality relies on an + * association with some display properties. + * + * @param displayId The id of the display to which the view was moved. + * + * @see #onConfigurationChanged(Configuration) + */ + public void onMovedToDisplay(int displayId) { + } + + /** * Return true if the application tag in the AndroidManifest has set "supportRtl" to true */ private boolean hasRtlSupport() { @@ -23756,7 +23782,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final IBinder mWindowToken; - final Display mDisplay; + Display mDisplay; final Callbacks mRootCallbacks; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index fd3ff823065d..6c926c5487e9 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3239,6 +3239,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } + @Override + void dispatchMovedToDisplay(Display display) { + super.dispatchMovedToDisplay(display); + + final int count = mChildrenCount; + final View[] children = mChildren; + for (int i = 0; i < count; i++) { + children[i].dispatchMovedToDisplay(display); + } + } + /** @hide */ @Override public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 20d8a114863e..bbf840fe9f90 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1034,6 +1034,26 @@ public final class ViewRootImpl implements ViewParent, } }; + /** + * Notify about move to a different display. + * @param displayId The id of the display where this view root is moved to. + * + * @hide + */ + public void onMovedToDisplay(int displayId) { + if (mDisplay.getDisplayId() == displayId) { + return; + } + + // Get new instance of display based on current display adjustments. It may be updated later + // if moving between the displays also involved a configuration change. + final DisplayAdjustments displayAdjustments = mView.getResources().getDisplayAdjustments(); + mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId, displayAdjustments); + mAttachInfo.mDisplayState = mDisplay.getState(); + // Internal state updated, now notify the view hierarchy. + mView.dispatchMovedToDisplay(mDisplay); + } + void pokeDrawLockIfNeeded() { final int displayState = mAttachInfo.mDisplayState; if (mView != null && mAdded && mTraversalScheduled @@ -3523,7 +3543,8 @@ public final class ViewRootImpl implements ViewParent, && mPendingOutsets.equals(args.arg7) && mPendingBackDropFrame.equals(args.arg8) && args.arg4 == null - && args.argi1 == 0) { + && args.argi1 == 0 + && mDisplay.getDisplayId() == args.argi3) { break; } } // fall through... @@ -3531,6 +3552,10 @@ public final class ViewRootImpl implements ViewParent, if (mAdded) { SomeArgs args = (SomeArgs) msg.obj; + if (mDisplay.getDisplayId() != args.argi3) { + onMovedToDisplay(args.argi3); + } + Configuration config = (Configuration) args.arg4; if (config != null) { updateConfiguration(config, false); @@ -6138,7 +6163,7 @@ public final class ViewRootImpl implements ViewParent, public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar) { + boolean alwaysConsumeNavBar, int displayId) { if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -6176,6 +6201,7 @@ public final class ViewRootImpl implements ViewParent, args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame; args.argi1 = forceLayout ? 1 : 0; args.argi2 = alwaysConsumeNavBar ? 1 : 0; + args.argi3 = displayId; msg.obj = args; mHandler.sendMessage(msg); } @@ -7188,12 +7214,12 @@ public final class ViewRootImpl implements ViewParent, public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeNavBar) { + boolean alwaysConsumeNavBar, int displayId) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame, - forceLayout, alwaysConsumeNavBar); + forceLayout, alwaysConsumeNavBar, displayId); } } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index dd91d2f2cfaf..ce51dc4ead9e 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -40,7 +40,7 @@ public class BaseIWindow extends IWindow.Stub { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig, - Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar) { + Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId) { if (reportDraw) { try { mSession.finishDrawing(this); |
