Merge "Separate global and override config sent to client"
This commit is contained in:
committed by
Android (Google) Code Review
commit
c1b59ed73e
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
19
core/java/android/util/MergedConfiguration.aidl
Normal file
19
core/java/android/util/MergedConfiguration.aidl
Normal 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;
|
||||
122
core/java/android/util/MergedConfiguration.java
Normal file
122
core/java/android/util/MergedConfiguration.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user