diff options
| author | Andrii Kulian <akulian@google.com> | 2017-03-17 15:39:32 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-03-17 15:39:37 +0000 |
| commit | c1b59ed73eeea40c70cc81e2ab486cd54d94ed5d (patch) | |
| tree | 30a6bfe3b09b1d6eaa552c143d5f7ff690c79b5f /core/java/android | |
| parent | edd694e4bf584d933028c9ef02199c36a9729690 (diff) | |
| parent | 446079600ece83b22cb91865bcbeb694292b0108 (diff) | |
Merge "Separate global and override config sent to client"
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 66 | ||||
| -rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 13 | ||||
| -rw-r--r-- | core/java/android/util/MergedConfiguration.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/util/MergedConfiguration.java | 122 | ||||
| -rw-r--r-- | core/java/android/view/AccessibilityIterators.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/IWindow.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/view/IWindowSession.aidl | 14 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 215 |
8 files changed, 357 insertions, 110 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); } } |
