summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorAndrii Kulian <akulian@google.com>2017-03-17 15:39:32 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-03-17 15:39:37 +0000
commitc1b59ed73eeea40c70cc81e2ab486cd54d94ed5d (patch)
tree30a6bfe3b09b1d6eaa552c143d5f7ff690c79b5f /core/java
parentedd694e4bf584d933028c9ef02199c36a9729690 (diff)
parent446079600ece83b22cb91865bcbeb694292b0108 (diff)
Merge "Separate global and override config sent to client"
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ActivityThread.java66
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java13
-rw-r--r--core/java/android/util/MergedConfiguration.aidl19
-rw-r--r--core/java/android/util/MergedConfiguration.java122
-rw-r--r--core/java/android/view/AccessibilityIterators.java12
-rw-r--r--core/java/android/view/IWindow.aidl6
-rw-r--r--core/java/android/view/IWindowSession.aidl14
-rw-r--r--core/java/android/view/ViewRootImpl.java215
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java7
9 files changed, 361 insertions, 113 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 39b9d66a9623..6b53cd841dff 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -337,6 +337,8 @@ public final class ActivityThread {
Configuration overrideConfig;
// Used for consolidating configs before sending on to Activity.
private Configuration tmpConfig = new Configuration();
+ // Callback used for updating activity override config.
+ ViewRootImpl.ActivityConfigCallback configCallback;
ActivityClientRecord nextIdle;
ProfilerInfo profilerInfo;
@@ -372,6 +374,14 @@ public final class ActivityThread {
stopped = false;
hideForNow = false;
nextIdle = null;
+ configCallback = (Configuration overrideConfig, int newDisplayId) -> {
+ if (activity == null) {
+ throw new IllegalStateException(
+ "Received config update for non-existing activity");
+ }
+ activity.mMainThread.handleActivityConfigurationChanged(
+ new ActivityConfigChangeData(token, overrideConfig), newDisplayId);
+ };
}
public boolean isPreHoneycomb() {
@@ -3681,6 +3691,12 @@ public final class ActivityThread {
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
+ final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl();
+ if (viewRoot != null) {
+ // TODO: Figure out the best place to set the callback.
+ // This looks like a place where decor view is already initialized.
+ viewRoot.setActivityConfigCallback(r.configCallback);
+ }
}
if (!r.onlyLocalRequest) {
@@ -5029,7 +5045,7 @@ public final class ActivityThread {
* @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) {
+ void handleActivityConfigurationChanged(ActivityConfigChangeData data, int displayId) {
ActivityClientRecord r = mActivities.get(data.activityToken);
// Check input params.
if (r == null || r.activity == null) {
@@ -5046,6 +5062,7 @@ public final class ActivityThread {
// Perform updates.
r.overrideConfig = data.overrideConfig;
+ final ViewRootImpl viewRoot = r.activity.mDecor.getViewRootImpl();
if (movedToDifferentDisplay) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity moved to display, activity:"
+ r.activityInfo.name + ", displayId=" + displayId
@@ -5053,13 +5070,15 @@ public final class ActivityThread {
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);
}
+ // Notify the ViewRootImpl instance about configuration changes. It may have initiated this
+ // update to make sure that resources are updated before updating itself.
+ viewRoot.updateConfiguration();
mSomeActivitiesChanged = true;
}
@@ -6295,35 +6314,26 @@ public final class ActivityThread {
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
- ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- synchronized (mResourcesManager) {
- // We need to apply this change to the resources
- // immediately, because upon returning the view
- // hierarchy will be informed about it.
- if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
- updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
- mResourcesManager.getConfiguration().getLocales());
-
- // This actually changed the resources! Tell
- // everyone about it.
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(newConfig)) {
- mPendingConfiguration = newConfig;
-
- sendMessage(H.CONFIGURATION_CHANGED, newConfig);
- }
+ ViewRootImpl.ConfigChangedCallback configChangedCallback
+ = (Configuration globalConfig) -> {
+ synchronized (mResourcesManager) {
+ // We need to apply this change to the resources immediately, because upon returning
+ // the view hierarchy will be informed about it.
+ if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
+ null /* compat */)) {
+ updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
+ mResourcesManager.getConfiguration().getLocales());
+
+ // This actually changed the resources! Tell everyone about it.
+ if (mPendingConfiguration == null
+ || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
+ mPendingConfiguration = globalConfig;
+ sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
- @Override
- public void onLowMemory() {
- }
- @Override
- public void onTrimMemory(int level) {
- }
- });
+ };
+ ViewRootImpl.addConfigCallback(configChangedCallback);
}
public static ActivityThread systemMain() {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 483a49ba1697..6bbb0ff9861b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -18,11 +18,11 @@ package android.service.wallpaper;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.util.MergedConfiguration;
import android.view.WindowInsets;
import com.android.internal.R;
import com.android.internal.os.HandlerCaller;
-import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.view.BaseIWindow;
import com.android.internal.view.BaseSurfaceHolder;
@@ -32,7 +32,6 @@ import android.app.Service;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
@@ -55,7 +54,6 @@ import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
import java.io.FileDescriptor;
@@ -169,7 +167,7 @@ public abstract class WallpaperService extends Service {
final Rect mFinalSystemInsets = new Rect();
final Rect mFinalStableInsets = new Rect();
final Rect mBackdropFrame = new Rect();
- final Configuration mConfiguration = new Configuration();
+ final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
final WindowManager.LayoutParams mLayout
= new WindowManager.LayoutParams();
@@ -288,7 +286,7 @@ public abstract class WallpaperService extends Service {
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropRect, boolean forceLayout,
boolean alwaysConsumeNavBar, int displayId) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0, outsets);
@@ -568,7 +566,8 @@ public abstract class WallpaperService extends Service {
out.print(mVisibleInsets.toShortString());
out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
out.print(" mContentInsets="); out.println(mContentInsets.toShortString());
- out.print(prefix); out.print("mConfiguration="); out.println(mConfiguration);
+ out.print(prefix); out.print("mConfiguration=");
+ out.println(mMergedConfiguration.getMergedConfiguration());
out.print(prefix); out.print("mLayout="); out.println(mLayout);
synchronized (mLock) {
out.print(prefix); out.print("mPendingXOffset="); out.print(mPendingXOffset);
@@ -695,7 +694,7 @@ public abstract class WallpaperService extends Service {
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mConfiguration, mSurfaceHolder.mSurface);
+ mMergedConfiguration, mSurfaceHolder.mSurface);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
diff --git a/core/java/android/util/MergedConfiguration.aidl b/core/java/android/util/MergedConfiguration.aidl
new file mode 100644
index 000000000000..c24dbbec68a6
--- /dev/null
+++ b/core/java/android/util/MergedConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+parcelable MergedConfiguration; \ No newline at end of file
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
new file mode 100644
index 000000000000..d94af8a68fc1
--- /dev/null
+++ b/core/java/android/util/MergedConfiguration.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container that holds global and override config and their merge product.
+ * Merged configuration updates automatically whenever global or override configs are updated via
+ * setters.
+ *
+ * {@hide}
+ */
+public class MergedConfiguration implements Parcelable {
+
+ private Configuration mGlobalConfig = new Configuration();
+ private Configuration mOverrideConfig = new Configuration();
+ private Configuration mMergedConfig = new Configuration();
+
+ public MergedConfiguration() {
+ }
+
+ public MergedConfiguration(Configuration globalConfig, Configuration overrideConfig) {
+ setConfiguration(globalConfig, overrideConfig);
+ }
+
+ public MergedConfiguration(MergedConfiguration mergedConfiguration) {
+ setConfiguration(mergedConfiguration.getGlobalConfiguration(),
+ mergedConfiguration.getOverrideConfiguration());
+ }
+
+ private MergedConfiguration(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mGlobalConfig, flags);
+ dest.writeParcelable(mOverrideConfig, flags);
+ dest.writeParcelable(mMergedConfig, flags);
+ }
+
+ public void readFromParcel(Parcel source) {
+ mGlobalConfig = source.readParcelable(Configuration.class.getClassLoader());
+ mOverrideConfig = source.readParcelable(Configuration.class.getClassLoader());
+ mMergedConfig = source.readParcelable(Configuration.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<MergedConfiguration> CREATOR = new Creator<MergedConfiguration>() {
+ @Override
+ public MergedConfiguration createFromParcel(Parcel in) {
+ return new MergedConfiguration(in);
+ }
+
+ @Override
+ public MergedConfiguration[] newArray(int size) {
+ return new MergedConfiguration[size];
+ }
+ };
+
+ /**
+ * Update global and override configurations.
+ * Merged configuration will automatically be updated.
+ * @param globalConfig New global configuration.
+ * @param overrideConfig New override configuration.
+ */
+ public void setConfiguration(Configuration globalConfig, Configuration overrideConfig) {
+ mGlobalConfig.setTo(globalConfig);
+ mOverrideConfig.setTo(overrideConfig);
+ updateMergedConfig();
+ }
+
+ /**
+ * @return Stored global configuration value.
+ */
+ @NonNull
+ public Configuration getGlobalConfiguration() {
+ return mGlobalConfig;
+ }
+
+ /**
+ * @return Stored override configuration value.
+ */
+ public Configuration getOverrideConfiguration() {
+ return mOverrideConfig;
+ }
+
+ /**
+ * @return Stored merged configuration value.
+ */
+ public Configuration getMergedConfiguration() {
+ return mMergedConfig;
+ }
+
+ /** Update merged config when global or override config changes. */
+ private void updateMergedConfig() {
+ mMergedConfig.setTo(mGlobalConfig);
+ mMergedConfig.updateFrom(mOverrideConfig);
+ }
+}
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index e59937dae055..ca54bef1e780 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -16,7 +16,6 @@
package android.view;
-import android.content.ComponentCallbacks;
import android.content.res.Configuration;
import java.text.BreakIterator;
@@ -65,7 +64,7 @@ public final class AccessibilityIterators {
}
static class CharacterTextSegmentIterator extends AbstractTextSegmentIterator
- implements ComponentCallbacks {
+ implements ViewRootImpl.ConfigChangedCallback {
private static CharacterTextSegmentIterator sInstance;
private Locale mLocale;
@@ -144,19 +143,14 @@ public final class AccessibilityIterators {
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- Locale locale = newConfig.locale;
+ public void onConfigurationChanged(Configuration globalConfig) {
+ final Locale locale = globalConfig.getLocales().get(0);
if (!mLocale.equals(locale)) {
mLocale = locale;
onLocaleChanged(locale);
}
}
- @Override
- public void onLowMemory() {
- /* ignore */
- }
-
protected void onLocaleChanged(Locale locale) {
mImpl = BreakIterator.getCharacterInstance(locale);
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 14b2abec2adb..611cc6337fb4 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,7 +17,6 @@
package android.view;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -26,6 +25,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import com.android.internal.os.IResultReceiver;
+import android.util.MergedConfiguration;
/**
* API back to a client window that the Window Manager uses to inform it of
@@ -49,8 +49,8 @@ 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, int displayId);
+ in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
+ boolean forceLayout, boolean alwaysConsumeNavBar, int displayId);
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7e6af11a62c7..51d65144f260 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -11,17 +11,17 @@
** 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
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.view;
import android.content.ClipData;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
+import android.util.MergedConfiguration;
import android.view.InputChannel;
import android.view.IWindow;
import android.view.IWindowId;
@@ -83,9 +83,9 @@ interface IWindowSession {
* treat as real display. Example of such area is a chin in some models of wearable devices.
* @param outBackdropFrame Rect which is used draw the resizing background during a resize
* operation.
- * @param outConfiguration New configuration of window, if it is now
- * becoming visible and the global configuration has changed since it
- * was last displayed.
+ * @param outMergedConfiguration New config container that holds global, override and merged
+ * config for window, if it is now becoming visible and the merged configuration has changed
+ * since it was last displayed.
* @param outSurface Object in which is placed the new display surface.
*
* @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
@@ -95,8 +95,8 @@ interface IWindowSession {
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
- out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig,
- out Surface outSurface);
+ out Rect outOutsets, out Rect outBackdropFrame,
+ out MergedConfiguration outMergedConfiguration, out Surface outSurface);
/*
* Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ed4238501c5a..048b7c22237c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.PFLAG_DRAW_ANIMATION;
import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
@@ -28,10 +29,10 @@ import android.Manifest;
import android.animation.LayoutTransition;
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.app.ResourcesManager;
import android.content.ClipData;
import android.content.ClipDescription;
-import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
@@ -67,6 +68,7 @@ import android.os.Trace;
import android.util.AndroidRuntimeException;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.TypedValue;
@@ -161,7 +163,44 @@ public final class ViewRootImpl implements ViewParent,
static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
static boolean sFirstDrawComplete = false;
- static final ArrayList<ComponentCallbacks> sConfigCallbacks = new ArrayList();
+ /**
+ * Callback for notifying about global configuration changes.
+ */
+ public interface ConfigChangedCallback {
+
+ /** Notifies about global config change. */
+ void onConfigurationChanged(Configuration globalConfig);
+ }
+
+ private static final ArrayList<ConfigChangedCallback> sConfigCallbacks = new ArrayList<>();
+
+ /**
+ * Callback for notifying activities about override configuration changes.
+ */
+ public interface ActivityConfigCallback {
+
+ /**
+ * Notifies about override config change and/or move to different display.
+ * @param overrideConfig New override config to apply to activity.
+ * @param newDisplayId New display id, {@link Display#INVALID_DISPLAY} if not changed.
+ */
+ void onConfigurationChanged(Configuration overrideConfig, int newDisplayId);
+ }
+
+ /**
+ * Callback used to notify corresponding activity about override configuration change and make
+ * sure that all resources are set correctly before updating the ViewRootImpl's internal state.
+ */
+ private ActivityConfigCallback mActivityConfigCallback;
+
+ /**
+ * Used when configuration change first updates the config of corresponding activity.
+ * In that case we receive a call back from {@link ActivityThread} and this flag is used to
+ * preserve the initial value.
+ *
+ * @see #performConfigurationChange(Configuration, Configuration, boolean, int)
+ */
+ private boolean mForceNextConfigUpdate;
/**
* Signals that compatibility booleans have been initialized according to
@@ -344,8 +383,12 @@ public final class ViewRootImpl implements ViewParent,
private WindowInsets mLastWindowInsets;
- final Configuration mLastConfiguration = new Configuration();
- final Configuration mPendingConfiguration = new Configuration();
+ /** Last applied configuration obtained from resources. */
+ private final Configuration mLastConfigurationFromResources = new Configuration();
+ /** Last configuration reported from WM or via {@link #MSG_UPDATE_CONFIGURATION}. */
+ private final MergedConfiguration mLastReportedMergedConfiguration = new MergedConfiguration();
+ /** Configurations waiting to be applied. */
+ private final MergedConfiguration mPendingMergedConfiguration = new MergedConfiguration();
boolean mScrollMayChange;
@SoftInputModeFlags
@@ -480,12 +523,18 @@ public final class ViewRootImpl implements ViewParent,
}
}
- public static void addConfigCallback(ComponentCallbacks callback) {
+ /** Add static config callback to be notified about global config changes. */
+ public static void addConfigCallback(ConfigChangedCallback callback) {
synchronized (sConfigCallbacks) {
sConfigCallbacks.add(callback);
}
}
+ /** Add activity config callback to be notified about override config changes. */
+ public void setActivityConfigCallback(ActivityConfigCallback callback) {
+ mActivityConfigCallback = callback;
+ }
+
public void addWindowCallbacks(WindowCallbacks callback) {
if (USE_MT_RENDERER) {
synchronized (mWindowCallbacks) {
@@ -1558,6 +1607,7 @@ public final class ViewRootImpl implements ViewParent,
mFullRedrawNeeded = true;
mLayoutRequested = true;
+ final Configuration config = mContext.getResources().getConfiguration();
if (shouldUseDisplaySize(lp)) {
// NOTE -- system code, won't try to do compat mode.
Point size = new Point();
@@ -1565,7 +1615,6 @@ public final class ViewRootImpl implements ViewParent,
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
} else {
- Configuration config = mContext.getResources().getConfiguration();
desiredWindowWidth = dipToPx(config.screenWidthDp);
desiredWindowHeight = dipToPx(config.screenHeightDp);
}
@@ -1577,11 +1626,11 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mHasWindowFocus = false;
mAttachInfo.mWindowVisibility = viewVisibility;
mAttachInfo.mRecomputeGlobalAttributes = false;
- mLastConfiguration.setTo(host.getResources().getConfiguration());
+ mLastConfigurationFromResources.setTo(config);
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
// Set the layout direction if it has not been set before (inherit is the default)
if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
- host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+ host.setLayoutDirection(config.getLayoutDirection());
}
host.dispatchAttachedToWindow(mAttachInfo, 0);
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
@@ -1826,11 +1875,14 @@ public final class ViewRootImpl implements ViewParent,
+ " outsets=" + mPendingOutsets.toShortString()
+ " surface=" + mSurface);
- if (mPendingConfiguration.seq != 0) {
+ final Configuration pendingMergedConfig =
+ mPendingMergedConfiguration.getMergedConfiguration();
+ if (pendingMergedConfig.seq != 0) {
if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
- + mPendingConfiguration);
- updateConfiguration(new Configuration(mPendingConfiguration), !mFirst);
- mPendingConfiguration.seq = 0;
+ + pendingMergedConfig);
+ performConfigurationChange(mPendingMergedConfiguration, !mFirst,
+ INVALID_DISPLAY /* same display */);
+ pendingMergedConfig.seq = 0;
updatedConfiguration = true;
}
@@ -3388,43 +3440,82 @@ public final class ViewRootImpl implements ViewParent,
unscheduleTraversals();
}
- void updateConfiguration(Configuration config, boolean force) {
+ /**
+ * Notifies all callbacks that configuration and/or display has changed and updates internal
+ * state.
+ * @param mergedConfiguration New global and override config in {@link MergedConfiguration}
+ * container.
+ * @param force Flag indicating if we should force apply the config.
+ * @param newDisplayId Id of new display if moved, {@link Display#INVALID_DISPLAY} if not
+ * changed.
+ */
+ private void performConfigurationChange(MergedConfiguration mergedConfiguration, boolean force,
+ int newDisplayId) {
+ if (mergedConfiguration == null) {
+ throw new IllegalArgumentException("No merged config provided.");
+ }
+
+ Configuration globalConfig = mergedConfiguration.getGlobalConfiguration();
+ final Configuration overrideConfig = mergedConfiguration.getOverrideConfiguration();
if (DEBUG_CONFIGURATION) Log.v(mTag,
- "Applying new config to window "
- + mWindowAttributes.getTitle()
- + ": " + config);
+ "Applying new config to window " + mWindowAttributes.getTitle()
+ + ", globalConfig: " + globalConfig
+ + ", overrideConfig: " + overrideConfig);
- CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
+ final CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
- config = new Configuration(config);
- ci.applyToConfiguration(mNoncompatDensity, config);
+ globalConfig = new Configuration(globalConfig);
+ ci.applyToConfiguration(mNoncompatDensity, globalConfig);
}
synchronized (sConfigCallbacks) {
for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
- sConfigCallbacks.get(i).onConfigurationChanged(config);
+ sConfigCallbacks.get(i).onConfigurationChanged(globalConfig);
}
}
- if (mView != null) {
- // At this point the resources have been updated to
- // have the most recent config, whatever that is. Use
- // the one in them which may be newer.
- final Resources localResources = mView.getResources();
- config = localResources.getConfiguration();
- if (force || mLastConfiguration.diff(config) != 0) {
- // Update the display with new DisplayAdjustments.
- mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
- mDisplay.getDisplayId(), localResources);
- final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
- final int currentLayoutDirection = config.getLayoutDirection();
- mLastConfiguration.setTo(config);
- if (lastLayoutDirection != currentLayoutDirection &&
- mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
- mView.setLayoutDirection(currentLayoutDirection);
- }
- mView.dispatchConfigurationChanged(config);
+ mLastReportedMergedConfiguration.setConfiguration(globalConfig, overrideConfig);
+
+ mForceNextConfigUpdate = force;
+ if (mActivityConfigCallback != null) {
+ // An activity callback is set - notify it about override configuration update.
+ // This basically initiates a round trip to ActivityThread and back, which will ensure
+ // that corresponding activity and resources are updated before updating inner state of
+ // ViewRootImpl. Eventually it will call #updateConfiguration().
+ mActivityConfigCallback.onConfigurationChanged(overrideConfig, newDisplayId);
+ } else {
+ // There is no activity callback - update the configuration right away.
+ updateConfiguration();
+ }
+ mForceNextConfigUpdate = false;
+ }
+
+ /**
+ * Update display and views if last applied merged configuration changed.
+ */
+ public void updateConfiguration() {
+ if (mView == null) {
+ return;
+ }
+
+ // At this point the resources have been updated to
+ // have the most recent config, whatever that is. Use
+ // the one in them which may be newer.
+ final Resources localResources = mView.getResources();
+ final Configuration config = localResources.getConfiguration();
+ if (mForceNextConfigUpdate || mLastConfigurationFromResources.diff(config) != 0) {
+ // Update the display with new DisplayAdjustments.
+ mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
+ mDisplay.getDisplayId(), localResources);
+
+ final int lastLayoutDirection = mLastConfigurationFromResources.getLayoutDirection();
+ final int currentLayoutDirection = config.getLayoutDirection();
+ mLastConfigurationFromResources.setTo(config);
+ if (lastLayoutDirection != currentLayoutDirection
+ && mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+ mView.setLayoutDirection(currentLayoutDirection);
}
+ mView.dispatchConfigurationChanged(config);
}
}
@@ -3582,13 +3673,16 @@ public final class ViewRootImpl implements ViewParent,
if (mAdded) {
SomeArgs args = (SomeArgs) msg.obj;
- if (mDisplay.getDisplayId() != args.argi3) {
- onMovedToDisplay(args.argi3);
+ final int displayId = args.argi3;
+ final boolean displayChanged = mDisplay.getDisplayId() != displayId;
+ if (displayChanged) {
+ onMovedToDisplay(displayId);
}
- Configuration config = (Configuration) args.arg4;
- if (config != null) {
- updateConfiguration(config, false);
+ final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
+ if (mergedConfiguration != null) {
+ performConfigurationChange(mergedConfiguration, false /* force */,
+ displayChanged ? displayId : INVALID_DISPLAY /* same display */);
}
final boolean framesChanged = !mWinFrame.equals(args.arg1)
@@ -3759,11 +3853,19 @@ public final class ViewRootImpl implements ViewParent,
handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo) msg.obj);
} break;
case MSG_UPDATE_CONFIGURATION: {
- Configuration config = (Configuration)msg.obj;
- if (config.isOtherSeqNewer(mLastConfiguration)) {
- config = mLastConfiguration;
+ Configuration config = (Configuration) msg.obj;
+ if (config.isOtherSeqNewer(
+ mLastReportedMergedConfiguration.getMergedConfiguration())) {
+ // If we already have a newer merged config applied - use its global part.
+ config = mLastReportedMergedConfiguration.getGlobalConfiguration();
}
- updateConfiguration(config, false);
+
+ // Use the newer global config and last reported override config.
+ mPendingMergedConfiguration.setConfiguration(config,
+ mLastReportedMergedConfiguration.getOverrideConfiguration());
+
+ performConfigurationChange(mPendingMergedConfiguration, false /* force */,
+ INVALID_DISPLAY /* same display */);
} break;
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
setAccessibilityFocus(null, null);
@@ -5902,7 +6004,7 @@ public final class ViewRootImpl implements ViewParent,
if (params != null) {
if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
}
- mPendingConfiguration.seq = 0;
+ mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
//Log.d(mTag, ">>>>>> CALLING relayout");
if (params != null && mOrigWindowType != params.type) {
// For compatibility with old apps, don't crash here.
@@ -5918,8 +6020,8 @@ public final class ViewRootImpl implements ViewParent,
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
- mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
- mSurface);
+ mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame,
+ mPendingMergedConfiguration, mSurface);
mPendingAlwaysConsumeNavBar =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6199,9 +6301,9 @@ public final class ViewRootImpl implements ViewParent,
}
}
- public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
+ private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
boolean alwaysConsumeNavBar, int displayId) {
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
+ " contentInsets=" + contentInsets.toShortString()
@@ -6233,7 +6335,8 @@ public final class ViewRootImpl implements ViewParent,
args.arg1 = sameProcessCall ? new Rect(frame) : frame;
args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets;
args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets;
- args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig;
+ args.arg4 = sameProcessCall && mergedConfiguration != null
+ ? new MergedConfiguration(mergedConfiguration) : null;
args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets;
args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
@@ -7243,13 +7346,13 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
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, displayId);
+ visibleInsets, stableInsets, outsets, reportDraw, mergedConfiguration,
+ backDropFrame, forceLayout, alwaysConsumeNavBar, displayId);
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index ce51dc4ead9e..361fd3da97c7 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,12 +16,12 @@
package com.android.internal.view;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.util.MergedConfiguration;
import android.view.DragEvent;
import android.view.IWindow;
import android.view.IWindowSession;
@@ -39,8 +39,9 @@ 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, int displayId) {
+ Rect stableInsets, Rect outsets, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar, int displayId) {
if (reportDraw) {
try {
mSession.finishDrawing(this);