summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java23
-rw-r--r--core/java/android/app/ActivityThread.java242
-rw-r--r--core/java/android/app/ContextImpl.java7
-rw-r--r--core/java/android/app/IApplicationThread.aidl5
-rw-r--r--core/java/android/app/ResourcesManager.java19
-rw-r--r--core/java/android/content/Context.java5
-rw-r--r--core/java/android/content/ContextWrapper.java8
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java2
-rw-r--r--core/java/android/view/IWindow.aidl2
-rw-r--r--core/java/android/view/SurfaceView.java2
-rw-r--r--core/java/android/view/View.java28
-rw-r--r--core/java/android/view/ViewGroup.java11
-rw-r--r--core/java/android/view/ViewRootImpl.java34
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java2
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);