Merge "Separate global and override config sent to client"

This commit is contained in:
Andrii Kulian
2017-03-17 15:39:32 +00:00
committed by Android (Google) Code Review
16 changed files with 401 additions and 147 deletions

View File

@@ -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());
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(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
// 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() {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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) {
if (DEBUG_CONFIGURATION) Log.v(mTag,
"Applying new config to window "
+ mWindowAttributes.getTitle()
+ ": " + config);
/**
* 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.");
}
CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
Configuration globalConfig = mergedConfiguration.getGlobalConfiguration();
final Configuration overrideConfig = mergedConfiguration.getOverrideConfiguration();
if (DEBUG_CONFIGURATION) Log.v(mTag,
"Applying new config to window " + mWindowAttributes.getTitle()
+ ", globalConfig: " + globalConfig
+ ", overrideConfig: " + overrideConfig);
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);
}
}