summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml26
-rw-r--r--core/java/android/app/ActivityThread.java153
-rw-r--r--core/java/android/content/res/Configuration.java48
-rw-r--r--core/java/android/content/res/Resources.java4
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java3
-rw-r--r--core/java/android/view/IWindow.aidl3
-rw-r--r--core/java/android/view/IWindowManager.aidl9
-rw-r--r--core/java/android/view/SurfaceView.java3
-rw-r--r--core/java/android/view/View.java27
-rw-r--r--core/java/android/view/ViewGroup.java14
-rw-r--r--core/java/android/view/ViewRoot.java51
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java3
-rw-r--r--services/java/com/android/server/WindowManagerService.java395
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java31
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java3
15 files changed, 516 insertions, 257 deletions
diff --git a/api/current.xml b/api/current.xml
index 6b277f3..c0a76f8 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -173008,6 +173008,19 @@
visibility="public"
>
</method>
+<method name="dispatchConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newConfig" type="android.content.res.Configuration">
+</parameter>
+</method>
<method name="dispatchDisplayHint"
return="void"
abstract="false"
@@ -174699,6 +174712,19 @@
visibility="public"
>
</method>
+<method name="onConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="newConfig" type="android.content.res.Configuration">
+</parameter>
+</method>
<method name="onCreateContextMenu"
return="void"
abstract="false"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 56e44c8..13cc3ba 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1392,7 +1392,7 @@ public final class ActivityThread {
r.startsNotResumed = notResumed;
r.createdConfig = config;
- synchronized (mRelaunchingActivities) {
+ synchronized (mPackages) {
mRelaunchingActivities.add(r);
}
@@ -1523,8 +1523,11 @@ public final class ActivityThread {
}
public void scheduleConfigurationChanged(Configuration config) {
- synchronized (mRelaunchingActivities) {
- mPendingConfiguration = config;
+ synchronized (mPackages) {
+ if (mPendingConfiguration == null ||
+ mPendingConfiguration.isOtherSeqNewer(config)) {
+ mPendingConfiguration = config;
+ }
}
queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
}
@@ -2060,6 +2063,7 @@ public final class ActivityThread {
= new HashMap<IBinder, Service>();
AppBindData mBoundApplication;
Configuration mConfiguration;
+ Configuration mResConfiguration;
Application mInitialApplication;
final ArrayList<Application> mAllApplications
= new ArrayList<Application>();
@@ -2073,14 +2077,6 @@ public final class ActivityThread {
boolean mSystemThread = false;
boolean mJitEnabled = false;
- /**
- * Activities that are enqueued to be relaunched. This list is accessed
- * by multiple threads, so you must synchronize on it when accessing it.
- */
- final ArrayList<ActivityRecord> mRelaunchingActivities
- = new ArrayList<ActivityRecord>();
- Configuration mPendingConfiguration = null;
-
// These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
@@ -2092,6 +2088,9 @@ public final class ActivityThread {
DisplayMetrics mDisplayMetrics = null;
HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
= new HashMap<ResourcesKey, WeakReference<Resources> >();
+ final ArrayList<ActivityRecord> mRelaunchingActivities
+ = new ArrayList<ActivityRecord>();
+ Configuration mPendingConfiguration = null;
// The lock of mProviderMap protects the following variables.
final HashMap<String, ProviderRecord> mProviderMap
@@ -3555,7 +3554,7 @@ public final class ActivityThread {
// First: make sure we have the most recent configuration and most
// recent version of the activity, or skip it if some previous call
// had taken a more recent version.
- synchronized (mRelaunchingActivities) {
+ synchronized (mPackages) {
int N = mRelaunchingActivities.size();
IBinder token = tmp.token;
tmp = null;
@@ -3585,8 +3584,12 @@ public final class ActivityThread {
// assume that is really what we want regardless of what we
// may have pending.
if (mConfiguration == null
- || mConfiguration.diff(tmp.createdConfig) != 0) {
- changedConfig = tmp.createdConfig;
+ || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
+ && mConfiguration.diff(tmp.createdConfig) != 0)) {
+ if (changedConfig == null
+ || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
+ changedConfig = tmp.createdConfig;
+ }
}
}
@@ -3761,62 +3764,81 @@ public final class ActivityThread {
}
}
+ final void applyConfigurationToResourcesLocked(Configuration config) {
+ if (mResConfiguration == null) {
+ mResConfiguration = new Configuration();
+ }
+ if (!mResConfiguration.isOtherSeqNewer(config)) {
+ return;
+ }
+ mResConfiguration.updateFrom(config);
+ DisplayMetrics dm = getDisplayMetricsLocked(true);
+
+ // set it for java, this also affects newly created Resources
+ if (config.locale != null) {
+ Locale.setDefault(config.locale);
+ }
+
+ Resources.updateSystemConfiguration(config, dm);
+
+ ContextImpl.ApplicationPackageManager.configurationChanged();
+ //Log.i(TAG, "Configuration changed in " + currentPackageName());
+
+ Iterator<WeakReference<Resources>> it =
+ mActiveResources.values().iterator();
+ //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
+ // mActiveResources.entrySet().iterator();
+ while (it.hasNext()) {
+ WeakReference<Resources> v = it.next();
+ Resources r = v.get();
+ if (r != null) {
+ r.updateConfiguration(config, dm);
+ //Log.i(TAG, "Updated app resources " + v.getKey()
+ // + " " + r + ": " + r.getConfiguration());
+ } else {
+ //Log.i(TAG, "Removing old resources " + v.getKey());
+ it.remove();
+ }
+ }
+ }
+
final void handleConfigurationChanged(Configuration config) {
- synchronized (mRelaunchingActivities) {
+ ArrayList<ComponentCallbacks> callbacks = null;
+
+ synchronized (mPackages) {
if (mPendingConfiguration != null) {
- config = mPendingConfiguration;
+ if (!mPendingConfiguration.isOtherSeqNewer(config)) {
+ config = mPendingConfiguration;
+ }
mPendingConfiguration = null;
}
- }
-
- ArrayList<ComponentCallbacks> callbacks
- = new ArrayList<ComponentCallbacks>();
- if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
- + config);
+ if (config == null) {
+ return;
+ }
+
+ if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
+ + config);
- synchronized(mPackages) {
+ applyConfigurationToResourcesLocked(config);
+
if (mConfiguration == null) {
mConfiguration = new Configuration();
}
- mConfiguration.updateFrom(config);
- DisplayMetrics dm = getDisplayMetricsLocked(true);
-
- // set it for java, this also affects newly created Resources
- if (config.locale != null) {
- Locale.setDefault(config.locale);
- }
-
- Resources.updateSystemConfiguration(config, dm);
-
- ContextImpl.ApplicationPackageManager.configurationChanged();
- //Log.i(TAG, "Configuration changed in " + currentPackageName());
- {
- Iterator<WeakReference<Resources>> it =
- mActiveResources.values().iterator();
- //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
- // mActiveResources.entrySet().iterator();
- while (it.hasNext()) {
- WeakReference<Resources> v = it.next();
- Resources r = v.get();
- if (r != null) {
- r.updateConfiguration(config, dm);
- //Log.i(TAG, "Updated app resources " + v.getKey()
- // + " " + r + ": " + r.getConfiguration());
- } else {
- //Log.i(TAG, "Removing old resources " + v.getKey());
- it.remove();
- }
- }
+ if (!mConfiguration.isOtherSeqNewer(config)) {
+ return;
}
+ mConfiguration.updateFrom(config);
callbacks = collectComponentCallbacksLocked(false, config);
}
- final int N = callbacks.size();
- for (int i=0; i<N; i++) {
- performConfigurationChanged(callbacks.get(i), config);
+ if (callbacks != null) {
+ final int N = callbacks.size();
+ for (int i=0; i<N; i++) {
+ performConfigurationChanged(callbacks.get(i), config);
+ }
}
}
@@ -3856,7 +3878,7 @@ public final class ActivityThread {
ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>();
- synchronized(mPackages) {
+ synchronized (mPackages) {
callbacks = collectComponentCallbacksLocked(true, null);
}
@@ -4348,6 +4370,25 @@ public final class ActivityThread {
"Unable to instantiate Application():" + e.toString(), e);
}
}
+
+ ViewRoot.addConfigCallback(new ComponentCallbacks() {
+ public void onConfigurationChanged(Configuration newConfig) {
+ synchronized (mPackages) {
+ if (mPendingConfiguration == null ||
+ mPendingConfiguration.isOtherSeqNewer(newConfig)) {
+ mPendingConfiguration = newConfig;
+
+ // We need to apply this change to the resources
+ // immediately, because upon returning the view
+ // hierarchy will be informed about it.
+ applyConfigurationToResourcesLocked(newConfig);
+ }
+ }
+ queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
+ }
+ public void onLowMemory() {
+ }
+ });
}
private final void detach()
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index aa5f128..6490b65 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -193,6 +193,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public int uiMode;
/**
+ * @hide Internal book-keeping.
+ */
+ public int seq;
+
+ /**
* Construct an invalid Configuration. You must call {@link #setToDefaults}
* for this object to be valid. {@more}
*/
@@ -220,6 +225,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
orientation = o.orientation;
screenLayout = o.screenLayout;
uiMode = o.uiMode;
+ seq = o.seq;
}
public String toString() {
@@ -250,6 +256,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
sb.append(screenLayout);
sb.append(" uiMode=");
sb.append(uiMode);
+ if (seq != 0) {
+ sb.append(" seq=");
+ sb.append(seq);
+ }
sb.append('}');
return sb.toString();
}
@@ -260,7 +270,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public void setToDefaults() {
fontScale = 1;
mcc = mnc = 0;
- locale = Locale.getDefault();
+ locale = null;
userSetLocale = false;
touchscreen = TOUCHSCREEN_UNDEFINED;
keyboard = KEYBOARD_UNDEFINED;
@@ -271,6 +281,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
orientation = ORIENTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
uiMode = UI_MODE_TYPE_NORMAL;
+ seq = 0;
}
/** {@hide} */
@@ -357,6 +368,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
uiMode = delta.uiMode;
}
+ if (delta.seq != 0) {
+ seq = delta.seq;
+ }
+
return changed;
}
@@ -456,6 +471,35 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
/**
+ * @hide Return true if the sequence of 'other' is better than this. Assumes
+ * that 'this' is your current sequence and 'other' is a new one you have
+ * received some how and want to compare with what you have.
+ */
+ public boolean isOtherSeqNewer(Configuration other) {
+ if (other == null) {
+ // Sanity check.
+ return false;
+ }
+ if (other.seq == 0) {
+ // If the other sequence is not specified, then we must assume
+ // it is newer since we don't know any better.
+ return true;
+ }
+ if (seq == 0) {
+ // If this sequence is not specified, then we also consider the
+ // other is better. Yes we have a preference for other. Sue us.
+ return true;
+ }
+ int diff = other.seq - seq;
+ if (diff > 0x10000) {
+ // If there has been a sufficiently large jump, assume the
+ // sequence has wrapped around.
+ return false;
+ }
+ return diff > 0;
+ }
+
+ /**
* Parcelable methods
*/
public int describeContents() {
@@ -488,6 +532,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(orientation);
dest.writeInt(screenLayout);
dest.writeInt(uiMode);
+ dest.writeInt(seq);
}
public static final Parcelable.Creator<Configuration> CREATOR
@@ -522,6 +567,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
orientation = source.readInt();
screenLayout = source.readInt();
uiMode = source.readInt();
+ seq = source.readInt();
}
public int compareTo(Configuration that) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ae8e297..a5e39d4 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -39,6 +39,7 @@ import android.view.Display;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
+import java.util.Locale;
/**
* Class for accessing an application's resources. This sits on top of the
@@ -1259,6 +1260,9 @@ public class Resources {
if (config != null) {
configChanges = mConfiguration.updateFrom(config);
}
+ if (mConfiguration.locale == null) {
+ mConfiguration.locale = Locale.getDefault();
+ }
if (metrics != null) {
mMetrics.setTo(metrics);
mMetrics.updateMetrics(mCompatibilityInfo,
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index eb48a0c..52de64c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -28,6 +28,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -226,7 +227,7 @@ public abstract class WallpaperService extends Service {
@Override
public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
+ Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0);
mCaller.sendMessage(msg);
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 71302cb..3b09808 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,6 +17,7 @@
package android.view;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -44,7 +45,7 @@ oneway interface IWindow {
void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
- boolean reportDraw);
+ boolean reportDraw, in Configuration newConfig);
void dispatchKey(in KeyEvent event);
void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0ebe360..9b7b2f4 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -64,8 +64,6 @@ interface IWindowManager
void addAppToken(int addPos, IApplicationToken token,
int groupId, int requestedOrientation, boolean fullscreen);
void setAppGroupId(IBinder token, int groupId);
- Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
- IBinder freezeThisOneIfNeeded);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
void setFocusedApp(IBinder token, boolean moveFocusNow);
@@ -85,6 +83,13 @@ interface IWindowManager
void moveAppTokensToTop(in List<IBinder> tokens);
void moveAppTokensToBottom(in List<IBinder> tokens);
+ // Re-evaluate the current orientation from the caller's state.
+ // If there is a change, the new Configuration is returned and the
+ // caller must call setNewConfiguration() sometime later.
+ Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
+ IBinder freezeThisOneIfNeeded);
+ void setNewConfiguration(in Configuration config);
+
// these require DISABLE_KEYGUARD permission
void disableKeyguard(IBinder token, String tag);
void reenableKeyguard(IBinder token);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index ca5e1de..d7f2539 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -19,6 +19,7 @@ package android.view;
import com.android.internal.view.BaseIWindow;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
@@ -504,7 +505,7 @@ public class SurfaceView extends View {
}
public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
+ Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
if (localLOGV) Log.v(
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bc49439..2eb633f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20,6 +20,7 @@ import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -3933,6 +3934,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Dispatch a notification about a resource configuration change down
+ * the view hierarchy.
+ * ViewGroups should override to route to their children.
+ *
+ * @param newConfig The new resource configuration.
+ *
+ * @see #onConfigurationChanged
+ */
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ onConfigurationChanged(newConfig);
+ }
+
+ /**
+ * Called when the current configuration of the resources being used
+ * by the application have changed. You can use this to decide when
+ * to reload resources that can changed based on orientation and other
+ * configuration characterstics. You only need to use this if you are
+ * not relying on the normal {@link android.app.Activity} mechanism of
+ * recreating the activity instance upon a configuration change.
+ *
+ * @param newConfig The new resource configuration.
+ */
+ protected void onConfigurationChanged(Configuration newConfig) {
+ }
+
+ /**
* Private function to aggregate all per-view attributes in to the view
* root.
*/
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2ed623d..0663215 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -19,6 +19,7 @@ package android.view;
import com.android.internal.R;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -722,6 +723,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* {@inheritDoc}
*/
+ @Override
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ super.dispatchConfigurationChanged(newConfig);
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < count; i++) {
+ children[i].dispatchConfigurationChanged(newConfig);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void recomputeViewAttributes(View child) {
ViewParent parent = mParent;
if (parent != null) parent.recomputeViewAttributes(this);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 07b2d1c..264b8c9 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -41,7 +41,9 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.ComponentCallbacks;
import android.content.Context;
import android.app.ActivityManagerNative;
import android.Manifest;
@@ -101,6 +103,9 @@ public final class ViewRoot extends Handler implements ViewParent,
static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
static boolean sFirstDrawComplete = false;
+ static final ArrayList<ComponentCallbacks> sConfigCallbacks
+ = new ArrayList<ComponentCallbacks>();
+
private static int sDrawTime;
long mLastTrackballTime = 0;
@@ -171,6 +176,12 @@ public final class ViewRoot extends Handler implements ViewParent,
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
+ class ResizedInfo {
+ Rect coveredInsets;
+ Rect visibleInsets;
+ Configuration newConfig;
+ }
+
boolean mScrollMayChange;
int mSoftInputMode;
View mLastScrolledFocus;
@@ -265,6 +276,12 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
+ public static void addConfigCallback(ComponentCallbacks callback) {
+ synchronized (sConfigCallbacks) {
+ sConfigCallbacks.add(callback);
+ }
+ }
+
// FIXME for perf testing only
private boolean mProfile = false;
@@ -1782,23 +1799,33 @@ public final class ViewRoot extends Handler implements ViewParent,
handleGetNewSurface();
break;
case RESIZED:
- Rect coveredInsets = ((Rect[])msg.obj)[0];
- Rect visibleInsets = ((Rect[])msg.obj)[1];
+ ResizedInfo ri = (ResizedInfo)msg.obj;
if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
- && mPendingContentInsets.equals(coveredInsets)
- && mPendingVisibleInsets.equals(visibleInsets)) {
+ && mPendingContentInsets.equals(ri.coveredInsets)
+ && mPendingVisibleInsets.equals(ri.visibleInsets)) {
break;
}
// fall through...
case RESIZED_REPORT:
if (mAdded) {
+ Configuration config = ((ResizedInfo)msg.obj).newConfig;
+ if (config != null) {
+ synchronized (sConfigCallbacks) {
+ for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
+ sConfigCallbacks.get(i).onConfigurationChanged(config);
+ }
+ }
+ if (mView != null) {
+ mView.dispatchConfigurationChanged(config);
+ }
+ }
mWinFrame.left = 0;
mWinFrame.right = msg.arg1;
mWinFrame.top = 0;
mWinFrame.bottom = msg.arg2;
- mPendingContentInsets.set(((Rect[])msg.obj)[0]);
- mPendingVisibleInsets.set(((Rect[])msg.obj)[1]);
+ mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
+ mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
if (msg.what == RESIZED_REPORT) {
mReportNextDraw = true;
}
@@ -2587,7 +2614,7 @@ public final class ViewRoot extends Handler implements ViewParent,
}
public void dispatchResized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
+ Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w
+ " h=" + h + " coveredInsets=" + coveredInsets.toShortString()
+ " visibleInsets=" + visibleInsets.toShortString()
@@ -2601,7 +2628,11 @@ public final class ViewRoot extends Handler implements ViewParent,
}
msg.arg1 = w;
msg.arg2 = h;
- msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
+ ResizedInfo ri = new ResizedInfo();
+ ri.coveredInsets = new Rect(coveredInsets);
+ ri.visibleInsets = new Rect(visibleInsets);
+ ri.newConfig = newConfig;
+ msg.obj = ri;
sendMessage(msg);
}
@@ -2802,11 +2833,11 @@ public final class ViewRoot extends Handler implements ViewParent,
}
public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
+ Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
viewRoot.dispatchResized(w, h, coveredInsets,
- visibleInsets, reportDraw);
+ visibleInsets, reportDraw, newConfig);
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 15dcbd6..22c6e79 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -1,5 +1,6 @@
package com.android.internal.view;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -17,7 +18,7 @@ public class BaseIWindow extends IWindow.Stub {
}
public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
+ Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
if (reportDraw) {
try {
mSession.finishDrawing(this);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 7fcf900..a481036 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -373,10 +373,15 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mLayoutNeeded = true;
boolean mAnimationPending = false;
boolean mDisplayFrozen = false;
+ boolean mWaitingForConfig = false;
boolean mWindowsFreezingScreen = false;
long mFreezeGcPending = 0;
int mAppsFreezingScreen = 0;
+ int mLayoutSeq = 0;
+
+ Configuration mCurConfiguration = new Configuration();
+
// This is held as long as we have the screen frozen, to give us time to
// perform a rotation animation when turning off shows the lock screen which
// changes the orientation.
@@ -1828,7 +1833,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
- attachedWindow = windowForClientLocked(null, attrs.token);
+ attachedWindow = windowForClientLocked(null, attrs.token, false);
if (attachedWindow == null) {
Log.w(TAG, "Attempted to add window with token that is not a window: "
+ attrs.token + ". Aborting.");
@@ -1988,6 +1993,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (localLOGV) Log.v(
TAG, "New client " + client.asBinder()
+ ": window=" + win);
+
+ if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
+ reportNewConfig = true;
+ }
}
// sendNewConfiguration() checks caller permissions so we must call it with
@@ -1997,14 +2006,6 @@ public class WindowManagerService extends IWindowManager.Stub
final long origId = Binder.clearCallingIdentity();
if (reportNewConfig) {
sendNewConfiguration();
- } else {
- // Update Orientation after adding a window, only if the window needs to be
- // displayed right away
- if (win.isVisibleOrAdding()) {
- if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
- sendNewConfiguration();
- }
- }
}
Binder.restoreCallingIdentity(origId);
@@ -2013,7 +2014,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(session, client);
+ WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return;
}
@@ -2081,8 +2082,9 @@ public class WindowManagerService extends IWindowManager.Stub
// Removing a visible window will effect the computed orientation
// So just update orientation if needed.
if (wasVisible && computeForcedAppOrientationLocked()
- != mForcedAppOrientation) {
- mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION));
+ != mForcedAppOrientation
+ && updateOrientationFromAppTokensLocked()) {
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
Binder.restoreCallingIdentity(origId);
@@ -2177,7 +2179,7 @@ public class WindowManagerService extends IWindowManager.Stub
long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
- WindowState w = windowForClientLocked(session, client);
+ WindowState w = windowForClientLocked(session, client, false);
if ((w != null) && (w.mSurface != null)) {
if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
Surface.openTransaction();
@@ -2203,7 +2205,7 @@ public class WindowManagerService extends IWindowManager.Stub
long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
- WindowState w = windowForClientLocked(session, client);
+ WindowState w = windowForClientLocked(session, client, false);
if (w != null) {
w.mGivenInsetsPending = false;
w.mGivenContentInsets.set(contentInsets);
@@ -2221,7 +2223,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void getWindowDisplayFrame(Session session, IWindow client,
Rect outDisplayFrame) {
synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(session, client);
+ WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
outDisplayFrame.setEmpty();
return;
@@ -2291,11 +2293,11 @@ public class WindowManagerService extends IWindowManager.Stub
Surface outSurface) {
boolean displayed = false;
boolean inTouchMode;
- Configuration newConfig = null;
+ boolean configChanged;
long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(session, client);
+ WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return 0;
}
@@ -2507,7 +2509,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (assignLayers) {
assignLayersLocked();
}
- newConfig = updateOrientationFromAppTokensLocked(null, null);
+ configChanged = updateOrientationFromAppTokensLocked();
performLayoutAndPlaceSurfacesLocked();
if (displayed && win.mIsWallpaper) {
updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
@@ -2533,7 +2535,7 @@ public class WindowManagerService extends IWindowManager.Stub
inTouchMode = mInTouchMode;
}
- if (newConfig != null) {
+ if (configChanged) {
sendNewConfiguration();
}
@@ -2546,7 +2548,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void finishDrawingWindow(Session session, IWindow client) {
final long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(session, client);
+ WindowState win = windowForClientLocked(session, client, false);
if (win != null && win.finishDrawingLocked()) {
if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
adjustWallpaperWindowsLocked();
@@ -2988,62 +2990,62 @@ public class WindowManagerService extends IWindowManager.Stub
}
public int getOrientationFromAppTokensLocked() {
- int pos = mAppTokens.size() - 1;
- int curGroup = 0;
- int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
- boolean findingBehind = false;
- boolean haveGroup = false;
- boolean lastFullscreen = false;
- while (pos >= 0) {
- AppWindowToken wtoken = mAppTokens.get(pos);
- pos--;
- // if we're about to tear down this window and not seek for
- // the behind activity, don't use it for orientation
- if (!findingBehind
- && (!wtoken.hidden && wtoken.hiddenRequested)) {
+ int pos = mAppTokens.size() - 1;
+ int curGroup = 0;
+ int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ boolean findingBehind = false;
+ boolean haveGroup = false;
+ boolean lastFullscreen = false;
+ while (pos >= 0) {
+ AppWindowToken wtoken = mAppTokens.get(pos);
+ pos--;
+ // if we're about to tear down this window and not seek for
+ // the behind activity, don't use it for orientation
+ if (!findingBehind
+ && (!wtoken.hidden && wtoken.hiddenRequested)) {
+ continue;
+ }
+
+ if (!haveGroup) {
+ // We ignore any hidden applications on the top.
+ if (wtoken.hiddenRequested || wtoken.willBeHidden) {
continue;
}
-
- if (!haveGroup) {
- // We ignore any hidden applications on the top.
- if (wtoken.hiddenRequested || wtoken.willBeHidden) {
- continue;
- }
- haveGroup = true;
- curGroup = wtoken.groupId;
- lastOrientation = wtoken.requestedOrientation;
- } else if (curGroup != wtoken.groupId) {
- // If we have hit a new application group, and the bottom
- // of the previous group didn't explicitly say to use
- // the orientation behind it, and the last app was
- // full screen, then we'll stick with the
- // user's orientation.
- if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
- && lastFullscreen) {
- return lastOrientation;
- }
- }
- int or = wtoken.requestedOrientation;
- // If this application is fullscreen, and didn't explicitly say
- // to use the orientation behind it, then just take whatever
- // orientation it has and ignores whatever is under it.
- lastFullscreen = wtoken.appFullscreen;
- if (lastFullscreen
- && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
- return or;
- }
- // If this application has requested an explicit orientation,
- // then use it.
- if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
- or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
- or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
- or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
- or == ActivityInfo.SCREEN_ORIENTATION_USER) {
- return or;
- }
- findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
- }
- return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ haveGroup = true;
+ curGroup = wtoken.groupId;
+ lastOrientation = wtoken.requestedOrientation;
+ } else if (curGroup != wtoken.groupId) {
+ // If we have hit a new application group, and the bottom
+ // of the previous group didn't explicitly say to use
+ // the orientation behind it, and the last app was
+ // full screen, then we'll stick with the
+ // user's orientation.
+ if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
+ && lastFullscreen) {
+ return lastOrientation;
+ }
+ }
+ int or = wtoken.requestedOrientation;
+ // If this application is fullscreen, and didn't explicitly say
+ // to use the orientation behind it, then just take whatever
+ // orientation it has and ignores whatever is under it.
+ lastFullscreen = wtoken.appFullscreen;
+ if (lastFullscreen
+ && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ return or;
+ }
+ // If this application has requested an explicit orientation,
+ // then use it.
+ if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
+ or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
+ or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
+ or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
+ or == ActivityInfo.SCREEN_ORIENTATION_USER) {
+ return or;
+ }
+ findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
+ }
+ return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
public Configuration updateOrientationFromAppTokens(
@@ -3053,81 +3055,75 @@ public class WindowManagerService extends IWindowManager.Stub
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
- Configuration config;
+ Configuration config = null;
long ident = Binder.clearCallingIdentity();
- config = updateOrientationFromAppTokensUnchecked(currentConfig,
- freezeThisOneIfNeeded);
- Binder.restoreCallingIdentity(ident);
- return config;
- }
-
- Configuration updateOrientationFromAppTokensUnchecked(
- Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
- Configuration config;
+
synchronized(mWindowMap) {
- config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
- if (config != null) {
- mLayoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ if (updateOrientationFromAppTokensLocked()) {
+ if (freezeThisOneIfNeeded != null) {
+ AppWindowToken wtoken = findAppWindowToken(
+ freezeThisOneIfNeeded);
+ if (wtoken != null) {
+ startAppFreezingScreenLocked(wtoken,
+ ActivityInfo.CONFIG_ORIENTATION);
+ }
+ }
+ config = computeNewConfigurationLocked();
+
+ } else if (currentConfig != null) {
+ // No obvious action we need to take, but if our current
+ // state mismatches the activity maanager's, update it
+ mTempConfiguration.setToDefaults();
+ if (computeNewConfigurationLocked(mTempConfiguration)) {
+ if (currentConfig.diff(mTempConfiguration) != 0) {
+ mWaitingForConfig = true;
+ mLayoutNeeded = true;
+ startFreezingDisplayLocked();
+ config = new Configuration(mTempConfiguration);
+ }
+ }
}
}
+
+ Binder.restoreCallingIdentity(ident);
return config;
}
/*
+ * Determine the new desired orientation of the display, returning
+ * a non-null new Configuration if it has changed from the current
+ * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
+ * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
+ * SCREEN. This will typically be done for you if you call
+ * sendNewConfiguration().
+ *
* The orientation is computed from non-application windows first. If none of
* the non-application windows specify orientation, the orientation is computed from
* application tokens.
* @see android.view.IWindowManager#updateOrientationFromAppTokens(
* android.os.IBinder)
*/
- Configuration updateOrientationFromAppTokensLocked(
- Configuration appConfig, IBinder freezeThisOneIfNeeded) {
+ boolean updateOrientationFromAppTokensLocked() {
boolean changed = false;
long ident = Binder.clearCallingIdentity();
try {
int req = computeForcedAppOrientationLocked();
if (req != mForcedAppOrientation) {
- changed = true;
mForcedAppOrientation = req;
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
- }
-
- if (changed) {
- changed = setRotationUncheckedLocked(
- WindowManagerPolicy.USE_LAST_ROTATION,
- mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE));
- if (changed) {
- if (freezeThisOneIfNeeded != null) {
- AppWindowToken wtoken = findAppWindowToken(
- freezeThisOneIfNeeded);
- if (wtoken != null) {
- startAppFreezingScreenLocked(wtoken,
- ActivityInfo.CONFIG_ORIENTATION);
- }
- }
- return computeNewConfigurationLocked();
+ if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
+ mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
+ changed = true;
}
}
- // No obvious action we need to take, but if our current
- // state mismatches the activity maanager's, update it
- if (appConfig != null) {
- mTempConfiguration.setToDefaults();
- if (computeNewConfigurationLocked(mTempConfiguration)) {
- if (appConfig.diff(mTempConfiguration) != 0) {
- return new Configuration(mTempConfiguration);
- }
- }
- }
+ return changed;
} finally {
Binder.restoreCallingIdentity(ident);
}
-
- return null;
}
int computeForcedAppOrientationLocked() {
@@ -3138,6 +3134,19 @@ public class WindowManagerService extends IWindowManager.Stub
return req;
}
+ public void setNewConfiguration(Configuration config) {
+ if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+ "setNewConfiguration()")) {
+ throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+ }
+
+ synchronized(mWindowMap) {
+ mCurConfiguration = new Configuration(config);
+ mWaitingForConfig = false;
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ }
+
public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppOrientation()")) {
@@ -3648,9 +3657,7 @@ public class WindowManagerService extends IWindowManager.Stub
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
}
- if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
- stopFreezingDisplayLocked();
- }
+ stopFreezingDisplayLocked();
}
}
}
@@ -4403,20 +4410,21 @@ public class WindowManagerService extends IWindowManager.Stub
changed = setRotationUncheckedLocked(rotation, animFlags);
}
- if (changed) {
- sendNewConfiguration();
- synchronized(mWindowMap) {
- mLayoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
- }
- } else if (alwaysSendConfiguration) {
- //update configuration ignoring orientation change
+ if (changed || alwaysSendConfiguration) {
sendNewConfiguration();
}
Binder.restoreCallingIdentity(origId);
}
+ /**
+ * Apply a new rotation to the screen, respecting the requests of
+ * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
+ * re-evaluate the desired rotation.
+ *
+ * Returns null if the rotation has been changed. In this case YOU
+ * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
+ */
public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
boolean changed;
if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
@@ -4442,6 +4450,8 @@ public class WindowManagerService extends IWindowManager.Stub
mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
2000);
+ mWaitingForConfig = true;
+ mLayoutNeeded = true;
startFreezingDisplayLocked();
Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
mQueue.setOrientation(rotation);
@@ -6707,7 +6717,8 @@ public class WindowManagerService extends IWindowManager.Stub
long ident = Binder.clearCallingIdentity();
try {
return mPolicy.performHapticFeedbackLw(
- windowForClientLocked(this, window), effectId, always);
+ windowForClientLocked(this, window, true),
+ effectId, always);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -6718,7 +6729,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
+ setWindowWallpaperPositionLocked(
+ windowForClientLocked(this, window, true),
x, y, xStep, yStep);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6736,7 +6748,7 @@ public class WindowManagerService extends IWindowManager.Stub
long ident = Binder.clearCallingIdentity();
try {
return sendWindowWallpaperCommandLocked(
- windowForClientLocked(this, window),
+ windowForClientLocked(this, window, true),
action, x, y, z, extras, sync);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6852,6 +6864,10 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState mNextOutsideTouch;
+ int mLayoutSeq = -1;
+
+ Configuration mConfiguration = null;
+
// Actual frame shown on-screen (may be modified by animation)
final Rect mShownFrame = new Rect();
final Rect mLastShownFrame = new Rect();
@@ -7980,7 +7996,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void binderDied() {
try {
synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(mSession, mClient);
+ WindowState win = windowForClientLocked(mSession, mClient, false);
Log.i(TAG, "WIN DEATH: " + win);
if (win != null) {
removeWindowLocked(mSession, win);
@@ -8056,8 +8072,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
void dump(PrintWriter pw, String prefix) {
- StringBuilder sb = new StringBuilder(64);
-
pw.print(prefix); pw.print("mSession="); pw.print(mSession);
pw.print(" mClient="); pw.println(mClient.asBinder());
pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
@@ -8105,7 +8119,8 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
}
pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
- pw.print(" h="); pw.println(mRequestedHeight);
+ pw.print(" h="); pw.print(mRequestedHeight);
+ pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
if (mXOffset != 0 || mYOffset != 0) {
pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
pw.print(" y="); pw.println(mYOffset);
@@ -8119,6 +8134,7 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
}
+ pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
pw.print(prefix); pw.print("mShownFrame=");
mShownFrame.printShortString(pw);
pw.print(" last="); mLastShownFrame.printShortString(pw);
@@ -8693,7 +8709,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int FORCE_GC = 15;
public static final int ENABLE_SCREEN = 16;
public static final int APP_FREEZE_TIMEOUT = 17;
- public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18;
+ public static final int SEND_NEW_CONFIGURATION = 18;
private Session mLastReportedHold;
@@ -9019,10 +9035,9 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
- if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
- sendNewConfiguration();
- }
+ case SEND_NEW_CONFIGURATION: {
+ removeMessages(SEND_NEW_CONFIGURATION);
+ sendNewConfiguration();
break;
}
@@ -9064,23 +9079,33 @@ public class WindowManagerService extends IWindowManager.Stub
// Internals
// -------------------------------------------------------------
- final WindowState windowForClientLocked(Session session, IWindow client) {
- return windowForClientLocked(session, client.asBinder());
+ final WindowState windowForClientLocked(Session session, IWindow client,
+ boolean throwOnError) {
+ return windowForClientLocked(session, client.asBinder(), throwOnError);
}
- final WindowState windowForClientLocked(Session session, IBinder client) {
+ final WindowState windowForClientLocked(Session session, IBinder client,
+ boolean throwOnError) {
WindowState win = mWindowMap.get(client);
if (localLOGV) Log.v(
TAG, "Looking up client " + client + ": " + win);
if (win == null) {
- RuntimeException ex = new RuntimeException();
- Log.w(TAG, "Requested window " + client + " does not exist", ex);
+ RuntimeException ex = new IllegalArgumentException(
+ "Requested window " + client + " does not exist");
+ if (throwOnError) {
+ throw ex;
+ }
+ Log.w(TAG, "Failed looking up window", ex);
return null;
}
if (session != null && win.mSession != session) {
- RuntimeException ex = new RuntimeException();
- Log.w(TAG, "Requested window " + client + " is in session " +
- win.mSession + ", not " + session, ex);
+ RuntimeException ex = new IllegalArgumentException(
+ "Requested window " + client + " is in session " +
+ win.mSession + ", not " + session);
+ if (throwOnError) {
+ throw ex;
+ }
+ Log.w(TAG, "Failed looking up window", ex);
return null;
}
@@ -9183,6 +9208,13 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (mWaitingForConfig) {
+ // Our configuration has changed (most likely rotation), but we
+ // don't yet have the complete configuration to report to
+ // applications. Don't do any window layout until we have it.
+ return;
+ }
+
boolean recoveringMemory = false;
if (mForceRemoves != null) {
recoveringMemory = true;
@@ -9249,6 +9281,10 @@ public class WindowManagerService extends IWindowManager.Stub
while (mLayoutNeeded) {
mPolicy.beginLayoutLw(dw, dh);
+ int seq = mLayoutSeq+1;
+ if (seq < 0) seq = 0;
+ mLayoutSeq = seq;
+
// First perform layout of any root windows (not attached
// to another window).
int topAttached = -1;
@@ -9266,7 +9302,7 @@ public class WindowManagerService extends IWindowManager.Stub
|| win.mAttachedHidden
|| win.mExiting || win.mDestroying;
- if (win.mLayoutAttached) {
+ if (!win.mLayoutAttached) {
if (DEBUG_LAYOUT) Log.v(TAG, "First pass " + win
+ ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
+ " mLayoutAttached=" + win.mLayoutAttached);
@@ -9286,6 +9322,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!gone || !win.mHaveFrame) {
if (!win.mLayoutAttached) {
mPolicy.layoutWindowLw(win, win.mAttrs, null);
+ win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Log.v(TAG, "-> mFrame="
+ win.mFrame + " mContainingFrame="
+ win.mContainingFrame + " mDisplayFrame="
@@ -9316,6 +9353,7 @@ public class WindowManagerService extends IWindowManager.Stub
if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
|| !win.mHaveFrame) {
mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
+ win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Log.v(TAG, "-> mFrame="
+ win.mFrame + " mContainingFrame="
+ win.mContainingFrame + " mDisplayFrame="
@@ -9336,11 +9374,8 @@ public class WindowManagerService extends IWindowManager.Stub
Log.w(TAG, "Layout repeat aborted after too many iterations");
mLayoutNeeded = false;
if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
- Configuration newConfig = updateOrientationFromAppTokensLocked(
- null, null);
- if (newConfig != null) {
- mLayoutNeeded = true;
- mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+ if (updateOrientationFromAppTokensLocked()) {
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
} else {
@@ -9349,10 +9384,8 @@ public class WindowManagerService extends IWindowManager.Stub
repeats++;
if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Log.v(TAG, "Computing new config from layout");
- Configuration newConfig = updateOrientationFromAppTokensLocked(
- null, null);
- if (newConfig != null) {
- mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+ if (updateOrientationFromAppTokensLocked()) {
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
}
@@ -9996,14 +10029,22 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
- if (!w.mAppFreezing) {
+ if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
w.mContentInsetsChanged =
!w.mLastContentInsets.equals(w.mContentInsets);
w.mVisibleInsetsChanged =
!w.mLastVisibleInsets.equals(w.mVisibleInsets);
+ boolean configChanged =
+ w.mConfiguration != mCurConfiguration
+ && (w.mConfiguration == null
+ || mCurConfiguration.diff(w.mConfiguration) != 0);
+ if (localLOGV) Log.v(TAG, "Resizing " + w
+ + ": configChanged=" + configChanged
+ + " last=" + w.mLastFrame + " frame=" + w.mFrame);
if (!w.mLastFrame.equals(w.mFrame)
|| w.mContentInsetsChanged
- || w.mVisibleInsetsChanged) {
+ || w.mVisibleInsetsChanged
+ || configChanged) {
w.mLastFrame.set(w.mFrame);
w.mLastContentInsets.set(w.mContentInsets);
w.mLastVisibleInsets.set(w.mVisibleInsets);
@@ -10014,7 +10055,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION) Log.v(TAG,
"Resizing while display frozen: " + w);
w.mOrientationChanging = true;
- if (mWindowsFreezingScreen) {
+ if (!mWindowsFreezingScreen) {
mWindowsFreezingScreen = true;
// XXX should probably keep timeout from
// when we first froze the display.
@@ -10327,9 +10368,7 @@ public class WindowManagerService extends IWindowManager.Stub
mWindowsFreezingScreen = false;
mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
}
- if (mAppsFreezingScreen == 0) {
- stopFreezingDisplayLocked();
- }
+ stopFreezingDisplayLocked();
}
i = mResizingWindows.size();
@@ -10340,9 +10379,20 @@ public class WindowManagerService extends IWindowManager.Stub
try {
if (DEBUG_ORIENTATION) Log.v(TAG, "Reporting new frame to "
+ win + ": " + win.mFrame);
+ boolean configChanged =
+ win.mConfiguration != mCurConfiguration
+ && (win.mConfiguration == null
+ || mCurConfiguration.diff(win.mConfiguration) != 0);
+ win.mConfiguration = mCurConfiguration;
+ if (DEBUG_ORIENTATION && configChanged) {
+ Log.i(TAG, "Sending new config to window " + win + ": "
+ + win.mFrame.width() + "x" + win.mFrame.height()
+ + " / " + win.mConfiguration);
+ }
win.mClient.resized(win.mFrame.width(),
win.mFrame.height(), win.mLastContentInsets,
- win.mLastVisibleInsets, win.mDrawPending);
+ win.mLastVisibleInsets, win.mDrawPending,
+ configChanged ? win.mConfiguration : null);
win.mContentInsetsChanged = false;
win.mVisibleInsetsChanged = false;
} catch (RemoteException e) {
@@ -10732,6 +10782,10 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+ return;
+ }
+
mDisplayFrozen = false;
mH.removeMessages(H.APP_FREEZE_TIMEOUT);
if (PROFILE_ORIENTATION) {
@@ -10921,7 +10975,9 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
}
- pw.print(" mInTouchMode="); pw.println(mInTouchMode);
+ pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
+ pw.print(" mInTouchMode="); pw.print(mInTouchMode);
+ pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
pw.print(" mSystemBooted="); pw.print(mSystemBooted);
pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
@@ -10939,7 +10995,8 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
- pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
+ pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
+ pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
pw.print(" mRotation="); pw.print(mRotation);
pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 47a58cf..45c3f00 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -766,6 +766,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
Configuration mConfiguration = new Configuration();
/**
+ * Current sequencing integer of the configuration, for skipping old
+ * configurations.
+ */
+ int mConfigurationSeq = 0;
+
+ /**
* Hardware-reported OpenGLES version.
*/
final int GL_ES_VERSION;
@@ -2662,20 +2668,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next : null);
if (config != null) {
- /*
- * Explicitly restore the locale to the one from the
- * old configuration, since the one that comes back from
- * the window manager has the default (boot) locale.
- *
- * It looks like previously the locale picker only worked
- * by coincidence: usually it would do its setting of
- * the locale after the activity transition, so it didn't
- * matter that this lost it. With the synchronized
- * block now keeping them from happening at the same time,
- * this one always would happen second and undo what the
- * locale picker had just done.
- */
- config.locale = mConfiguration.locale;
next.frozenBeforeDestroy = true;
}
updated = updateConfigurationLocked(config, next);
@@ -8347,7 +8339,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mAlwaysFinishActivities = alwaysFinishActivities;
// This happens before any activities are started, so we can
// change mConfiguration in-place.
+ mConfiguration.locale = Locale.getDefault();
mConfiguration.updateFrom(configuration);
+ mConfigurationSeq = mConfiguration.seq = 1;
if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
}
}
@@ -13090,6 +13084,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
values.userSetLocale);
}
+ mConfigurationSeq++;
+ if (mConfigurationSeq <= 0) {
+ mConfigurationSeq = 1;
+ }
+ newConfig.seq = mConfigurationSeq;
mConfiguration = newConfig;
Log.i(TAG, "Config changed: " + newConfig);
@@ -13146,6 +13145,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ if (values != null && mWindowManager != null) {
+ mWindowManager.setNewConfiguration(mConfiguration);
+ }
+
return kept;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 990498f..41d9f9d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -30,6 +30,7 @@ import com.android.ninepatch.NinePatch;
import com.android.tools.layoutlib.create.MethodAdapter;
import com.android.tools.layoutlib.create.OverrideMethod;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -1133,7 +1134,7 @@ public final class Bridge implements ILayoutBridge {
}
@SuppressWarnings("unused")
- public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4)
+ public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
throws RemoteException {
// pass for now.
}