Merge "Suppress AutoCancelTest."
diff --git a/Android.mk b/Android.mk
index e84b683..505b12d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -173,6 +173,7 @@
core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
core/java/android/hardware/input/IInputManager.aidl \
core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
+ core/java/android/hardware/input/ITabletModeChangedListener.aidl \
core/java/android/hardware/location/IActivityRecognitionHardware.aidl \
core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl \
core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl \
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 2406985..933f98d 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
@@ -59,6 +60,13 @@
public static final String KEY_PACKAGE_NAME = "android:activity.packageName";
/**
+ * The bounds that the activity should be started in. Set to null explicitly
+ * for full screen. If the key is not found, previous bounds will be preserved.
+ * @hide
+ */
+ public static final String KEY_BOUNDS = "android:activity.bounds";
+
+ /**
* Type of animation that arguments specify.
* @hide
*/
@@ -163,6 +171,8 @@
public static final int ANIM_CLIP_REVEAL = 11;
private String mPackageName;
+ private boolean mHasBounds;
+ private Rect mBounds;
private int mAnimationType = ANIM_NONE;
private int mCustomEnterResId;
private int mCustomExitResId;
@@ -631,6 +641,10 @@
} catch (RuntimeException e) {
Slog.w(TAG, e);
}
+ mHasBounds = opts.containsKey(KEY_BOUNDS);
+ if (mHasBounds) {
+ mBounds = opts.getParcelable(KEY_BOUNDS);
+ }
mAnimationType = opts.getInt(KEY_ANIM_TYPE);
switch (mAnimationType) {
case ANIM_CUSTOM:
@@ -677,11 +691,28 @@
}
/** @hide */
+ public ActivityOptions setBounds(Rect bounds) {
+ mHasBounds = true;
+ mBounds = bounds;
+ return this;
+ }
+
+ /** @hide */
public String getPackageName() {
return mPackageName;
}
/** @hide */
+ public boolean hasBounds() {
+ return mHasBounds;
+ }
+
+ /** @hide */
+ public Rect getBounds(){
+ return mBounds;
+ }
+
+ /** @hide */
public int getAnimationType() {
return mAnimationType;
}
@@ -867,6 +898,9 @@
if (mPackageName != null) {
b.putString(KEY_PACKAGE_NAME, mPackageName);
}
+ if (mHasBounds) {
+ b.putParcelable(KEY_BOUNDS, mBounds);
+ }
b.putInt(KEY_ANIM_TYPE, mAnimationType);
if (mUsageTimeReport != null) {
b.putParcelable(KEY_USAGE_TIME_REPORT, mUsageTimeReport);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e15ba74..67dee7f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4593,27 +4593,6 @@
}
updateDefaultDensity();
- final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
- if (!Process.isIsolated()) {
- final File cacheDir = appContext.getCacheDir();
-
- if (cacheDir != null) {
- // Provide a usable directory for temporary files
- System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
- } else {
- Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property due to missing cache directory");
- }
-
- // Use codeCacheDir to store generated/compiled graphics code
- final File codeCacheDir = appContext.getCodeCacheDir();
- if (codeCacheDir != null) {
- setupGraphicsSupport(data.info, codeCacheDir);
- } else {
- Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
- }
- }
-
-
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
@@ -4685,29 +4664,28 @@
/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
*/
- IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
// In pre-boot mode (doing initial launch to collect password), not
// all system is up. This includes the connectivity service, so don't
// crash if we can't get it.
- IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+ final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {}
}
+ // Instrumentation info affects the class loader, so load it before
+ // setting up the app context.
+ final InstrumentationInfo ii;
if (data.instrumentationName != null) {
- InstrumentationInfo ii = null;
try {
- ii = appContext.getPackageManager().
- getInstrumentationInfo(data.instrumentationName, 0);
+ ii = new ApplicationPackageManager(null, getPackageManager())
+ .getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
- }
- if (ii == null) {
throw new RuntimeException(
- "Unable to find instrumentation info for: "
- + data.instrumentationName);
+ "Unable to find instrumentation info for: " + data.instrumentationName);
}
mInstrumentationPackageName = ii.packageName;
@@ -4717,13 +4695,32 @@
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
+ } else {
+ ii = null;
+ }
- // The app context's info was created against this thread, but
- // the class loader may have already been loaded and cached with
- // outdated paths. Clear it so we can load it again using the
- // instrumentation paths.
- data.info.clearClassLoader();
+ final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
+ if (!Process.isIsolated()) {
+ final File cacheDir = appContext.getCacheDir();
+ if (cacheDir != null) {
+ // Provide a usable directory for temporary files
+ System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+ } else {
+ Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
+ + "due to missing cache directory");
+ }
+ // Use codeCacheDir to store generated/compiled graphics code
+ final File codeCacheDir = appContext.getCodeCacheDir();
+ if (codeCacheDir != null) {
+ setupGraphicsSupport(data.info, codeCacheDir);
+ } else {
+ Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
+ }
+ }
+
+ // Continue loading instrumentation.
+ if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
@@ -4732,13 +4729,13 @@
instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
- LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
+
+ final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
- ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
+ final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
-
- java.lang.ClassLoader cl = instrContext.getClassLoader();
+ final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
@@ -4747,18 +4744,17 @@
+ data.instrumentationName + ": " + e.toString(), e);
}
- mInstrumentation.init(this, instrContext, appContext,
- new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
- data.instrumentationUiAutomationConnection);
+ final ComponentName component = new ComponentName(ii.packageName, ii.name);
+ mInstrumentation.init(this, instrContext, appContext, component,
+ data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
- File file = new File(mProfiler.profileFile);
+ final File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
-
} else {
mInstrumentation = new Instrumentation();
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 3b1c60b..c2bf28a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -255,13 +255,6 @@
return ai.sharedLibraryFiles;
}
- /** @hide */
- public void clearClassLoader() {
- synchronized (this) {
- mClassLoader = null;
- }
- }
-
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader != null) {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 3ecbaa0..927c02f 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1049,7 +1049,7 @@
}
fixUpLocaleList();
delta.fixUpLocaleList();
- if (!mLocaleList.equals(delta.mLocaleList)) {
+ if (!delta.mLocaleList.isEmpty() && !mLocaleList.equals(delta.mLocaleList)) {
changed |= ActivityInfo.CONFIG_LOCALE;
changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 465d142..c8b45c7 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -19,6 +19,7 @@
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.TouchCalibration;
import android.os.IBinder;
import android.view.InputDevice;
@@ -60,6 +61,9 @@
// Registers an input devices changed listener.
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
+ // Registers a tablet mode change listener
+ void registerTabletModeChangedListener(ITabletModeChangedListener listener);
+
// Input device vibrator control.
void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
void cancelVibrate(int deviceId, IBinder token);
diff --git a/core/java/android/hardware/input/ITabletModeChangedListener.aidl b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
new file mode 100644
index 0000000..a8559a7
--- /dev/null
+++ b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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.hardware.input;
+
+/** @hide */
+interface ITabletModeChangedListener {
+ /* Called when the device enters or exits tablet mode. */
+ oneway void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 4292050..bae5757 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
package android.hardware.input;
+import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import android.annotation.SdkConstant;
@@ -29,6 +30,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -38,6 +40,7 @@
import android.view.InputEvent;
import java.util.ArrayList;
+import java.util.List;
/**
* Provides information about input devices and available key layouts.
@@ -67,6 +70,11 @@
private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
new ArrayList<InputDeviceListenerDelegate>();
+ // Guarded by mTabletModeLock
+ private final Object mTabletModeLock = new Object();
+ private TabletModeChangedListener mTabletModeChangedListener;
+ private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
+
/**
* Broadcast Action: Query available keyboard layouts.
* <p>
@@ -332,6 +340,72 @@
}
/**
+ * Register a tablet mode changed listener.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @hide
+ */
+ public void registerOnTabletModeChangedListener(
+ OnTabletModeChangedListener listener, Handler handler) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ synchronized (mTabletModeLock) {
+ if (mOnTabletModeChangedListeners == null) {
+ initializeTabletModeListenerLocked();
+ }
+ int idx = findOnTabletModeChangedListenerLocked(listener);
+ if (idx < 0) {
+ OnTabletModeChangedListenerDelegate d =
+ new OnTabletModeChangedListenerDelegate(listener, handler);
+ mOnTabletModeChangedListeners.add(d);
+ }
+ }
+ }
+
+ /**
+ * Unregister a tablet mode changed listener.
+ *
+ * @param listener The listener to unregister.
+ * @hide
+ */
+ public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ synchronized (mTabletModeLock) {
+ int idx = findOnTabletModeChangedListenerLocked(listener);
+ if (idx >= 0) {
+ OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
+ d.removeCallbacksAndMessages(null);
+ }
+ }
+ }
+
+ private void initializeTabletModeListenerLocked() {
+ final TabletModeChangedListener listener = new TabletModeChangedListener();
+ try {
+ mIm.registerTabletModeChangedListener(listener);
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Could not register tablet mode changed listener", ex);
+ }
+ mTabletModeChangedListener = listener;
+ mOnTabletModeChangedListeners = new ArrayList<>();
+ }
+
+ private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
+ final int N = mOnTabletModeChangedListeners.size();
+ for (int i = 0; i < N; i++) {
+ if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
* Gets information about all supported keyboard layouts.
* <p>
* The input manager consults the built-in keyboard layouts as well
@@ -770,6 +844,22 @@
return false;
}
+
+ private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ if (DEBUG) {
+ Log.d(TAG, "Received tablet mode changed: "
+ + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
+ }
+ synchronized (mTabletModeLock) {
+ final int N = mOnTabletModeChangedListeners.size();
+ for (int i = 0; i < N; i++) {
+ OnTabletModeChangedListenerDelegate listener =
+ mOnTabletModeChangedListeners.get(i);
+ listener.sendTabletModeChanged(whenNanos, inTabletMode);
+ }
+ }
+ }
+
/**
* Gets a vibrator service associated with an input device, assuming it has one.
* @return The vibrator, never null.
@@ -839,6 +929,57 @@
}
}
+ /** @hide */
+ public interface OnTabletModeChangedListener {
+ /**
+ * Called whenever the device goes into or comes out of tablet mode.
+ *
+ * @param whenNanos The time at which the device transitioned into or
+ * out of tablet mode. This is given in nanoseconds in the
+ * {@link SystemClock#uptimeMillis} time base.
+ */
+ void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+ }
+
+ private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
+ @Override
+ public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
+ }
+ }
+
+ private static final class OnTabletModeChangedListenerDelegate extends Handler {
+ private static final int MSG_TABLET_MODE_CHANGED = 0;
+
+ public final OnTabletModeChangedListener mListener;
+
+ public OnTabletModeChangedListenerDelegate(
+ OnTabletModeChangedListener listener, Handler handler) {
+ super(handler != null ? handler.getLooper() : Looper.myLooper());
+ mListener = listener;
+ }
+
+ public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+ args.argi2 = (int) (whenNanos >> 32);
+ args.arg1 = (Boolean) inTabletMode;
+ obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_TABLET_MODE_CHANGED:
+ SomeArgs args = (SomeArgs) msg.obj;
+ long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
+ boolean inTabletMode = (boolean) args.arg1;
+ mListener.onTabletModeChanged(whenNanos, inTabletMode);
+ break;
+ }
+ }
+ }
+
private final class InputDeviceVibrator extends Vibrator {
private final int mDeviceId;
private final Binder mToken;
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index e77b862..72971e8 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -199,10 +199,7 @@
} else {
userId = UserHandle.myUserId();
}
- IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- IAccessibilityManager service = iBinder == null
- ? null : IAccessibilityManager.Stub.asInterface(iBinder);
- sInstance = new AccessibilityManager(context, service, userId);
+ sInstance = new AccessibilityManager(context, null, userId);
}
}
return sInstance;
@@ -219,10 +216,9 @@
*/
public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
mHandler = new MyHandler(context.getMainLooper());
- mService = service;
mUserId = userId;
synchronized (mLock) {
- tryConnectToServiceLocked();
+ tryConnectToServiceLocked(service);
}
}
@@ -612,17 +608,20 @@
private IAccessibilityManager getServiceLocked() {
if (mService == null) {
- tryConnectToServiceLocked();
+ tryConnectToServiceLocked(null);
}
return mService;
}
- private void tryConnectToServiceLocked() {
- IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- if (iBinder == null) {
- return;
+ private void tryConnectToServiceLocked(IAccessibilityManager service) {
+ if (service == null) {
+ IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+ if (iBinder == null) {
+ return;
+ }
+ service = IAccessibilityManager.Stub.asInterface(iBinder);
}
- IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
+
try {
final int stateFlags = service.addClient(mClient, mUserId);
setStateLocked(stateFlags);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 051845f..d96a909 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -232,7 +232,7 @@
public void reportFailedPasswordAttempt(int userId) {
getDevicePolicyManager().reportFailedPasswordAttempt(userId);
getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
- requireCredentialEntry(userId);
+ requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId);
}
public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1290,10 +1290,17 @@
*/
public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
+ /**
+ * Some authentication is required because the user has entered a wrong credential.
+ */
+ public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10;
+
public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
- final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
+ private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
+ | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
+ private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
private final H mHandler;
public StrongAuthTracker() {
@@ -1332,7 +1339,7 @@
* current strong authentication requirements.
*/
public boolean isFingerprintAllowedForUser(int userId) {
- return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
+ return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
}
/**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b0621e9..d6657dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2069,6 +2069,12 @@
<permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
android:protectionLevel="signature" />
+ <!-- Allows an application to monitor changes in tablet mode.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.TABLET_MODE_LISTENER"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to request installing packages. Apps
targeting APIs greater than 22 must hold this permission in
order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 2615a28..e6d3158 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -28,7 +28,6 @@
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
@@ -37,7 +36,6 @@
import java.util.List;
/** Unit test for SettingsProvider. */
-@Suppress // Failing.
public class SettingsProviderTest extends AndroidTestCase {
@MediumTest
public void testNameValueCache() {
@@ -53,84 +51,108 @@
assertEquals(1, r.delete(Settings.Secure.getUriFor("test_service"), null, null));
assertEquals(null, Settings.Secure.getString(r, "test_service"));
- // Try all the same things in the System table
- Settings.System.putString(r, "test_setting", "Value");
- assertEquals("Value", Settings.System.getString(r, "test_setting"));
-
- Settings.System.putString(r, "test_setting", "New");
- assertEquals("New", Settings.System.getString(r, "test_setting"));
-
- assertEquals(1, r.delete(Settings.System.getUriFor("test_setting"), null, null));
- assertEquals(null, Settings.System.getString(r, "test_setting"));
+ // Apps should not be able to use System settings.
+ try {
+ Settings.System.putString(r, "test_setting", "Value");
+ fail("IllegalArgumentException expected");
+ } catch (java.lang.IllegalArgumentException e) {
+ // expected
+ }
}
@MediumTest
- public void testRowNameContentUri() {
+ public void testRowNameContentUriForSecure() {
+ final String testKey = "testRowNameContentUriForSecure";
+ final String testValue = "testValue";
+ final String secondTestValue = "testValueNew";
+
+ try {
+ testRowNameContentUri(Settings.Secure.CONTENT_URI, Settings.Secure.NAME,
+ Settings.Secure.VALUE, testKey, testValue, secondTestValue);
+ } finally {
+ // clean up
+ Settings.Secure.putString(getContext().getContentResolver(), testKey, null);
+ }
+ }
+
+ @MediumTest
+ public void testRowNameContentUriForSystem() {
+ final String testKey = Settings.System.VIBRATE_ON;
+ assertTrue("Settings.System.PUBLIC_SETTINGS cannot be empty. We need to use one of it"
+ + " for testing. Only settings key in this collection will be accepted by the"
+ + " framework.", Settings.System.PUBLIC_SETTINGS.contains(testKey));
+ final String testValue = "0";
+ final String secondTestValue = "1";
+ final String oldValue =
+ Settings.System.getString(getContext().getContentResolver(), testKey);
+
+ try {
+ testRowNameContentUri(Settings.System.CONTENT_URI, Settings.System.NAME,
+ Settings.System.VALUE, testKey, testValue, secondTestValue);
+ } finally {
+ // restore old value
+ if (oldValue != null) {
+ Settings.System.putString(getContext().getContentResolver(), testKey, oldValue);
+ }
+ }
+ }
+
+ private void testRowNameContentUri(Uri table, String nameField, String valueField,
+ String testKey, String testValue, String secondTestValue) {
ContentResolver r = getContext().getContentResolver();
- assertEquals("content://settings/system/test_setting",
- Settings.System.getUriFor("test_setting").toString());
- assertEquals("content://settings/secure/test_service",
- Settings.Secure.getUriFor("test_service").toString());
+ ContentValues v = new ContentValues();
+ v.put(nameField, testKey);
+ v.put(valueField, testValue);
- // These tables use the row name (not ID) as their content URI.
- Uri tables[] = { Settings.System.CONTENT_URI, Settings.Secure.CONTENT_URI };
- for (Uri table : tables) {
- ContentValues v = new ContentValues();
- v.put(Settings.System.NAME, "test_key");
- v.put(Settings.System.VALUE, "Test");
- Uri uri = r.insert(table, v);
- assertEquals(table.toString() + "/test_key", uri.toString());
+ r.insert(table, v);
+ Uri uri = Uri.parse(table.toString() + "/" + testKey);
- // Query with a specific URI and no WHERE clause succeeds.
- Cursor c = r.query(uri, null, null, null, null);
- try {
- assertTrue(c.moveToNext());
- assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME)));
- assertEquals("Test", c.getString(c.getColumnIndex(Settings.System.VALUE)));
- assertFalse(c.moveToNext());
- } finally {
- c.close();
- }
-
- // Query with a specific URI and a WHERE clause fails.
- try {
- r.query(uri, null, "1", null, null);
- fail("UnsupportedOperationException expected");
- } catch (UnsupportedOperationException e) {
- if (!e.toString().contains("WHERE clause")) throw e;
- }
-
- // Query with a tablewide URI and a WHERE clause succeeds.
- c = r.query(table, null, "name='test_key'", null, null);
- try {
- assertTrue(c.moveToNext());
- assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME)));
- assertEquals("Test", c.getString(c.getColumnIndex(Settings.System.VALUE)));
- assertFalse(c.moveToNext());
- } finally {
- c.close();
- }
-
- v = new ContentValues();
- v.put(Settings.System.VALUE, "Toast");
- assertEquals(1, r.update(uri, v, null, null));
-
- c = r.query(uri, null, null, null, null);
- try {
- assertTrue(c.moveToNext());
- assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME)));
- assertEquals("Toast", c.getString(c.getColumnIndex(Settings.System.VALUE)));
- assertFalse(c.moveToNext());
- } finally {
- c.close();
- }
-
- assertEquals(1, r.delete(uri, null, null));
+ // Query with a specific URI and no WHERE clause succeeds.
+ Cursor c = r.query(uri, null, null, null, null);
+ try {
+ assertTrue(c.moveToNext());
+ assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
+ assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
+ assertFalse(c.moveToNext());
+ } finally {
+ c.close();
}
- assertEquals(null, Settings.System.getString(r, "test_key"));
- assertEquals(null, Settings.Secure.getString(r, "test_key"));
+ // Query with a specific URI and a WHERE clause fails.
+ try {
+ r.query(uri, null, "1", null, null);
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // Query with a tablewide URI and a WHERE clause succeeds.
+ c = r.query(table, null, "name='" + testKey + "'", null, null);
+ try {
+ assertTrue(c.moveToNext());
+ assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
+ assertEquals(testValue, c.getString(c.getColumnIndex(valueField)));
+ assertFalse(c.moveToNext());
+ } finally {
+ c.close();
+ }
+
+ v = new ContentValues();
+ // NAME is still needed, although the uri should be specific enough. Why?
+ v.put(nameField, testKey);
+ v.put(valueField, secondTestValue);
+ assertEquals(1, r.update(uri, v, null, null));
+
+ c = r.query(uri, null, null, null, null);
+ try {
+ assertTrue(c.moveToNext());
+ assertEquals(testKey, c.getString(c.getColumnIndex(nameField)));
+ assertEquals(secondTestValue, c.getString(c.getColumnIndex(valueField)));
+ assertFalse(c.moveToNext());
+ } finally {
+ c.close();
+ }
}
@MediumTest
@@ -139,7 +161,7 @@
ContentResolver r = getContext().getContentResolver();
// Make sure there's an owner
- assertTrue(findUser(um, UserHandle.USER_OWNER));
+ assertTrue(findUser(um, UserHandle.USER_SYSTEM));
// create a new user to use for testing
UserInfo otherUser = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
@@ -148,21 +170,17 @@
assertNotSame("Current calling user id should not be the new guest user",
otherUser.id, UserHandle.getCallingUserId());
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "gps");
- Settings.Secure.putStringForUser(r,
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "network", otherUser.id);
+ final String testKey = "testSettingsChangeForOtherUser";
+ final String testValue1 = "value1";
+ final String testValue2 = "value2";
+ Settings.Secure.putString(r, testKey, testValue1);
+ Settings.Secure.putStringForUser(r, testKey, testValue2, otherUser.id);
- assertEquals("gps",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
- assertEquals("network", Settings.Secure.getStringForUser(
- r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, otherUser.id));
+ assertEquals(testValue1, Settings.Secure.getString(r, testKey));
+ assertEquals(testValue2, Settings.Secure.getStringForUser(r, testKey, otherUser.id));
assertNotSame("Current calling user id should not be the new guest user",
otherUser.id, UserHandle.getCallingUserId());
- Settings.Secure.setLocationProviderEnabledForUser(r, "network", false, otherUser.id);
- assertEquals("", Settings.Secure.getStringForUser(
- r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, otherUser.id));
-
} finally {
// Tidy up
um.removeUser(otherUser.id);
@@ -170,6 +188,7 @@
}
@MediumTest
+ @Suppress // Settings.Bookmarks uses a query format that's not supported now.
public void testRowNumberContentUri() {
ContentResolver r = getContext().getContentResolver();
@@ -196,47 +215,56 @@
public void testParseProviderList() {
ContentResolver r = getContext().getContentResolver();
- // Make sure we get out what we put in.
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- "test1,test2,test3");
- assertEquals(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED),
- "test1,test2,test3");
-
+ // We only accept "+value" and "-value"
// Test adding a value
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- "");
Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test1");
- assertEquals("test1",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test1"));
// Test adding a second value
Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test2");
- assertEquals("test1,test2",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test1"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test2"));
// Test adding a third value
Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test3");
- assertEquals("test1,test2,test3",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test1"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test2"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test3"));
// Test deleting the first value in a 3 item list
Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test1");
- assertEquals("test2,test3",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test1"));
// Test deleting the middle value in a 3 item list
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- "test1,test2,test3");
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test2");
- assertEquals("test1,test3",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test4");
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test2"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test3"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test4"));
+ Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test3");
+ assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test3"));
// Test deleting the last value in a 3 item list
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- "test1,test2,test3");
- Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test3");
- assertEquals("test1,test2",
- Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+ Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+test5");
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test2"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test4"));
+ assertTrue(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test5"));
+ Settings.Secure.putString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test5");
+ assertFalse(Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
+ .contains("test5"));
}
private boolean findUser(UserManager um, int userHandle) {
@@ -254,7 +282,7 @@
ContentResolver r = getContext().getContentResolver();
// Make sure there's an owner
- assertTrue(findUser(um, UserHandle.USER_OWNER));
+ assertTrue(findUser(um, UserHandle.USER_SYSTEM));
// create a new user to use for testing
UserInfo user = um.createUser("TestUser1", UserInfo.FLAG_GUEST);
@@ -266,12 +294,12 @@
final int SELF_VALUE = 40;
final int OTHER_VALUE = 27;
- Settings.System.putInt(r, TEST_KEY, SELF_VALUE);
- Settings.System.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id);
+ Settings.Secure.putInt(r, TEST_KEY, SELF_VALUE);
+ Settings.Secure.putIntForUser(r, TEST_KEY, OTHER_VALUE, user.id);
// Verify that they read back as intended
- int myValue = Settings.System.getInt(r, TEST_KEY, 0);
- int otherValue = Settings.System.getIntForUser(r, TEST_KEY, 0, user.id);
+ int myValue = Settings.Secure.getInt(r, TEST_KEY, 0);
+ int otherValue = Settings.Secure.getIntForUser(r, TEST_KEY, 0, user.id);
assertTrue("Running as user " + UserHandle.myUserId()
+ " and reading/writing as user " + user.id
+ ", expected to read " + SELF_VALUE + " but got " + myValue,
@@ -310,7 +338,8 @@
assertCanBeHandled(new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
- assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
+ //TODO: seems no one is using this anymore.
+// assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_SEARCH_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_SECURITY_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index e1975c9..521c74b 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -105,10 +105,12 @@
/**
* Sets whether this AnimationDrawable is visible.
* <p>
- * When the drawable becomes invisible, it will pause its animation. A
- * subsequent change to visible with <code>restart</code> set to true will
- * restart the animation from the first frame. If <code>restart</code> is
- * false, the animation will resume from the most recent frame.
+ * When the drawable becomes invisible, it will pause its animation. A subsequent change to
+ * visible with <code>restart</code> set to true will restart the animation from the
+ * first frame. If <code>restart</code> is false, the drawable will resume from the most recent
+ * frame. If the drawable has already reached the last frame, it will then loop back to the
+ * first frame, unless it's a one shot drawable (set through {@link #setOneShot(boolean)}),
+ * in which case, it will stay on the last frame.
*
* @param visible true if visible, false otherwise
* @param restart when visible, true to force the animation to restart
@@ -120,7 +122,7 @@
final boolean changed = super.setVisible(visible, restart);
if (visible) {
if (restart || changed) {
- boolean startFromZero = restart || !mRunning ||
+ boolean startFromZero = restart || (!mRunning && !mAnimationState.mOneShot) ||
mCurFrame >= mAnimationState.getChildCount();
setFrame(startFromZero ? 0 : mCurFrame, true, mAnimating);
}
@@ -131,7 +133,7 @@
}
/**
- * Starts the animation, looping if necessary. This method has no effect
+ * Starts the animation from the first frame, looping if necessary. This method has no effect
* if the animation is running.
* <p>
* <strong>Note:</strong> Do not call this in the
@@ -158,7 +160,7 @@
}
/**
- * Stops the animation. This method has no effect if the animation is not
+ * Stops the animation at the current frame. This method has no effect if the animation is not
* running.
*
* @see #isRunning()
@@ -169,6 +171,7 @@
mAnimating = false;
if (isRunning()) {
+ mCurFrame = 0;
unscheduleSelf(this);
}
}
@@ -196,7 +199,6 @@
@Override
public void unscheduleSelf(Runnable what) {
- mCurFrame = 0;
mRunning = false;
super.unscheduleSelf(what);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 4284f6f..30a5a47 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -339,7 +339,7 @@
}
handlePositionChanged(position, metaState);
- return false;
+ return true;
}
/**
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index cfc232c..b752c9b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1348,9 +1348,7 @@
*/
private void handleKeyguardReset() {
if (DEBUG) Log.d(TAG, "handleKeyguardReset");
- if (!isUnlockingWithFingerprintAllowed()) {
- updateFingerprintListeningState();
- }
+ updateFingerprintListeningState();
}
/**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5a14967..ee296d9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -109,7 +109,7 @@
static String dbNameForUser(final int userHandle) {
// The owner gets the unadorned db name;
- if (userHandle == UserHandle.USER_OWNER) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
return DATABASE_NAME;
} else {
// Place the database in the user-specific data tree so that it's
@@ -186,8 +186,8 @@
createSecureTable(db);
- // Only create the global table for the singleton 'owner' user
- if (mUserHandle == UserHandle.USER_OWNER) {
+ // Only create the global table for the singleton 'owner/system' user
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
createGlobalTable(db);
}
@@ -1252,7 +1252,7 @@
if (upgradeVersion == 82) {
// Move to per-user settings dbs
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
@@ -1306,7 +1306,7 @@
}
if (upgradeVersion == 84) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1331,7 +1331,7 @@
}
if (upgradeVersion == 85) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
// Fix up the migration, ignoring already-migrated elements, to snap up to
@@ -1348,7 +1348,7 @@
}
if (upgradeVersion == 86) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] settingsToMove = {
@@ -1367,7 +1367,7 @@
}
if (upgradeVersion == 87) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] settingsToMove = {
@@ -1386,7 +1386,7 @@
}
if (upgradeVersion == 88) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] settingsToMove = {
@@ -1432,7 +1432,7 @@
}
if (upgradeVersion == 89) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] prefixesToMove = {
@@ -1452,7 +1452,7 @@
}
if (upgradeVersion == 90) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] systemToGlobal = {
@@ -1485,7 +1485,7 @@
}
if (upgradeVersion == 91) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
// Move ringer mode from system to global settings
@@ -1505,7 +1505,7 @@
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+ " VALUES(?,?);");
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
// consider existing primary users to have made it through user setup
// if the globally-scoped device-provisioned bit is set
// (indicating they already made it through setup as primary)
@@ -1526,7 +1526,7 @@
if (upgradeVersion == 93) {
// Redo this step, since somehow it didn't work the first time for some users
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
// Migrate now-global settings
@@ -1547,7 +1547,7 @@
if (upgradeVersion == 94) {
// Add wireless charging started sound setting
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1565,7 +1565,7 @@
}
if (upgradeVersion == 95) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
try {
String[] settingsToMove = { Settings.Global.BUGREPORT_IN_POWER_MENU };
@@ -1584,7 +1584,7 @@
}
if (upgradeVersion == 97) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1613,7 +1613,7 @@
if (upgradeVersion == 100) {
// note: LOCK_SCREEN_SHOW_NOTIFICATIONS now handled in version 106
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1631,7 +1631,7 @@
}
if (upgradeVersion == 101) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1653,7 +1653,7 @@
try {
// The INSTALL_NON_MARKET_APPS setting is becoming per-user rather
// than device-global.
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
// In the owner user, the global table exists so we can migrate the
// entry from there to the secure table, preserving its value.
String[] globalToSecure = {
@@ -1693,7 +1693,7 @@
}
if (upgradeVersion < 105) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1719,7 +1719,7 @@
+ " VALUES(?,?);");
loadIntegerSetting(stmt, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
R.integer.def_lock_screen_show_notifications);
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
final int oldShow = getIntValueFromTable(db,
TABLE_GLOBAL, Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, -1);
if (oldShow >= 0) {
@@ -1741,7 +1741,7 @@
if (upgradeVersion < 107) {
// Add trusted sound setting
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1816,7 +1816,7 @@
if (upgradeVersion < 111) {
// reset ringer mode, so it doesn't force zen mode to follow
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1833,7 +1833,7 @@
}
if (upgradeVersion < 112) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
// When device name was added, we went with Manufacturer + Model, device name should
// actually be Model only.
// Update device name to Model if it wasn't modified by user.
@@ -1874,7 +1874,7 @@
// We skipped 114 to handle a merge conflict with the introduction of theater mode.
if (upgradeVersion < 115) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -1892,7 +1892,7 @@
}
if (upgradeVersion < 116) {
- if (mUserHandle == UserHandle.USER_OWNER) {
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
@@ -2066,7 +2066,7 @@
LockPatternUtils lpu = new LockPatternUtils(mContext);
List<LockPatternView.Cell> cellPattern =
LockPatternUtils.stringToPattern(lockPattern);
- lpu.saveLockPattern(cellPattern, null, UserHandle.USER_OWNER);
+ lpu.saveLockPattern(cellPattern, null, UserHandle.USER_SYSTEM);
} catch (IllegalArgumentException e) {
// Don't want corrupted lock pattern to hang the reboot process
}
@@ -2343,8 +2343,8 @@
private void loadSettings(SQLiteDatabase db) {
loadSystemSettings(db);
loadSecureSettings(db);
- // The global table only exists for the 'owner' user
- if (mUserHandle == UserHandle.USER_OWNER) {
+ // The global table only exists for the 'owner/system' user
+ if (mUserHandle == UserHandle.USER_SYSTEM) {
loadGlobalSettings(db);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 952b220..1d71346 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -123,7 +123,8 @@
}
if (sBroadcastOnRestore.contains(name)) {
- oldValue = table.lookup(cr, name, UserHandle.USER_OWNER);
+ // TODO: http://b/22388012
+ oldValue = table.lookup(cr, name, UserHandle.USER_SYSTEM);
sendBroadcast = true;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 73971ad..8b1caf9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -18,7 +18,7 @@
import android.Manifest;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
+import android.app.AppGlobals;
import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
@@ -27,6 +27,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -47,6 +48,7 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -208,13 +210,13 @@
private volatile UserManager mUserManager;
// We have to call in the package manager with no lock held,
- private volatile PackageManager mPackageManager;
+ private volatile IPackageManager mPackageManager;
@Override
public boolean onCreate() {
synchronized (mLock) {
- mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
- mPackageManager = getContext().getPackageManager();
+ mUserManager = UserManager.get(getContext());
+ mPackageManager = AppGlobals.getPackageManager();
mSettingsRegistry = new SettingsRegistry();
}
registerBroadcastReceivers();
@@ -496,7 +498,7 @@
}
private void dumpForUser(int userId, PrintWriter pw) {
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
pw.println("GLOBAL SETTINGS (user " + userId + ")");
Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
dumpSettings(globalCursor, pw);
@@ -547,7 +549,7 @@
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_OWNER);
+ UserHandle.USER_SYSTEM);
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED: {
@@ -584,7 +586,7 @@
synchronized (mLock) {
// Get the settings.
SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
- SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
List<String> names = settingsState.getSettingNamesLocked();
@@ -612,7 +614,7 @@
// Get the value.
synchronized (mLock) {
return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_OWNER, name);
+ UserHandle.USER_SYSTEM, name);
}
}
@@ -656,19 +658,19 @@
case MUTATION_OPERATION_INSERT: {
return mSettingsRegistry
.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_OWNER, name, value, getCallingPackage());
+ UserHandle.USER_SYSTEM, name, value, getCallingPackage());
}
case MUTATION_OPERATION_DELETE: {
return mSettingsRegistry.deleteSettingLocked(
SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_OWNER, name);
+ UserHandle.USER_SYSTEM, name);
}
case MUTATION_OPERATION_UPDATE: {
return mSettingsRegistry
.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
- UserHandle.USER_OWNER, name, value, getCallingPackage());
+ UserHandle.USER_SYSTEM, name, value, getCallingPackage());
}
}
}
@@ -903,7 +905,7 @@
}
// Enforce what the calling package can mutate the system settings.
- enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name);
+ enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, runAsUserId);
// Resolve the userId on whose behalf the call is made.
final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
@@ -1001,7 +1003,7 @@
}
private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation,
- String name) {
+ String name, int userId) {
// System/root/shell can mutate whatever secure settings they want.
final int callingUid = Binder.getCallingUid();
if (callingUid == android.os.Process.SYSTEM_UID
@@ -1019,7 +1021,7 @@
}
// The calling package is already verified.
- PackageInfo packageInfo = getCallingPackageInfoOrThrow();
+ PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
// Privileged apps can do whatever they want.
if ((packageInfo.applicationInfo.privateFlags
@@ -1039,7 +1041,7 @@
}
// The calling package is already verified.
- PackageInfo packageInfo = getCallingPackageInfoOrThrow();
+ PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
// Privileged apps can do whatever they want.
if ((packageInfo.applicationInfo.privateFlags &
@@ -1053,17 +1055,17 @@
}
}
- private PackageInfo getCallingPackageInfoOrThrow() {
+ private PackageInfo getCallingPackageInfoOrThrow(int userId) {
try {
- return mPackageManager.getPackageInfo(getCallingPackage(), 0);
- } catch (PackageManager.NameNotFoundException e) {
+ return mPackageManager.getPackageInfo(getCallingPackage(), 0, userId);
+ } catch (RemoteException e) {
throw new IllegalStateException("Calling package doesn't exist");
}
}
private int getGroupParentLocked(int userId) {
// Most frequent use case.
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
return userId;
}
// We are in the same process with the user manager and the returned
@@ -1401,8 +1403,8 @@
migrateLegacySettingsForUserIfNeededLocked(userId);
// Ensure global settings loaded if owner.
- if (userId == UserHandle.USER_OWNER) {
- final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ if (userId == UserHandle.USER_SYSTEM) {
+ final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
ensureSettingsStateLocked(globalKey);
}
@@ -1541,7 +1543,7 @@
private void migrateAllLegacySettingsIfNeeded() {
synchronized (mLock) {
- final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
File globalFile = getSettingsFile(key);
if (globalFile.exists()) {
return;
@@ -1591,7 +1593,7 @@
private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
SQLiteDatabase database, int userId) {
// Move over the global settings if owner.
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
ensureSettingsStateLocked(globalKey);
SettingsState globalSettings = mSettingsStates.get(globalKey);
@@ -1898,7 +1900,7 @@
}
// Set the global settings version if owner.
- if (mUserId == UserHandle.USER_OWNER) {
+ if (mUserId == UserHandle.USER_SYSTEM) {
SettingsState globalSettings = getSettingsLocked(
SettingsRegistry.SETTINGS_TYPE_GLOBAL, mUserId);
globalSettings.setVersionLocked(newVersion);
@@ -1914,7 +1916,7 @@
}
private SettingsState getGlobalSettingsLocked() {
- return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
}
private SettingsState getSecureSettingsLocked(int userId) {
@@ -1960,7 +1962,7 @@
// v119: Reset zen + ringer mode.
if (currentVersion == 118) {
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
final SettingsState globalSettings = getGlobalSettingsLocked();
globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
Integer.toString(Settings.Global.ZEN_MODE_OFF),
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
index c7cc89b..8e56f47 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
@@ -48,7 +48,7 @@
Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE
};
- protected int mSecondaryUserId = UserHandle.USER_OWNER;
+ protected int mSecondaryUserId = UserHandle.USER_SYSTEM;
@Override
public void setContext(Context context) {
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java
index d581f3b..a09d5fe 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java
@@ -47,7 +47,7 @@
// Make sure the setting changed.
String firstValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
- FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ FAKE_SETTING_NAME, UserHandle.USER_SYSTEM);
assertEquals("Setting value didn't change", FAKE_SETTING_VALUE, firstValue);
// Set the setting to its second value.
@@ -56,7 +56,7 @@
// Make sure the setting changed.
String secondValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
- FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ FAKE_SETTING_NAME, UserHandle.USER_SYSTEM);
assertEquals("Setting value didn't change", FAKE_SETTING_VALUE_1, secondValue);
}
} finally {
@@ -86,20 +86,20 @@
for (int i = 0; i < ITERATION_COUNT; i++) {
// Set the setting to its first value.
setStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
- FAKE_SETTING_VALUE, UserHandle.USER_OWNER);
+ FAKE_SETTING_VALUE, UserHandle.USER_SYSTEM);
// Make sure the setting changed.
String firstValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
- FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ FAKE_SETTING_NAME, UserHandle.USER_SYSTEM);
assertEquals("Setting value didn't change", FAKE_SETTING_VALUE, firstValue);
// Set the setting to its second value.
setStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
- FAKE_SETTING_VALUE_1, UserHandle.USER_OWNER);
+ FAKE_SETTING_VALUE_1, UserHandle.USER_SYSTEM);
// Make sure the setting changed.
String secondValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
- FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ FAKE_SETTING_NAME, UserHandle.USER_SYSTEM);
assertEquals("Setting value didn't change", FAKE_SETTING_VALUE_1, secondValue);
}
} finally {
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
index ad56b9d..8ca1b46 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -46,40 +46,40 @@
private final Object mLock = new Object();
- public void testSetAndGetGlobalViaFrontEndApiForOwnerUser() throws Exception {
- performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ public void testSetAndGetGlobalViaFrontEndApiForSystemUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
}
- public void testSetAndGetGlobalViaFrontEndApiForNonOwnerUser() throws Exception {
- if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ public void testSetAndGetGlobalViaFrontEndApiForNonSystemUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_SYSTEM) {
Log.w(LOG_TAG, "No secondary user. Skipping "
- + "testSetAndGetGlobalViaFrontEndApiForNonOwnerUser");
+ + "testSetAndGetGlobalViaFrontEndApiForNonSystemUser");
return;
}
performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, mSecondaryUserId);
}
- public void testSetAndGetSecureViaFrontEndApiForOwnerUser() throws Exception {
- performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_OWNER);
+ public void testSetAndGetSecureViaFrontEndApiForSystemUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_SYSTEM);
}
- public void testSetAndGetSecureViaFrontEndApiForNonOwnerUser() throws Exception {
- if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ public void testSetAndGetSecureViaFrontEndApiForNonSystemUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_SYSTEM) {
Log.w(LOG_TAG, "No secondary user. Skipping "
- + "testSetAndGetSecureViaFrontEndApiForNonOwnerUser");
+ + "testSetAndGetSecureViaFrontEndApiForNonSystemUser");
return;
}
performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, mSecondaryUserId);
}
- public void testSetAndGetSystemViaFrontEndApiForOwnerUser() throws Exception {
- performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_OWNER);
+ public void testSetAndGetSystemViaFrontEndApiForSystemUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_SYSTEM);
}
- public void testSetAndGetSystemViaFrontEndApiForNonOwnerUser() throws Exception {
- if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ public void testSetAndGetSystemViaFrontEndApiForNonSystemUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_SYSTEM) {
Log.w(LOG_TAG, "No secondary user. Skipping "
- + "testSetAndGetSystemViaFrontEndApiForNonOwnerUser");
+ + "testSetAndGetSystemViaFrontEndApiForNonSystemUser");
return;
}
performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, mSecondaryUserId);
@@ -357,7 +357,7 @@
public void run() {
insertStringViaProviderApi(type, name, value, withTableRowUri);
}
- }, type, name, value, UserHandle.USER_OWNER);
+ }, type, name, value, UserHandle.USER_SYSTEM);
}
private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6f49fd6..0be3069 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1051,6 +1051,7 @@
// Without this, settings is not enabled until the lock screen first appears
setShowingLocked(false);
hideLocked();
+ mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
return;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index b701e0b..300ea2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -197,6 +197,7 @@
break;
case PLACE_FULL:
// Nothing to change.
+ mBounds[0] = null;
break;
}
@@ -213,10 +214,13 @@
dismiss();
mRecentsActivity.dismissRecentsToHomeWithoutTransitionAnimation();
- // Resize all tasks beginning from the "oldest" one.
- for (int i = additionalTasks; i >= 0; --i) {
- if (mTasks[i] != null) {
- mSsp.resizeTask(mTasks[i].key.id, mBounds[i]);
+ // In debug mode, we force all task to be resizeable regardless of the
+ // current app configuration.
+ if (RecentsConfiguration.getInstance().multiStackEnabled) {
+ for (int i = additionalTasks; i >= 0; --i) {
+ if (mTasks[i] != null) {
+ mSsp.setTaskResizeable(mTasks[i].key.id);
+ }
}
}
@@ -224,7 +228,7 @@
// the focus ends on the selected one.
for (int i = additionalTasks; i >= 0; --i) {
if (mTasks[i] != null) {
- mRecentsView.launchTask(mTasks[i]);
+ mRecentsView.launchTask(mTasks[i], mBounds[i]);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 89aeabc..bead1b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -271,17 +271,12 @@
return null;
}
- /** Resize a given task. */
- public void resizeTask(int taskId, Rect bounds) {
+ /** Allow a task to resize. */
+ public void setTaskResizeable(int taskId) {
if (mIam == null) return;
try {
- if (RecentsConfiguration.getInstance().multiStackEnabled) {
- // In debug mode, we force all task to be resizeable regardless of the
- // current app configuration.
- mIam.setTaskResizeable(taskId, true);
- }
- mIam.resizeTask(taskId, bounds);
+ mIam.setTaskResizeable(taskId, true);
} catch (RemoteException e) {
e.printStackTrace();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 00ac5f9..651b29a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -165,7 +165,7 @@
/** Gets the next task in the stack - or if the last - the top task */
public Task getNextTaskOrTopTask(Task taskToSearch) {
- Task returnTask = null;
+ Task returnTask = null;
boolean found = false;
List<TaskStackView> stackViews = getTaskStackViews();
int stackCount = stackViews.size();
@@ -203,7 +203,7 @@
TaskView tv = taskViews.get(j);
Task task = tv.getTask();
if (tv.isFocusedTask()) {
- onTaskViewClicked(stackView, tv, stack, task, false);
+ onTaskViewClicked(stackView, tv, stack, task, false, false, null);
return true;
}
}
@@ -212,7 +212,7 @@
}
/** Launches a given task. */
- public boolean launchTask(Task task) {
+ public boolean launchTask(Task task, Rect taskBounds) {
// Get the first stack view
List<TaskStackView> stackViews = getTaskStackViews();
int stackCount = stackViews.size();
@@ -225,7 +225,7 @@
for (int j = 0; j < taskViewCount; j++) {
TaskView tv = taskViews.get(j);
if (tv.getTask() == task) {
- onTaskViewClicked(stackView, tv, stack, task, false);
+ onTaskViewClicked(stackView, tv, stack, task, false, true, taskBounds);
return true;
}
}
@@ -250,7 +250,7 @@
if (tasks.get(j).isLaunchTarget) {
Task task = tasks.get(j);
TaskView tv = stackView.getChildViewForTask(task);
- onTaskViewClicked(stackView, tv, stack, task, false);
+ onTaskViewClicked(stackView, tv, stack, task, false, false, null);
return true;
}
}
@@ -373,7 +373,7 @@
searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
}
- // Layout each TaskStackView with the full width and height of the window since the
+ // Layout each TaskStackView with the full width and height of the window since the
// transition view is a child of that stack view
List<TaskStackView> stackViews = getTaskStackViews();
int stackCount = stackViews.size();
@@ -604,7 +604,8 @@
@Override
public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
- final TaskStack stack, final Task task, final boolean lockToTask) {
+ final TaskStack stack, final Task task, final boolean lockToTask,
+ final boolean boundsValid, final Rect bounds) {
// Notify any callbacks of the launching of a new task
if (mCb != null) {
@@ -632,9 +633,9 @@
final SystemServicesProxy ssp =
RecentsTaskLoader.getInstance().getSystemServicesProxy();
ActivityOptions opts = null;
+ ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
task.thumbnail.getHeight() > 0) {
- ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
boolean mTriggered = false;
@@ -665,9 +666,14 @@
offsetX, offsetY, transform.rect.width(), transform.rect.height(),
sourceView.getHandler(), animStartedListener);
}
+ } else {
+ opts = ActivityOptions.makeBasic();
}
-
+ if (boundsValid) {
+ opts.setBounds(bounds);
+ }
final ActivityOptions launchOpts = opts;
+ final boolean screenPinningRequested = (animStartedListener == null) && lockToTask;
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
@@ -677,7 +683,7 @@
} else {
if (ssp.startActivityFromRecents(getContext(), task.key.id,
task.activityLabel, launchOpts)) {
- if (launchOpts == null && lockToTask) {
+ if (screenPinningRequested) {
mCb.onScreenPinningRequest();
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0068f84..4e82c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -59,7 +59,7 @@
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
- boolean lockToTask);
+ boolean lockToTask, boolean boundsValid, Rect bounds);
public void onTaskViewAppInfoClicked(Task t);
public void onTaskViewDismissed(Task t);
public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
@@ -1377,7 +1377,7 @@
mUIDozeTrigger.stopDozing();
if (mCb != null) {
- mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask);
+ mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index d0a7f8a..030501b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -248,10 +248,10 @@
return STATE_FINGERPRINT_ERROR;
} else if (mUnlockMethodCache.canSkipBouncer()) {
return STATE_LOCK_OPEN;
- } else if (fingerprintRunning && unlockingAllowed) {
- return STATE_FINGERPRINT;
} else if (mUnlockMethodCache.isFaceUnlockRunning()) {
return STATE_FACE_UNLOCK;
+ } else if (fingerprintRunning && unlockingAllowed) {
+ return STATE_FINGERPRINT;
} else {
return STATE_LOCKED;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 57769e7..7051b52 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -205,9 +205,7 @@
private final UserManager mUserManager;
- private final LockPatternUtils mLockPatternUtils;
-
- private int mCurrentUserId = UserHandle.USER_OWNER;
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
//TODO: Remove this hack
private boolean mInitialized;
@@ -230,7 +228,6 @@
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mSecurityPolicy = new SecurityPolicy();
mMainHandler = new MainHandler(mContext.getMainLooper());
- mLockPatternUtils = new LockPatternUtils(context);
registerBroadcastReceivers();
new AccessibilityContentObserver(mMainHandler).register(
context.getContentResolver());
@@ -866,17 +863,18 @@
}
// Called only during settings restore; currently supports only the owner user
+ // TODO: http://b/22388012
void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
- UserState userState = getUserStateLocked(UserHandle.USER_OWNER);
+ UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
userState.mEnabledServices.clear();
userState.mEnabledServices.addAll(mTempComponentNameSet);
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
userState.mEnabledServices,
- UserHandle.USER_OWNER);
+ UserHandle.USER_SYSTEM);
onUserStateChangedLocked(userState);
}
@@ -1646,10 +1644,6 @@
DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
}
- private boolean hasRunningServicesLocked(UserState userState) {
- return !userState.mBoundServices.isEmpty() || !userState.mBindingServices.isEmpty();
- }
-
private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
IBinder windowToken = mGlobalWindowTokens.get(windowId);
if (windowToken == null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0119000..4949138 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2085,7 +2085,8 @@
}
private boolean collectPackageServicesLocked(String packageName, Set<String> filterByClasses,
- boolean evenPersistent, boolean doit, ArrayMap<ComponentName, ServiceRecord> services) {
+ boolean evenPersistent, boolean doit, boolean killProcess,
+ ArrayMap<ComponentName, ServiceRecord> services) {
boolean didSomething = false;
for (int i = services.size() - 1; i >= 0; i--) {
ServiceRecord service = services.valueAt(i);
@@ -2101,7 +2102,7 @@
didSomething = true;
Slog.i(TAG, " Force stopping service " + service);
if (service.app != null) {
- service.app.removed = true;
+ service.app.removed = killProcess;
if (!service.app.persistent) {
service.app.services.remove(service);
}
@@ -2118,7 +2119,7 @@
}
boolean bringDownDisabledPackageServicesLocked(String packageName, Set<String> filterByClasses,
- int userId, boolean evenPersistent, boolean doit) {
+ int userId, boolean evenPersistent, boolean killProcess, boolean doit) {
boolean didSomething = false;
if (mTmpCollectionResults != null) {
@@ -2128,7 +2129,7 @@
if (userId == UserHandle.USER_ALL) {
for (int i = mServiceMap.size() - 1; i >= 0; i--) {
didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
- evenPersistent, doit, mServiceMap.valueAt(i).mServicesByName);
+ evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
if (!doit && didSomething) {
return true;
}
@@ -2138,7 +2139,7 @@
if (smap != null) {
ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
- evenPersistent, doit, items);
+ evenPersistent, doit, killProcess, items);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3554c39..81936ee 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4225,7 +4225,7 @@
throw new IllegalArgumentException("Task " + taskId + " not found.");
}
if (task.getRootActivity() != null) {
- moveTaskToFrontLocked(task.taskId, 0, null);
+ moveTaskToFrontLocked(task.taskId, 0, options);
return ActivityManager.START_TASK_TO_FRONT;
}
callingUid = task.mCallingUid;
@@ -5647,7 +5647,7 @@
}
private void cleanupDisabledPackageComponentsLocked(
- String packageName, int userId, String[] changedClasses) {
+ String packageName, int userId, boolean killProcess, String[] changedClasses) {
Set<String> disabledClasses = null;
boolean packageDisabled = false;
@@ -5717,7 +5717,7 @@
// Clean-up disabled services.
mServices.bringDownDisabledPackageServicesLocked(
- packageName, disabledClasses, userId, false, true);
+ packageName, disabledClasses, userId, false, killProcess, true);
// Clean-up disabled providers.
ArrayList<ContentProviderRecord> providers = new ArrayList<>();
@@ -5802,7 +5802,7 @@
}
if (mServices.bringDownDisabledPackageServicesLocked(
- packageName, null, userId, evenPersistent, doit)) {
+ packageName, null, userId, evenPersistent, true, doit)) {
if (!doit) {
return true;
}
@@ -16892,7 +16892,9 @@
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
boolean fullUninstall = removed &&
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
- if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+ final boolean killProcess =
+ !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
+ if (killProcess) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
false, true, true, false, fullUninstall, userId,
@@ -16912,7 +16914,7 @@
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
- cleanupDisabledPackageComponentsLocked(ssp, userId,
+ cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 37ddd4d..a2467ef 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -18,7 +18,6 @@
import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
@@ -4548,10 +4547,11 @@
boolean toTop) {
TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
voiceInteractor);
+ // add the task to stack first, mTaskPositioner might need the stack association
+ addTask(task, toTop, false);
if (mTaskPositioner != null) {
mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.initialLayout);
}
- addTask(task, toTop, false);
return task;
}
@@ -4588,19 +4588,20 @@
void addConfigOverride(ActivityRecord r, TaskRecord task) {
final Rect bounds = task.getLaunchBounds();
- final Configuration config = task.updateOverrideConfiguration(mStackId, bounds);
+ task.updateOverrideConfiguration(bounds);
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind,
- bounds, config);
+ bounds, task.mOverrideConfig);
r.taskConfigOverride = task.mOverrideConfig;
}
private void setAppTask(ActivityRecord r, TaskRecord task) {
final Rect bounds = task.getLaunchBounds();
- final Configuration config = task.updateOverrideConfiguration(mStackId, bounds);
- mWindowManager.setAppTask(r.appToken, task.taskId, task.getLaunchBounds(), config);
+ task.updateOverrideConfiguration(bounds);
+ mWindowManager.setAppTask(
+ r.appToken, task.taskId, task.getLaunchBounds(), task.mOverrideConfig);
r.taskConfigOverride = task.mOverrideConfig;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 33e0ef8..56ea0f1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1764,7 +1764,7 @@
return ACTIVITY_RESTRICTION_NONE;
}
- ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
+ ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) {
final TaskRecord task = r.task;
// On leanback only devices we should keep all activities in the same stack.
@@ -1815,10 +1815,10 @@
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
- stack = getStack(
- task != null
- ? task.getLaunchStackId(mFocusedStack) : FULLSCREEN_WORKSPACE_STACK_ID,
- CREATE_IF_NEEDED, ON_TOP);
+ int stackId = task != null ? task.getLaunchStackId() :
+ bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
+ FULLSCREEN_WORKSPACE_STACK_ID;
+ stack = getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
return stack;
@@ -1846,6 +1846,22 @@
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
+ boolean overrideBounds = false;
+ Rect newBounds = null;
+ if (r.info.resizeable || (inTask != null && inTask.mResizeable)) {
+ if (intent.hasExtra(ActivityOptions.KEY_BOUNDS)) {
+ overrideBounds = true;
+ newBounds = Rect.unflattenFromString(
+ intent.getStringExtra(ActivityOptions.KEY_BOUNDS));
+ } else if (options != null) {
+ ActivityOptions opts = new ActivityOptions(options);
+ if (opts.hasBounds()) {
+ overrideBounds = true;
+ newBounds = opts.getBounds();
+ }
+ }
+ }
+
// In some flows in to this function, we retrieve the task record and hold on to it
// without a lock before calling back in to here... so the task at this point may
// not actually be in recents. Check for that, and if it isn't in recents just
@@ -2199,7 +2215,8 @@
if (task != null && task.stack == null) {
// Target stack got cleared when we all activities were removed
// above. Go ahead and reset it.
- targetStack = computeStackFocus(sourceRecord, false /* newTask */);
+ targetStack = computeStackFocus(
+ sourceRecord, false /* newTask */, null /* bounds */);
targetStack.addTask(
task, !launchTaskBehind /* toTop */, false /* moving */);
}
@@ -2325,7 +2342,7 @@
if (r.resultTo == null && inTask == null && !addingToTask
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
- targetStack = computeStackFocus(r, newTask);
+ targetStack = computeStackFocus(r, newTask, newBounds);
if (doResume) {
targetStack.moveToFront("startingNewTask");
}
@@ -2336,6 +2353,9 @@
newTaskIntent != null ? newTaskIntent : intent,
voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
taskToAffiliate);
+ if (overrideBounds) {
+ r.task.updateOverrideConfiguration(newBounds);
+ }
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + r + " in new task " + r.task);
} else {
@@ -2420,6 +2440,14 @@
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
+ if (overrideBounds) {
+ inTask.updateOverrideConfiguration(newBounds);
+ int stackId = inTask.getLaunchStackId();
+ if (stackId != inTask.stack.mStackId) {
+ moveTaskToStackUncheckedLocked(
+ inTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
+ }
+ }
targetStack = inTask.stack;
targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker,
"inTaskToFront");
@@ -2457,7 +2485,7 @@
// This not being started from an existing activity, and not part
// of a new task... just put it in the top task, though these days
// this case should never happen.
- targetStack = computeStackFocus(r, newTask);
+ targetStack = computeStackFocus(r, newTask, null /* bounds */);
if (doResume) {
targetStack.moveToFront("addingToTopTask");
}
@@ -2816,9 +2844,26 @@
+ task + " to front. Stack is null");
return;
}
- task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+
+ int stackId = task.stack.mStackId;
+ if (task.mResizeable && options != null) {
+ ActivityOptions opts = new ActivityOptions(options);
+ if (opts.hasBounds()) {
+ Rect bounds = opts.getBounds();
+ task.updateOverrideConfiguration(bounds);
+ mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false);
+ stackId = task.getLaunchStackId();
+ }
+ }
+
+ if (stackId != task.stack.mStackId) {
+ moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, FORCE_FOCUS, reason);
+ } else {
+ task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
task.getTopActivity() == null ? null : task.getTopActivity().appTimeTracker,
reason);
+ }
+
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + task.stack);
}
@@ -2925,7 +2970,7 @@
ArrayList<TaskRecord> tasks = stack.getAllTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
TaskRecord task = tasks.get(i);
- task.updateOverrideConfiguration(stackId, bounds);
+ task.updateOverrideConfiguration(bounds);
mTmpConfigs.put(task.taskId, task.mOverrideConfig);
mTmpBounds.put(task.taskId, task.mBounds);
}
@@ -3007,7 +3052,7 @@
// Task doesn't exist in window manager yet (e.g. was restored from recents).
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
- task.mBounds = task.mLastNonFullscreenBounds = new Rect(bounds);
+ task.updateOverrideConfiguration(bounds);
if (task.stack != null && task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
// re-restore the task so it can have the proper stack association.
restoreRecentTaskLocked(task, FREEFORM_WORKSPACE_STACK_ID);
@@ -3029,7 +3074,7 @@
moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, "resizeTask");
}
- final Configuration overrideConfig = task.updateOverrideConfiguration(stackId, bounds);
+ final Configuration overrideConfig = task.updateOverrideConfiguration(bounds);
// This variable holds information whether the configuration didn't change in a signficant
// way and the activity was kept the way it was. If it's false, it means the activity had
// to be relaunched due to configuration change.
@@ -3081,8 +3126,7 @@
*/
private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
if (stackId == INVALID_STACK_ID) {
- stackId = mLeanbackOnlyDevice ?
- mHomeStack.mStackId : task.getLaunchStackId(mFocusedStack);
+ stackId = mLeanbackOnlyDevice ? mHomeStack.mStackId : task.getLaunchStackId();
}
if (task.stack != null) {
// Task has already been restored once. See if we need to do anything more
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
index 735c06f..3d45915 100644
--- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -235,7 +234,7 @@
break;
}
}
- task.updateOverrideConfiguration(FREEFORM_WORKSPACE_STACK_ID, proposal);
+ task.updateOverrideConfiguration(proposal);
}
private boolean shiftedToFar(Rect start, int shiftPolicy) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 12c7b86..5694e704 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -20,7 +20,6 @@
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.INVALID_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
@@ -228,8 +227,6 @@
Configuration mOverrideConfig = Configuration.EMPTY;
- private Rect mTmpRect = new Rect();
-
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
mService = service;
@@ -1174,7 +1171,7 @@
activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
callingUid, callingPackage, resizeable, privileged);
- task.updateOverrideConfiguration(INVALID_STACK_ID, bounds);
+ task.updateOverrideConfiguration(bounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
activities.get(activityNdx).task = task;
@@ -1188,12 +1185,12 @@
* Update task's override configuration based on the bounds.
* @return Update configuration or null if there is no change.
*/
- Configuration updateOverrideConfiguration(int stackId, Rect bounds) {
- if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
+ Configuration updateOverrideConfiguration(Rect bounds) {
+ if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
// For freeform stack we don't adjust the size of the tasks to match that of the
// stack, but we do try to make sure the tasks are still contained with the
// bounds of the stack.
- bounds = fitWithinBounds(bounds);
+ fitWithinBounds(bounds, stack.mBounds);
}
if (Objects.equals(mBounds, bounds)) {
return null;
@@ -1231,20 +1228,16 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
- /** Returns the stack that should be used to launch this task. */
- int getLaunchStackId(ActivityStack focusStack) {
- if (stack != null) {
- // We are already in a stack silly...
- return stack.mStackId;
- }
- if (isHomeTask()) {
+ /**
+ * Returns the correct stack to use based on task type and currently set bounds,
+ * regardless of the focused stack and current stack association of the task.
+ * The task will be moved (and stack focus changed) later if necessary.
+ */
+ int getLaunchStackId() {
+ if (!isApplicationTask()) {
return HOME_STACK_ID;
}
- if (focusStack != null && focusStack.mStackId != HOME_STACK_ID) {
- // Like it or not you are going in the focused stack!
- return focusStack.mStackId;
- }
- if (mBounds != null || mLastNonFullscreenBounds != null) {
+ if (mBounds != null) {
return FREEFORM_WORKSPACE_STACK_ID;
}
return FULLSCREEN_WORKSPACE_STACK_ID;
@@ -1262,39 +1255,43 @@
return mLastNonFullscreenBounds;
}
- /** Fits the tasks within the input bounds adjusting the task bounds as needed.
- * @param bounds Bounds to fit the task within. Nothing is done if null.
- * @return Returns final configuration after updating with the adjusted bounds.
- * */
- Rect fitWithinBounds(Rect bounds) {
- if (bounds == null || mBounds == null || bounds.contains(mBounds)) {
- return bounds;
+ /**
+ * Adjust bounds to stay within stack bounds.
+ *
+ * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
+ * that keep them unchanged, but be contained within the stack bounds.
+ *
+ * @param bounds Bounds to be adjusted.
+ * @param stackBounds Bounds within which the other bounds should remain.
+ */
+ private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
+ if (stackBounds == null || stackBounds.contains(bounds)) {
+ return;
}
- mTmpRect.set(mBounds);
- if (mBounds.left < bounds.left || mBounds.right > bounds.right) {
- final int maxRight = bounds.right - (bounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
- int horizontalDiff = bounds.left - mBounds.left;
- if ((horizontalDiff < 0 && mBounds.left >= maxRight)
- || (mBounds.left + horizontalDiff >= maxRight)) {
- horizontalDiff = maxRight - mBounds.left;
+ if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
+ final int maxRight = stackBounds.right
+ - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
+ int horizontalDiff = stackBounds.left - bounds.left;
+ if ((horizontalDiff < 0 && bounds.left >= maxRight)
+ || (bounds.left + horizontalDiff >= maxRight)) {
+ horizontalDiff = maxRight - bounds.left;
}
- mTmpRect.left += horizontalDiff;
- mTmpRect.right += horizontalDiff;
+ bounds.left += horizontalDiff;
+ bounds.right += horizontalDiff;
}
- if (mBounds.top < bounds.top || mBounds.bottom > bounds.bottom) {
- final int maxBottom = bounds.bottom - (bounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
- int verticalDiff = bounds.top - mBounds.top;
- if ((verticalDiff < 0 && mBounds.top >= maxBottom)
- || (mBounds.top + verticalDiff >= maxBottom)) {
- verticalDiff = maxBottom - mBounds.top;
+ if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
+ final int maxBottom = stackBounds.bottom
+ - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
+ int verticalDiff = stackBounds.top - bounds.top;
+ if ((verticalDiff < 0 && bounds.top >= maxBottom)
+ || (bounds.top + verticalDiff >= maxBottom)) {
+ verticalDiff = maxBottom - bounds.top;
}
- mTmpRect.top += verticalDiff;
- mTmpRect.bottom += verticalDiff;
+ bounds.top += verticalDiff;
+ bounds.bottom += verticalDiff;
}
-
- return mTmpRect;
}
void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 67c9ee8..0023258 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -259,7 +259,7 @@
}
private boolean inLockoutMode() {
- return mFailedAttempts > MAX_FAILED_ATTEMPTS;
+ return mFailedAttempts >= MAX_FAILED_ATTEMPTS;
}
private void resetFailedAttempts() {
@@ -275,7 +275,7 @@
private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
mFailedAttempts++;
- if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {
+ if (inLockoutMode()) {
// Failing multiple times will continue to push out the lockout time.
mHandler.removeCallbacks(mLockoutReset);
mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 17b4f9c..5a13672 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.input;
import android.view.Display;
+import com.android.internal.os.SomeArgs;
import com.android.internal.R;
import com.android.internal.util.XmlUtils;
import com.android.server.DisplayThread;
@@ -52,6 +53,7 @@
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
+import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.TouchCalibration;
import android.os.Binder;
@@ -93,6 +95,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import libcore.io.Streams;
import libcore.util.Objects;
@@ -112,6 +115,7 @@
private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
+ private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6;
// Pointer to native input manager service object.
private final long mPtr;
@@ -124,6 +128,13 @@
private boolean mSystemReady;
private NotificationManager mNotificationManager;
+ private final Object mTabletModeLock = new Object();
+ // List of currently registered tablet mode changed listeners by process id
+ private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners =
+ new SparseArray<>(); // guarded by mTabletModeLock
+ private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
+ new ArrayList<>();
+
// Persistent data store. Must be locked each time during use.
private final PersistentDataStore mDataStore = new PersistentDataStore();
@@ -227,6 +238,11 @@
/** Switch code: Lid switch. When set, lid is shut. */
public static final int SW_LID = 0x00;
+ /** Switch code: Tablet mode switch.
+ * When set, the device is in tablet mode (i.e. no keyboard is connected).
+ */
+ public static final int SW_TABLET_MODE = 0x01;
+
/** Switch code: Keypad slide. When set, keyboard is exposed. */
public static final int SW_KEYPAD_SLIDE = 0x0a;
@@ -246,6 +262,7 @@
public static final int SW_CAMERA_LENS_COVER = 0x09;
public static final int SW_LID_BIT = 1 << SW_LID;
+ public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
@@ -774,6 +791,57 @@
}
}
+ @Override // Binder call
+ public void registerTabletModeChangedListener(ITabletModeChangedListener listener) {
+ if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE_LISTENER,
+ "registerTabletModeChangedListener()")) {
+ throw new SecurityException("Requires TABLET_MODE_LISTENER permission");
+ }
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mTabletModeLock) {
+ final int callingPid = Binder.getCallingPid();
+ if (mTabletModeChangedListeners.get(callingPid) != null) {
+ throw new IllegalStateException("The calling process has already registered "
+ + "a TabletModeChangedListener.");
+ }
+ TabletModeChangedListenerRecord record =
+ new TabletModeChangedListenerRecord(callingPid, listener);
+ try {
+ IBinder binder = listener.asBinder();
+ binder.linkToDeath(record, 0);
+ } catch (RemoteException ex) {
+ throw new RuntimeException(ex);
+ }
+ mTabletModeChangedListeners.put(callingPid, record);
+ }
+ }
+
+ private void onTabletModeChangedListenerDied(int pid) {
+ synchronized (mTabletModeLock) {
+ mTabletModeChangedListeners.remove(pid);
+ }
+ }
+
+ // Must be called on handler
+ private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ mTempTabletModeChangedListenersToNotify.clear();
+ final int numListeners;
+ synchronized (mTabletModeLock) {
+ numListeners = mTabletModeChangedListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mTempTabletModeChangedListenersToNotify.add(
+ mTabletModeChangedListeners.valueAt(i));
+ }
+ }
+ for (int i = 0; i < numListeners; i++) {
+ mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged(
+ whenNanos, inTabletMode);
+ }
+ }
+
// Must be called on handler.
private void showMissingKeyboardLayoutNotification(InputDevice device) {
if (!mKeyboardLayoutNotificationShown) {
@@ -1419,6 +1487,15 @@
mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
switchMask);
}
+
+ if ((switchMask & SW_TABLET_MODE) != 0) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+ args.argi2 = (int) (whenNanos >> 32);
+ args.arg1 = Boolean.valueOf((switchValues & SW_TABLET_MODE_BIT) != 0);
+ mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
+ args).sendToTarget();
+ }
}
// Native callback.
@@ -1664,6 +1741,12 @@
case MSG_RELOAD_DEVICE_ALIASES:
reloadDeviceAliases();
break;
+ case MSG_DELIVER_TABLET_MODE_CHANGED:
+ SomeArgs args = (SomeArgs) msg.obj;
+ long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
+ boolean inTabletMode = (boolean) args.arg1;
+ deliverTabletModeChanged(whenNanos, inTabletMode);
+ break;
}
}
}
@@ -1755,6 +1838,34 @@
}
}
+ private final class TabletModeChangedListenerRecord implements DeathRecipient {
+ private final int mPid;
+ private final ITabletModeChangedListener mListener;
+
+ public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) {
+ mPid = pid;
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ if (DEBUG) {
+ Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died.");
+ }
+ onTabletModeChangedListenerDied(mPid);
+ }
+
+ public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ try {
+ mListener.onTabletModeChanged(whenNanos, inTabletMode);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid +
+ " that tablet mode changed, assuming it died.", ex);
+ binderDied();
+ }
+ }
+ }
+
private final class VibratorToken implements DeathRecipient {
public final int mDeviceId;
public final IBinder mToken;
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 239c471..5e5a55c 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -447,7 +447,8 @@
checkSmsSuplInit(intent);
} else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
checkWapSuplInit(intent);
- } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)
+ || action.equals(ConnectivityManager.CONNECTIVITY_ACTION_SUPL)) {
// retrieve NetworkType result for this UID
int networkType = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
if (DEBUG) Log.d(TAG, "Connectivity action, type=" + networkType);
@@ -2067,6 +2068,7 @@
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 88088fa..82afdd7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5999,12 +5999,6 @@
*/
if (shouldHideSystemApp) {
synchronized (mPackages) {
- /*
- * We have to grant systems permissions before we hide, because
- * grantPermissions will assume the package update is trying to
- * expand its permissions.
- */
- grantPermissionsLPw(pkg, true, pkg.packageName);
mSettings.disableSystemPackageLPw(pkg.packageName);
}
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index d0962f4..fc23fd1 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -750,7 +750,7 @@
}
boolean adjustWallpaperWindows() {
- mService.mInnerFields.mWallpaperMayChange = false;
+ mService.mWindowPlacerLocked.mWallpaperMayChange = false;
final WindowList windows = mService.getDefaultWindowListLocked();
// First find top-most window that has asked to be on top of the wallpaper;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index e6a1be1..b334a05 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -23,11 +23,11 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
import android.content.Context;
import android.os.RemoteException;
@@ -41,8 +41,6 @@
import android.view.animation.Animation;
import android.view.Choreographer;
-import com.android.server.wm.WindowManagerService.LayoutFields;
-
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -84,8 +82,7 @@
int mBulkUpdateParams = 0;
Object mLastWindowFreezeSource;
- SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
- new SparseArray<DisplayContentsAnimator>(2);
+ SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
boolean mInitialized = false;
@@ -179,10 +176,12 @@
mAnimating = mAppWindowAnimating = true;
} else if (appAnimator.wasAnimating) {
// stopped animating, do one more pass through the layout
- setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
- "exiting appToken " + appAnimator.mAppToken + " done", displayId);
+ setAppLayoutChanges(appAnimator,
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+ "exiting appToken " + appAnimator.mAppToken + " done", displayId);
if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
- "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
+ "updateWindowsApps...: done animating exiting "
+ + appAnimator.mAppToken);
}
}
}
@@ -301,7 +300,8 @@
setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
- mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 2",
getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
}
}
@@ -315,7 +315,8 @@
setPendingLayoutChanges(displayId,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
- mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 3",
getPendingLayoutChanges(displayId));
}
mService.mFocusMayChange = true;
@@ -409,7 +410,8 @@
setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
- mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 4",
getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
}
}
@@ -433,7 +435,8 @@
setPendingLayoutChanges(displayId,
WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
- mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 5",
getPendingLayoutChanges(displayId));
}
}
@@ -607,7 +610,8 @@
"Setting mOrientationChangeComplete=true because wtoken "
+ wtoken + " numInteresting=" + wtoken.numInterestingWindows
+ " numDrawn=" + wtoken.numDrawnWindows);
- // This will set mOrientationChangeComplete and cause a pass through layout.
+ // This will set mOrientationChangeComplete and cause a pass through
+ // layout.
setAppLayoutChanges(appAnimator,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
"testTokenMayBeDrawnLocked: freezingScreen", displayId);
@@ -737,7 +741,7 @@
boolean doRequest = false;
if (mBulkUpdateParams != 0) {
- doRequest = mService.copyAnimToLayoutParamsLocked();
+ doRequest = mService.mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
}
if (hasPendingLayoutChanges || doRequest) {
@@ -755,21 +759,21 @@
}
}
- static String bulkUpdateParamsToString(int bulkUpdateParams) {
+ private static String bulkUpdateParamsToString(int bulkUpdateParams) {
StringBuilder builder = new StringBuilder(128);
- if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+ if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
builder.append(" UPDATE_ROTATION");
}
- if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+ if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
builder.append(" WALLPAPER_MAY_CHANGE");
}
- if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+ if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
builder.append(" FORCE_HIDING_CHANGED");
}
- if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
+ if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
builder.append(" ORIENTATION_CHANGE_COMPLETE");
}
- if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
+ if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
builder.append(" TURN_ON_SCREEN");
}
return builder.toString();
@@ -846,7 +850,8 @@
if (displayId == windows.get(i).getDisplayId()) {
setPendingLayoutChanges(displayId, changes);
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
- mService.debugLayoutRepeats(reason, getPendingLayoutChanges(displayId));
+ mService.mWindowPlacerLocked.debugLayoutRepeats(reason,
+ getPendingLayoutChanges(displayId));
}
break;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 841233c..cf093f5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -34,8 +34,6 @@
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@@ -70,7 +68,6 @@
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
-import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -112,7 +109,6 @@
import android.view.WindowManagerPolicy;
import android.view.WindowManagerPolicy.PointerEventListener;
import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import com.android.internal.app.IAssistScreenshotReceiver;
@@ -157,16 +153,12 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -177,11 +169,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -313,6 +302,7 @@
}
}
};
+ final WindowSurfacePlacer mWindowPlacerLocked;
/**
* Current user when multi-user is enabled. Don't show windows of
@@ -444,7 +434,6 @@
final float[] mTmpFloats = new float[9];
final Rect mTmpContentRect = new Rect();
- private final Rect mTmpStartRect = new Rect();
boolean mDisplayReady;
boolean mSafeMode;
@@ -491,7 +480,7 @@
final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
- private int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
+ int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
boolean mClientFreezingScreen = false;
int mAppsFreezingScreen = 0;
@@ -614,51 +603,11 @@
// For frozen screen animations.
int mExitAnimId, mEnterAnimId;
- /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
- * methods. */
- class LayoutFields {
- static final int SET_UPDATE_ROTATION = 1 << 0;
- static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
- static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
- static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
- static final int SET_TURN_ON_SCREEN = 1 << 4;
- static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5;
-
- boolean mWallpaperForceHidingChanged = false;
- boolean mWallpaperMayChange = false;
- boolean mOrientationChangeComplete = true;
- Object mLastWindowFreezeSource = null;
- private Session mHoldScreen = null;
- private boolean mObscured = false;
- private boolean mSyswin = false;
- private float mScreenBrightness = -1;
- private float mButtonBrightness = -1;
- private long mUserActivityTimeout = -1;
- private boolean mUpdateRotation = false;
- boolean mWallpaperActionPending = false;
-
- // Set to true when the display contains content to show the user.
- // When false, the display manager may choose to mirror or blank the display.
- boolean mDisplayHasContent = false;
-
- // Only set while traversing the default display based on its content.
- // Affects the behavior of mirroring on secondary displays.
- boolean mObscureApplicationContentOnSecondaryDisplays = false;
-
- float mPreferredRefreshRate = 0;
-
- int mPreferredModeId = 0;
- }
- final LayoutFields mInnerFields = new LayoutFields();
-
boolean mAnimationScheduled;
/** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
* is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
- private int mTransactionSequence;
-
- /** Only do a maximum of 6 repeated layouts. After that quit */
- private int mLayoutRepeatCount;
+ int mTransactionSequence;
final WindowAnimator mAnimator;
@@ -768,7 +717,7 @@
boolean mInTouchMode;
private ViewServer mViewServer;
- private final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
+ final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
boolean mWindowsChanged = false;
public interface WindowChangeListener {
@@ -788,7 +737,7 @@
// List of clients without a transtiton animation that we notify once we are done transitioning
// since they won't be notified through the app window animator.
- private final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
+ final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
/** Listener to notify activity manager about app transitions. */
private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
@@ -866,6 +815,9 @@
mDisplaySettings = new DisplaySettings();
mDisplaySettings.readSettingsLocked();
+ mWallpaperControllerLocked = new WallpaperController(this);
+ mWindowPlacerLocked = new WindowSurfacePlacer(this);
+
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
@@ -953,8 +905,6 @@
updateCircularDisplayMaskIfNeeded();
showEmulatorDisplayOverlayIfNeeded();
-
- mWallpaperControllerLocked = new WallpaperController(this);
}
public InputMonitor getInputMonitor() {
@@ -2154,7 +2104,7 @@
}
final boolean focusChanged = updateFocusedWindowLocked(
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
if (appToken != null) {
appToken.updateReportedVisibilityLocked();
}
@@ -2272,14 +2222,14 @@
final WindowList windows = win.getWindowList();
if (windows != null) {
windows.remove(win);
- if (!mInLayout) {
+ if (!mWindowPlacerLocked.isInLayout()) {
assignLayersLocked(windows);
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent != null) {
displayContent.layoutNeeded = true;
}
if (performLayout) {
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
@@ -2363,7 +2313,7 @@
if (displayContent != null) {
displayContent.layoutNeeded = true;
}
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
} finally {
@@ -2692,7 +2642,7 @@
}
win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
configChanged = updateOrientationFromAppTokensLocked(false);
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
if (toBeDisplayed && win.mIsWallpaper) {
DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
mWallpaperControllerLocked.updateWallpaperOffset(
@@ -3025,7 +2975,7 @@
wtoken.hidden = true;
if (changed) {
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
false /*updateInputWindows*/);
}
@@ -3391,7 +3341,7 @@
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -3589,7 +3539,7 @@
mAppTransition.setReady();
final long origId = Binder.clearCallingIdentity();
try {
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3696,7 +3646,7 @@
updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
true /*updateInputWindows*/);
getDefaultDisplayContentLocked().layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
Binder.restoreCallingIdentity(origId);
return;
} else if (ttoken.startingData != null) {
@@ -3962,7 +3912,7 @@
if (performLayout) {
updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/);
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
}
@@ -4100,7 +4050,7 @@
&& mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
w.mOrientationChanging = true;
- mInnerFields.mOrientationChangeComplete = false;
+ mWindowPlacerLocked.mOrientationChangeComplete = false;
}
w.mLastFreezeDuration = 0;
unfrozeWindows = true;
@@ -4120,7 +4070,7 @@
}
if (unfreezeSurfaceNow) {
if (unfrozeWindows) {
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
stopFreezingDisplayLocked();
}
@@ -4408,7 +4358,7 @@
}
mInputMonitor.setUpdateInputWindowsNeededLw();
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
mInputMonitor.updateInputWindowsLw(false /*force*/);
//dump();
@@ -4560,7 +4510,7 @@
stack.addTask(task, toTop);
final DisplayContent displayContent = stack.getDisplayContent();
displayContent.layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -4581,7 +4531,7 @@
task.moveTaskToStack(stack, toTop);
final DisplayContent displayContent = stack.getDisplayContent();
displayContent.layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -4616,7 +4566,7 @@
if (stack.setBounds(bounds, resizeTasks, configs, taskBounds)) {
stack.resizeWindows();
stack.getDisplayContent().layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
return stack.isFullscreen();
}
@@ -4641,7 +4591,7 @@
task.positionTaskInStack(stack, position);
final DisplayContent displayContent = stack.getDisplayContent();
displayContent.layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -4661,7 +4611,7 @@
task.resizeWindows();
if (relayout) {
task.getDisplayContent().layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
}
@@ -5054,7 +5004,7 @@
displayContent.switchUserStacks();
rebuildAppWindowListLocked(displayContent);
}
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -5893,7 +5843,7 @@
changed = updateRotationUncheckedLocked(false);
if (!changed || forceRelayout) {
getDefaultDisplayContentLocked().layoutNeeded = true;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -6027,7 +5977,7 @@
if (w.mHasSurface) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
w.mOrientationChanging = true;
- mInnerFields.mOrientationChangeComplete = false;
+ mWindowPlacerLocked.mOrientationChangeComplete = false;
}
w.mLastFreezeDuration = 0;
}
@@ -7178,7 +7128,7 @@
case DO_TRAVERSAL: {
synchronized(mWindowMap) {
mTraversalScheduled = false;
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
} break;
@@ -7350,7 +7300,7 @@
Slog.w(TAG, "Force clearing orientation change: " + w);
}
}
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
break;
}
@@ -7364,7 +7314,7 @@
+ " mOpeningApps.size()=" + mOpeningApps.size()
+ " mClosingApps.size()=" + mClosingApps.size());
mAppTransition.setTimeout();
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
break;
@@ -7627,7 +7577,7 @@
case WALLPAPER_DRAW_PENDING_TIMEOUT: {
synchronized (mWindowMap) {
if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
}
@@ -8019,7 +7969,7 @@
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
private void configureDisplayPolicyLocked(DisplayContent displayContent) {
@@ -8207,7 +8157,7 @@
Arrays.fill(mRebuildTmp, null);
}
- private final void assignLayersLocked(WindowList windows) {
+ final void assignLayersLocked(WindowList windows) {
int N = windows.size();
int curBaseLayer = 0;
int curLayer = 0;
@@ -8277,253 +8227,6 @@
}
}
- private final void performLayoutAndPlaceSurfacesLocked() {
- int loopCount = 6;
- do {
- mTraversalScheduled = false;
- performLayoutAndPlaceSurfacesLockedLoop();
- mH.removeMessages(H.DO_TRAVERSAL);
- loopCount--;
- } while (mTraversalScheduled && loopCount > 0);
- mInnerFields.mWallpaperActionPending = false;
- }
-
- private boolean mInLayout = false;
- private final void performLayoutAndPlaceSurfacesLockedLoop() {
- if (mInLayout) {
- if (DEBUG) {
- throw new RuntimeException("Recursive call!");
- }
- Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
- + Debug.getCallers(3));
- 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;
- }
-
- if (!mDisplayReady) {
- // Not yet initialized, nothing to do.
- return;
- }
-
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
- mInLayout = true;
-
- boolean recoveringMemory = false;
- if (!mForceRemoves.isEmpty()) {
- recoveringMemory = true;
- // Wait a little bit for things to settle down, and off we go.
- while (!mForceRemoves.isEmpty()) {
- WindowState ws = mForceRemoves.remove(0);
- Slog.i(TAG, "Force removing: " + ws);
- removeWindowInnerLocked(ws);
- }
- Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
- Object tmp = new Object();
- synchronized (tmp) {
- try {
- tmp.wait(250);
- } catch (InterruptedException e) {
- }
- }
- }
-
- try {
- performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
-
- mInLayout = false;
-
- if (needsLayout()) {
- if (++mLayoutRepeatCount < 6) {
- requestTraversalLocked();
- } else {
- Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
- mLayoutRepeatCount = 0;
- }
- } else {
- mLayoutRepeatCount = 0;
- }
-
- if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
- mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
- mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
- }
- } catch (RuntimeException e) {
- mInLayout = false;
- Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
- }
-
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- }
-
- private final void performLayoutLockedInner(final DisplayContent displayContent,
- boolean initial, boolean updateInputWindows) {
- if (!displayContent.layoutNeeded) {
- return;
- }
- displayContent.layoutNeeded = false;
- WindowList windows = displayContent.getWindowList();
- boolean isDefaultDisplay = displayContent.isDefaultDisplay;
-
- DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
-
- if (mInputConsumer != null) {
- mInputConsumer.layout(dw, dh);
- }
-
- final int N = windows.size();
- int i;
-
- if (DEBUG_LAYOUT) {
- Slog.v(TAG, "-------------------------------------");
- Slog.v(TAG, "performLayout: needed="
- + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
- }
-
- mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
- if (isDefaultDisplay) {
- // Not needed on non-default displays.
- mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
- mScreenRect.set(0, 0, dw, dh);
- }
-
- mPolicy.getContentRectLw(mTmpContentRect);
- displayContent.resize(mTmpContentRect);
-
- int seq = mLayoutSeq+1;
- if (seq < 0) seq = 0;
- mLayoutSeq = seq;
-
- boolean behindDream = false;
-
- // First perform layout of any root windows (not attached
- // to another window).
- int topAttached = -1;
- for (i = N-1; i >= 0; i--) {
- final WindowState win = windows.get(i);
-
- // Don't do layout of a window if it is not visible, or
- // soon won't be visible, to avoid wasting time and funky
- // changes while a window is animating away.
- final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
- || win.isGoneForLayoutLw();
-
- if (DEBUG_LAYOUT && !win.mLayoutAttached) {
- Slog.v(TAG, "1ST PASS " + win
- + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
- + " mLayoutAttached=" + win.mLayoutAttached
- + " screen changed=" + win.isConfigChanged());
- final AppWindowToken atoken = win.mAppToken;
- if (gone) Slog.v(TAG, " GONE: mViewVisibility="
- + win.mViewVisibility + " mRelayoutCalled="
- + win.mRelayoutCalled + " hidden="
- + win.mRootToken.hidden + " hiddenRequested="
- + (atoken != null && atoken.hiddenRequested)
- + " mAttachedHidden=" + win.mAttachedHidden);
- else Slog.v(TAG, " VIS: mViewVisibility="
- + win.mViewVisibility + " mRelayoutCalled="
- + win.mRelayoutCalled + " hidden="
- + win.mRootToken.hidden + " hiddenRequested="
- + (atoken != null && atoken.hiddenRequested)
- + " mAttachedHidden=" + win.mAttachedHidden);
- }
-
- // If this view is GONE, then skip it -- keep the current
- // frame, and let the caller know so they can ignore it
- // if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal,
- // just don't display").
- if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || ((win.isConfigChanged() || win.setInsetsChanged()) &&
- ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (win.mHasSurface && win.mAppToken != null &&
- win.mAppToken.layoutConfigChanges)))) {
- if (!win.mLayoutAttached) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it
- // does stuff like hide the status bar we won't get a
- // bad transition when it goes away.
- behindDream = true;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mPolicy.layoutWindowLw(win, null);
- win.mLayoutSeq = seq;
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
- + win.mFrame + " mContainingFrame="
- + win.mContainingFrame + " mDisplayFrame="
- + win.mDisplayFrame);
- } else {
- if (topAttached < 0) topAttached = i;
- }
- }
- }
-
- boolean attachedBehindDream = false;
-
- // Now perform layout of attached windows, which usually
- // depend on the position of the window they are attached to.
- // XXX does not deal with windows that are attached to windows
- // that are themselves attached.
- for (i = topAttached; i >= 0; i--) {
- final WindowState win = windows.get(i);
-
- if (win.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
- + " mHaveFrame=" + win.mHaveFrame
- + " mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled);
- // If this view is GONE, then skip it -- keep the current
- // frame, and let the caller know so they can ignore it
- // if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal,
- // just don't display").
- if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
- continue;
- }
- if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
- || !win.mHaveFrame || win.mLayoutNeeded) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mPolicy.layoutWindowLw(win, win.mAttachedWindow);
- win.mLayoutSeq = seq;
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame="
- + win.mFrame + " mContainingFrame="
- + win.mContainingFrame + " mDisplayFrame="
- + win.mDisplayFrame);
- }
- } else if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it
- // does stuff like hide the status bar we won't get a
- // bad transition when it goes away.
- attachedBehindDream = behindDream;
- }
- }
-
- // Window frames may have changed. Tell the input dispatcher about it.
- mInputMonitor.setUpdateInputWindowsNeededLw();
- if (updateInputWindows) {
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
-
- mPolicy.finishLayoutLw();
- }
-
void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
// If the screen is currently frozen or off, then keep
// it frozen/off until this window draws at its new
@@ -8532,7 +8235,7 @@
if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
w.mOrientationChanging = true;
w.mLastFreezeDuration = 0;
- mInnerFields.mOrientationChangeComplete = false;
+ mWindowPlacerLocked.mOrientationChangeComplete = false;
if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
// XXX should probably keep timeout from
@@ -8545,411 +8248,9 @@
}
/**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- * @param windows List of windows on default display.
* @return bitmap indicating if another pass through layout must be made.
*/
- public int handleAppTransitionReadyLocked(WindowList windows) {
- int appsCount = mOpeningApps.size();
- if (!checkIfTransitionGoodToGo(appsCount)) {
- return 0;
- }
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
- int transit = mAppTransition.getAppTransition();
- if (mSkipAppTransitionAnimation) {
- transit = AppTransition.TRANSIT_UNSET;
- }
- mSkipAppTransitionAnimation = false;
- mNoAnimationNotifyOnTransitionFinished.clear();
-
- mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
-
- rebuildAppWindowListLocked();
-
- mInnerFields.mWallpaperMayChange = false;
-
- // The top-most window will supply the layout params,
- // and we will determine it below.
- LayoutParams animLp = null;
- int bestAnimLayer = -1;
- boolean fullscreenAnim = false;
- boolean voiceInteraction = false;
-
- final WindowState lowerWallpaperTarget =
- mWallpaperControllerLocked.getLowerWallpaperTarget();
- final WindowState upperWallpaperTarget =
- mWallpaperControllerLocked.getUpperWallpaperTarget();
-
- boolean openingAppHasWallpaper = false;
- boolean closingAppHasWallpaper = false;
- final AppWindowToken lowerWallpaperAppToken;
- final AppWindowToken upperWallpaperAppToken;
- if (lowerWallpaperTarget == null) {
- lowerWallpaperAppToken = upperWallpaperAppToken = null;
- } else {
- lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken;
- upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
- }
-
- int i;
- // Do a first pass through the tokens for two
- // things:
- // (1) Determine if both the closing and opening
- // app token sets are wallpaper targets, in which
- // case special animations are needed
- // (since the wallpaper needs to stay static
- // behind them).
- // (2) Find the layout params of the top-most
- // application window in the tokens, which is
- // what will control the animation theme.
- final int closingAppsCount = mClosingApps.size();
- appsCount = closingAppsCount + mOpeningApps.size();
- for (i = 0; i < appsCount; i++) {
- final AppWindowToken wtoken;
- if (i < closingAppsCount) {
- wtoken = mClosingApps.valueAt(i);
- if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
- closingAppHasWallpaper = true;
- }
- } else {
- wtoken = mOpeningApps.valueAt(i - closingAppsCount);
- if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
- openingAppHasWallpaper = true;
- }
- }
-
- voiceInteraction |= wtoken.voiceInteraction;
-
- if (wtoken.appFullscreen) {
- WindowState ws = wtoken.findMainWindow();
- if (ws != null) {
- animLp = ws.mAttrs;
- bestAnimLayer = ws.mLayer;
- fullscreenAnim = true;
- }
- } else if (!fullscreenAnim) {
- WindowState ws = wtoken.findMainWindow();
- if (ws != null) {
- if (ws.mLayer > bestAnimLayer) {
- animLp = ws.mAttrs;
- bestAnimLayer = ws.mLayer;
- }
- }
- }
- }
-
- transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
- closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
-
- // If all closing windows are obscured, then there is
- // no need to do an animation. This is the case, for
- // example, when this transition is being done behind
- // the lock screen.
- if (!mPolicy.allowAppAnimationsLw()) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "Animations disallowed by keyguard or dream.");
- animLp = null;
- }
-
- processApplicationsAnimatingInPlace(transit);
-
- AppWindowToken topClosingApp = null;
- int topClosingLayer = 0;
- appsCount = mClosingApps.size();
- for (i = 0; i < appsCount; i++) {
- AppWindowToken wtoken = mClosingApps.valueAt(i);
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- wtoken.inPendingTransaction = false;
- setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
- wtoken.updateReportedVisibilityLocked();
- // Force the allDrawn flag, because we want to start
- // this guy's animations regardless of whether it's
- // gotten drawn.
- wtoken.allDrawn = true;
- wtoken.deferClearAllDrawn = false;
- // Ensure that apps that are mid-starting are also scheduled to have their
- // starting windows removed after the animation is complete
- if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
- scheduleRemoveStartingWindowLocked(wtoken);
- }
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
- if (animLp != null) {
- int layer = -1;
- for (int j = 0; j < wtoken.windows.size(); j++) {
- WindowState win = wtoken.windows.get(j);
- if (win.mWinAnimator.mAnimLayer > layer) {
- layer = win.mWinAnimator.mAnimLayer;
- }
- }
- if (topClosingApp == null || layer > topClosingLayer) {
- topClosingApp = wtoken;
- topClosingLayer = layer;
- }
- }
- }
-
- AppWindowToken topOpeningApp = null;
- appsCount = mOpeningApps.size();
- for (i = 0; i < appsCount; i++) {
- AppWindowToken wtoken = mOpeningApps.valueAt(i);
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-
- if (!appAnimator.usingTransferredAnimation) {
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- }
- wtoken.inPendingTransaction = false;
- if (!setTokenVisibilityLocked(
- wtoken, animLp, true, transit, false, voiceInteraction)){
- // This token isn't going to be animating. Add it to the list of tokens to
- // be notified of app transition complete since the notification will not be
- // sent be the app window animator.
- mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
- }
- wtoken.updateReportedVisibilityLocked();
- wtoken.waitingToShow = false;
-
- appAnimator.mAllAppWinAnimators.clear();
- final int windowsCount = wtoken.allAppWindows.size();
- for (int j = 0; j < windowsCount; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
- mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
- int topOpeningLayer = 0;
- if (animLp != null) {
- int layer = -1;
- for (int j = 0; j < wtoken.windows.size(); j++) {
- WindowState win = wtoken.windows.get(j);
- if (win.mWinAnimator.mAnimLayer > layer) {
- layer = win.mWinAnimator.mAnimLayer;
- }
- }
- if (topOpeningApp == null || layer > topOpeningLayer) {
- topOpeningApp = wtoken;
- topOpeningLayer = layer;
- }
- }
- createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
- }
-
- AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
- topOpeningApp.mAppAnimator;
- AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
- topClosingApp.mAppAnimator;
-
- mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
- mAppTransition.postAnimationCallback();
- mAppTransition.clear();
-
- mOpeningApps.clear();
- mClosingApps.clear();
-
- // This has changed the visibility of windows, so perform
- // a new layout to get them all up-to-date.
- getDefaultDisplayContentLocked().layoutNeeded = true;
-
- // TODO(multidisplay): IMEs are only supported on the default display.
- if (windows == getDefaultWindowListLocked()
- && !moveInputMethodWindowsIfNeededLocked(true)) {
- assignLayersLocked(windows);
- }
- updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
- mFocusMayChange = false;
- notifyActivityDrawnForKeyguard();
- return WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
- | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
-
- }
-
- private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
- boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget,
- WindowState upperWallpaperTarget) {
- // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
- final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
- final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
- ? null : wallpaperTarget;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New wallpaper target=" + wallpaperTarget
- + ", oldWallpaper=" + oldWallpaper
- + ", lower target=" + lowerWallpaperTarget
- + ", upper target=" + upperWallpaperTarget);
- mAnimateWallpaperWithTarget = false;
- if (closingAppHasWallpaper && openingAppHasWallpaper) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
- switch (transit) {
- case AppTransition.TRANSIT_ACTIVITY_OPEN:
- case AppTransition.TRANSIT_TASK_OPEN:
- case AppTransition.TRANSIT_TASK_TO_FRONT:
- transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
- break;
- case AppTransition.TRANSIT_ACTIVITY_CLOSE:
- case AppTransition.TRANSIT_TASK_CLOSE:
- case AppTransition.TRANSIT_TASK_TO_BACK:
- transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
- break;
- }
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit: " + AppTransition.appTransitionToString(transit));
- } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
- && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
- // We are transitioning from an activity with
- // a wallpaper to one without.
- transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit away from wallpaper: "
- + AppTransition.appTransitionToString(transit));
- } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()) {
- // We are transitioning from an activity without
- // a wallpaper to now showing the wallpaper
- transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "New transit into wallpaper: "
- + AppTransition.appTransitionToString(transit));
- } else {
- mAnimateWallpaperWithTarget = true;
- }
- return transit;
- }
-
- private void processApplicationsAnimatingInPlace(int transit) {
- if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
- // Find the focused window
- final WindowState win =
- findFocusedWindowLocked(getDefaultDisplayContentLocked());
- if (win != null) {
- final AppWindowToken wtoken = win.mAppToken;
- final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
- appAnimator.clearThumbnail();
- appAnimator.animation = null;
- updateTokenInPlaceLocked(wtoken, transit);
- wtoken.updateReportedVisibilityLocked();
-
- appAnimator.mAllAppWinAnimators.clear();
- final int N = wtoken.allAppWindows.size();
- for (int j = 0; j < N; j++) {
- appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
- }
- mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
- mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
- }
- }
- }
-
- private boolean checkIfTransitionGoodToGo(int appsCount) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "Checking " + appsCount + " opening apps (frozen="
- + mDisplayFrozen + " timeout="
- + mAppTransition.isTimeout() + ")...");
- if (!mAppTransition.isTimeout()) {
- for (int i = 0; i < appsCount; i++) {
- AppWindowToken wtoken = mOpeningApps.valueAt(i);
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "Check opening app=" + wtoken + ": allDrawn="
- + wtoken.allDrawn + " startingDisplayed="
- + wtoken.startingDisplayed + " startingMoved="
- + wtoken.startingMoved);
- if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
- return false;
- }
- }
-
- // If the wallpaper is visible, we need to check it's ready too.
- return !mWallpaperControllerLocked.isWallpaperVisible() ||
- mWallpaperControllerLocked.wallpaperTransitionReady();
- }
- return true;
- }
-
- private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
- int openingLayer, int closingLayer) {
- AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
- if (openingAppAnimator == null || openingAppAnimator.animation == null) {
- return;
- }
- final int taskId = appToken.mTask.mTaskId;
- Bitmap thumbnailHeader = mAppTransition.getAppTransitionThumbnailHeader(taskId);
- if (thumbnailHeader == null || thumbnailHeader.getConfig() == Config.ALPHA_8) {
- return;
- }
- // This thumbnail animation is very special, we need to have
- // an extra surface with the thumbnail included with the animation.
- Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight());
- try {
- // TODO(multi-display): support other displays
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final Display display = displayContent.getDisplay();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
- // Create a new surface for the thumbnail
- SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
- "thumbnail anim", dirty.width(), dirty.height(),
- PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- surfaceControl.setLayerStack(display.getLayerStack());
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
- }
-
- // Draw the thumbnail onto the surface
- Surface drawSurface = new Surface();
- drawSurface.copyFrom(surfaceControl);
- Canvas c = drawSurface.lockCanvas(dirty);
- c.drawBitmap(thumbnailHeader, 0, 0, null);
- drawSurface.unlockCanvasAndPost(c);
- drawSurface.release();
-
- // Get the thumbnail animation
- Animation anim;
- if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
- // If this is a multi-window scenario, we use the windows frame as
- // destination of the thumbnail header animation. If this is a full screen
- // window scenario, we use the whole display as the target.
- WindowState win = appToken.findMainWindow();
- Rect appRect = win != null ? win.getContentFrameLw() :
- new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
- // For the new aspect-scaled transition, we want it to always show
- // above the animating opening/closing window, and we want to
- // synchronize its thumbnail surface with the surface for the
- // open/close animation (only on the way down)
- anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
- thumbnailHeader, taskId);
- Log.d(TAG, "assigning thumbnail force above layer: " + openingLayer + " " +
- closingLayer);
- openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
- openingAppAnimator.deferThumbnailDestruction =
- !mAppTransition.isNextThumbnailTransitionScaleUp();
- } else {
- anim = mAppTransition.createThumbnailScaleAnimationLocked(
- displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader);
- }
- anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
-
- openingAppAnimator.thumbnail = surfaceControl;
- openingAppAnimator.thumbnailLayer = openingLayer;
- openingAppAnimator.thumbnailAnimation = anim;
- mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect);
- openingAppAnimator.thumbnailX = mTmpStartRect.left;
- openingAppAnimator.thumbnailY = mTmpStartRect.top;
- } catch (OutOfResourcesException e) {
- Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
- + " h=" + dirty.height(), e);
- openingAppAnimator.clearThumbnail();
- }
- }
-
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- * @return bitmap indicating if another pass through layout must be made.
- */
- private int handleAnimatingStoppedAndTransitionLocked() {
+ int handleAnimatingStoppedAndTransitionLocked() {
int changes = 0;
mAppTransition.setIdle();
@@ -8979,7 +8280,7 @@
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
"Wallpaper layer changed: assigning layers + relayout");
moveInputMethodWindowsIfNeededLocked(true);
- mInnerFields.mWallpaperMayChange = true;
+ mWindowPlacerLocked.mWallpaperMayChange = true;
// Since the window list has been rebuilt, focus might
// have to be recomputed since the actual order of windows
// might have changed again.
@@ -8988,7 +8289,7 @@
return changes;
}
- private void updateResizingWindows(final WindowState w) {
+ void updateResizingWindows(final WindowState w) {
final WindowStateAnimator winAnimator = w.mWinAnimator;
if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
w.setInsetsChanged();
@@ -9060,707 +8361,6 @@
}
}
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- * @param w WindowState this method is applied to.
- * @param innerDw Width of app window.
- * @param innerDh Height of app window.
- */
- private void handleNotObscuredLocked(final WindowState w,
- final int innerDw, final int innerDh) {
- final WindowManager.LayoutParams attrs = w.mAttrs;
- final int attrFlags = attrs.flags;
- final boolean canBeSeen = w.isDisplayedLw();
- final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
-
- if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
- // This window completely covers everything behind it,
- // so we want to leave all of them as undimmed (for
- // performance reasons).
- mInnerFields.mObscured = true;
- }
-
- if (w.mHasSurface) {
- if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
- mInnerFields.mHoldScreen = w.mSession;
- }
- if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
- && mInnerFields.mScreenBrightness < 0) {
- mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
- }
- if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
- && mInnerFields.mButtonBrightness < 0) {
- mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
- }
- if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
- && mInnerFields.mUserActivityTimeout < 0) {
- mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
- }
-
- final int type = attrs.type;
- if (canBeSeen
- && (type == TYPE_SYSTEM_DIALOG
- || type == TYPE_SYSTEM_ERROR
- || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
- mInnerFields.mSyswin = true;
- }
-
- if (canBeSeen) {
- // This function assumes that the contents of the default display are
- // processed first before secondary displays.
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && displayContent.isDefaultDisplay) {
- // While a dream or keyguard is showing, obscure ordinary application
- // content on secondary displays (by forcibly enabling mirroring unless
- // there is other content we want to show) but still allow opaque
- // keyguard dialogs to be shown.
- if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
- }
- mInnerFields.mDisplayHasContent = true;
- } else if (displayContent != null &&
- (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
- || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
- // Allow full screen keyguard presentation dialogs to be seen.
- mInnerFields.mDisplayHasContent = true;
- }
- if (mInnerFields.mPreferredRefreshRate == 0
- && w.mAttrs.preferredRefreshRate != 0) {
- mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
- }
- if (mInnerFields.mPreferredModeId == 0
- && w.mAttrs.preferredDisplayModeId != 0) {
- mInnerFields.mPreferredModeId = w.mAttrs.preferredDisplayModeId;
- }
- }
- }
- }
-
- private void handleFlagDimBehind(WindowState w) {
- final WindowManager.LayoutParams attrs = w.mAttrs;
- if ((attrs.flags & FLAG_DIM_BEHIND) != 0
- && w.isDisplayedLw()
- && !w.mExiting) {
- final WindowStateAnimator winAnimator = w.mWinAnimator;
- final Task task = w.getTask();
- if (task == null) {
- return;
- }
- task.setContinueDimming();
- if (!task.isDimming(winAnimator)) {
- if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
- task.startDimmingIfNeeded(winAnimator);
- }
- }
- }
-
- private void updateAllDrawnLocked(DisplayContent displayContent) {
- // See if any windows have been drawn, so they (and others
- // associated with them) can now be shown.
- ArrayList<TaskStack> stacks = displayContent.getStacks();
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
- for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- final AppWindowToken wtoken = tokens.get(tokenNdx);
- if (!wtoken.allDrawn) {
- int numInteresting = wtoken.numInterestingWindows;
- if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "allDrawn: " + wtoken
- + " interesting=" + numInteresting
- + " drawn=" + wtoken.numDrawnWindows);
- wtoken.allDrawn = true;
- // Force an additional layout pass where WindowStateAnimator#
- // commitFinishDrawingLocked() will call performShowLocked().
- displayContent.layoutNeeded = true;
- mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
- }
- }
- }
- }
- }
- }
-
- // "Something has changed! Let's make it correct now."
- private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
- if (DEBUG_WINDOW_TRACE) {
- Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
- + Debug.getCallers(3));
- }
-
- int i;
- boolean updateInputWindowsNeeded = false;
-
- if (mFocusMayChange) {
- mFocusMayChange = false;
- updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
- false /*updateInputWindows*/);
- }
-
- // Initialize state of exiting tokens.
- final int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
- displayContent.mExitingTokens.get(i).hasVisible = false;
- }
- }
-
- for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- exitingAppTokens.get(tokenNdx).hasVisible = false;
- }
- }
-
- mInnerFields.mHoldScreen = null;
- mInnerFields.mScreenBrightness = -1;
- mInnerFields.mButtonBrightness = -1;
- mInnerFields.mUserActivityTimeout = -1;
- mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
-
- mTransactionSequence++;
-
- final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
- final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
- final int defaultDw = defaultInfo.logicalWidth;
- final int defaultDh = defaultInfo.logicalHeight;
-
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
- SurfaceControl.openTransaction();
- try {
-
- if (mWatermark != null) {
- mWatermark.positionSurface(defaultDw, defaultDh);
- }
- if (mStrictModeFlash != null) {
- mStrictModeFlash.positionSurface(defaultDw, defaultDh);
- }
- if (mCircularDisplayMask != null) {
- mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
- }
- if (mEmulatorDisplayOverlay != null) {
- mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation);
- }
-
- boolean focusDisplayed = false;
-
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- boolean updateAllDrawn = false;
- WindowList windows = displayContent.getWindowList();
- DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int displayId = displayContent.getDisplayId();
- final int dw = displayInfo.logicalWidth;
- final int dh = displayInfo.logicalHeight;
- final int innerDw = displayInfo.appWidth;
- final int innerDh = displayInfo.appHeight;
- final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
-
- // Reset for each display.
- mInnerFields.mDisplayHasContent = false;
- mInnerFields.mPreferredRefreshRate = 0;
- mInnerFields.mPreferredModeId = 0;
-
- int repeats = 0;
- do {
- repeats++;
- if (repeats > 6) {
- Slog.w(TAG, "Animation repeat aborted after too many iterations");
- displayContent.layoutNeeded = false;
- break;
- }
-
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
- displayContent.pendingLayoutChanges);
-
- if ((displayContent.pendingLayoutChanges &
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
- mWallpaperControllerLocked.adjustWallpaperWindows()) {
- assignLayersLocked(windows);
- displayContent.layoutNeeded = true;
- }
-
- if (isDefaultDisplay && (displayContent.pendingLayoutChanges
- & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
- if (updateOrientationFromAppTokensLocked(true)) {
- displayContent.layoutNeeded = true;
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- }
- }
-
- if ((displayContent.pendingLayoutChanges
- & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
- displayContent.layoutNeeded = true;
- }
-
- // FIRST LOOP: Perform a layout, if needed.
- if (repeats < LAYOUT_REPEAT_THRESHOLD) {
- performLayoutLockedInner(displayContent, repeats == 1,
- false /*updateInputWindows*/);
- } else {
- Slog.w(TAG, "Layout repeat skipped after too many iterations");
- }
-
- // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
- // it is animating.
- displayContent.pendingLayoutChanges = 0;
-
- if (isDefaultDisplay) {
- mPolicy.beginPostLayoutPolicyLw(dw, dh);
- for (i = windows.size() - 1; i >= 0; i--) {
- WindowState w = windows.get(i);
- if (w.mHasSurface) {
- mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.mAttachedWindow);
- }
- }
- displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
- "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
- }
- } while (displayContent.pendingLayoutChanges != 0);
-
- mInnerFields.mObscured = false;
- mInnerFields.mSyswin = false;
- displayContent.resetDimming();
-
- // Only used if default window
- final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
-
- final int N = windows.size();
- for (i=N-1; i>=0; i--) {
- WindowState w = windows.get(i);
- final Task task = w.getTask();
- if (task == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) {
- continue;
- }
-
- final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
-
- // Update effect.
- w.mObscured = mInnerFields.mObscured;
- if (!mInnerFields.mObscured) {
- handleNotObscuredLocked(w, innerDw, innerDh);
- }
-
- if (task != null && !task.getContinueDimming()) {
- handleFlagDimBehind(w);
- }
-
- if (isDefaultDisplay && obscuredChanged
- && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
- // This is the wallpaper target and its obscured state
- // changed... make sure the current wallaper's visibility
- // has been updated accordingly.
- mWallpaperControllerLocked.updateWallpaperVisibility();
- }
-
- final WindowStateAnimator winAnimator = w.mWinAnimator;
-
- // If the window has moved due to its containing content frame changing, then
- // notify the listeners and optionally animate it.
- if (w.hasMoved()) {
- // Frame has moved, containing content frame has also moved, and we're not
- // currently animating... let's do something.
- final int left = w.mFrame.left;
- final int top = w.mFrame.top;
- if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) {
- Animation a = AnimationUtils.loadAnimation(mContext,
- com.android.internal.R.anim.window_move_from_decor);
- winAnimator.setAnimation(a);
- winAnimator.mAnimDw = w.mLastFrame.left - left;
- winAnimator.mAnimDh = w.mLastFrame.top - top;
- winAnimator.mAnimateMove = true;
- winAnimator.mAnimatingMove = true;
- }
-
- //TODO (multidisplay): Accessibility supported only for the default display.
- if (mAccessibilityController != null
- && displayId == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onSomeWindowResizedOrMovedLocked();
- }
-
- try {
- w.mClient.moved(left, top);
- } catch (RemoteException e) {
- }
- }
-
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
- w.mContentChanged = false;
-
- // Moved from updateWindowsAndWallpaperLocked().
- if (w.mHasSurface) {
- // Take care of the window being ready to display.
- final boolean committed =
- winAnimator.commitFinishDrawingLocked();
- if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that
- // point hide the lock screen. So we need to
- // redo the layout to let the phone window manager
- // make this happen.
- displayContent.pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
- }
- }
- if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "First draw done in potential wallpaper target " + w);
- mInnerFields.mWallpaperMayChange = true;
- displayContent.pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- debugLayoutRepeats(
- "wallpaper and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
- }
- }
- }
-
- winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
- }
-
- final AppWindowToken atoken = w.mAppToken;
- if (DEBUG_STARTING_WINDOW && atoken != null
- && w == atoken.startingWindow) {
- Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
- + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
- + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
- }
- if (atoken != null
- && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
- if (atoken.lastTransactionSequence != mTransactionSequence) {
- atoken.lastTransactionSequence = mTransactionSequence;
- atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
- atoken.startingDisplayed = false;
- }
- if ((w.isOnScreenIgnoringKeyguard()
- || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
- && !w.mExiting && !w.mDestroying) {
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
- + ", isAnimating=" + winAnimator.isAnimating());
- if (!w.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
- + " pv=" + w.mPolicyVisibility
- + " mDrawState=" + winAnimator.drawStateToString()
- + " ah=" + w.mAttachedHidden
- + " th=" + atoken.hiddenRequested
- + " a=" + winAnimator.mAnimating);
- }
- }
- if (w != atoken.startingWindow) {
- if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
- atoken.numInterestingWindows++;
- if (w.isDrawnLw()) {
- atoken.numDrawnWindows++;
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
- "tokenMayBeDrawn: " + atoken
- + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
- updateAllDrawn = true;
- }
- }
- } else if (w.isDrawnLw()) {
- atoken.startingDisplayed = true;
- }
- }
- }
-
- if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
- && w.isDisplayedLw()) {
- focusDisplayed = true;
- }
-
- updateResizingWindows(w);
- }
-
- mDisplayManagerInternal.setDisplayProperties(displayId,
- mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate,
- mInnerFields.mPreferredModeId,
- true /* inTraversal, must call performTraversalInTrans... below */);
-
- getDisplayContentLocked(displayId).stopDimmingIfNeeded();
-
- if (updateAllDrawn) {
- updateAllDrawnLocked(displayContent);
- }
- }
-
- if (focusDisplayed) {
- mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
- }
-
- // Give the display manager a chance to adjust properties
- // like display rotation if it needs to.
- mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
-
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
- } finally {
- SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
- }
-
- final WindowList defaultWindows = defaultDisplay.getWindowList();
-
- // If we are ready to perform an app transition, check through
- // all of the app tokens to be shown and see if they are ready
- // to go.
- if (mAppTransition.isReady()) {
- defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
- defaultDisplay.pendingLayoutChanges);
- }
-
- if (!mAnimator.mAppWindowAnimating && mAppTransition.isRunning()) {
- // We have finished the animation of an app transition. To do
- // this, we have delayed a lot of operations like showing and
- // hiding apps, moving apps in Z-order, etc. The app token list
- // reflects the correct Z-order, but the window list may now
- // be out of sync with it. So here we will just rebuild the
- // entire app window list. Fun!
- defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
- defaultDisplay.pendingLayoutChanges);
- }
-
- if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
- && !mAppTransition.isReady()) {
- // At this point, there was a window with a wallpaper that
- // was force hiding other windows behind it, but now it
- // is going away. This may be simple -- just animate
- // away the wallpaper and its window -- or it may be
- // hard -- the wallpaper now needs to be shown behind
- // something that was hidden.
- defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
- defaultDisplay.pendingLayoutChanges);
- }
- mInnerFields.mWallpaperForceHidingChanged = false;
-
- if (mInnerFields.mWallpaperMayChange) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting");
- defaultDisplay.pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
- defaultDisplay.pendingLayoutChanges);
- }
-
- if (mFocusMayChange) {
- mFocusMayChange = false;
- if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
- false /*updateInputWindows*/)) {
- updateInputWindowsNeeded = true;
- defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
- }
- }
-
- if (needsLayout()) {
- defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
- defaultDisplay.pendingLayoutChanges);
- }
-
- for (i = mResizingWindows.size() - 1; i >= 0; i--) {
- WindowState win = mResizingWindows.get(i);
- if (win.mAppFreezing) {
- // Don't remove this window until rotation has completed.
- continue;
- }
- win.reportResized();
- mResizingWindows.remove(i);
- }
-
- if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
- "With display frozen, orientationChangeComplete="
- + mInnerFields.mOrientationChangeComplete);
- if (mInnerFields.mOrientationChangeComplete) {
- if (mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
- mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
- mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
- mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
- }
- stopFreezingDisplayLocked();
- }
-
- // Destroy the surface of any windows that are no longer visible.
- boolean wallpaperDestroyed = false;
- i = mDestroySurface.size();
- if (i > 0) {
- do {
- i--;
- WindowState win = mDestroySurface.get(i);
- win.mDestroying = false;
- if (mInputMethodWindow == win) {
- mInputMethodWindow = null;
- }
- if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
- wallpaperDestroyed = true;
- }
- win.mWinAnimator.destroySurfaceLocked();
- } while (i > 0);
- mDestroySurface.clear();
- }
-
- // Time to remove any exiting tokens?
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
- for (i = exitingTokens.size() - 1; i >= 0; i--) {
- WindowToken token = exitingTokens.get(i);
- if (!token.hasVisible) {
- exitingTokens.remove(i);
- if (token.windowType == TYPE_WALLPAPER) {
- mWallpaperControllerLocked.removeWallpaperToken(token);
- }
- }
- }
- }
-
- // Time to remove any exiting applications?
- for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
- AppWindowToken token = exitingAppTokens.get(i);
- if (!token.hasVisible && !mClosingApps.contains(token) &&
- (!token.mIsExiting || token.allAppWindows.isEmpty())) {
- // Make sure there is no animation running on this token,
- // so any windows associated with it will be removed as
- // soon as their animations are complete
- token.mAppAnimator.clearAnimation();
- token.mAppAnimator.animating = false;
- if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
- "performLayout: App token exiting now removed" + token);
- token.removeAppFromTaskLocked();
- }
- }
- }
-
- if (wallpaperDestroyed) {
- defaultDisplay.pendingLayoutChanges |=
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- defaultDisplay.layoutNeeded = true;
- }
-
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- if (displayContent.pendingLayoutChanges != 0) {
- displayContent.layoutNeeded = true;
- }
- }
-
- // Finally update all input windows now that the window changes have stabilized.
- mInputMonitor.updateInputWindowsLw(true /*force*/);
-
- setHoldScreenLocked(mInnerFields.mHoldScreen);
- if (!mDisplayFrozen) {
- if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
- mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
- } else {
- mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mInnerFields.mScreenBrightness));
- }
- if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
- mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
- } else {
- mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
- toBrightnessOverride(mInnerFields.mButtonBrightness));
- }
- mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
- mInnerFields.mUserActivityTimeout);
- }
-
- if (mTurnOnScreen) {
- if (mAllowTheaterModeWakeFromLayout
- || Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0) == 0) {
- if (DEBUG_VISIBILITY || DEBUG_POWER) {
- Slog.v(TAG, "Turning screen on after layout!");
- }
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.wm:TURN_ON");
- }
- mTurnOnScreen = false;
- }
-
- if (mInnerFields.mUpdateRotation) {
- if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
- if (updateRotationUncheckedLocked(false)) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- } else {
- mInnerFields.mUpdateRotation = false;
- }
- }
-
- if (mWaitingForDrawnCallback != null ||
- (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
- !mInnerFields.mUpdateRotation)) {
- checkDrawnWindowsLocked();
- }
-
- final int N = mPendingRemove.size();
- if (N > 0) {
- if (mPendingRemoveTmp.length < N) {
- mPendingRemoveTmp = new WindowState[N+10];
- }
- mPendingRemove.toArray(mPendingRemoveTmp);
- mPendingRemove.clear();
- DisplayContentList displayList = new DisplayContentList();
- for (i = 0; i < N; i++) {
- WindowState w = mPendingRemoveTmp[i];
- removeWindowInnerLocked(w);
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && !displayList.contains(displayContent)) {
- displayList.add(displayContent);
- }
- }
-
- for (DisplayContent displayContent : displayList) {
- assignLayersLocked(displayContent.getWindowList());
- displayContent.layoutNeeded = true;
- }
- }
-
- // Remove all deferred displays stacks, tasks, and activities.
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
- }
-
- if (updateInputWindowsNeeded) {
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- }
- setFocusTaskRegion();
-
- // Check to see if we are now in a state where the screen should
- // be enabled, because the window obscured flags have changed.
- enableScreenIfNeededLocked();
-
- scheduleAnimationLocked();
-
- if (DEBUG_WINDOW_TRACE) {
- Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
- + mAnimator.mAnimating);
- }
- }
-
- private int toBrightnessOverride(float value) {
- return (int)(value * PowerManager.BRIGHTNESS_ON);
- }
-
void checkDrawnWindowsLocked() {
if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
return;
@@ -9829,7 +8429,7 @@
}
}
- private boolean needsLayout() {
+ boolean needsLayout() {
final int numDisplays = mDisplayContents.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
@@ -9840,41 +8440,6 @@
return false;
}
- boolean copyAnimToLayoutParamsLocked() {
- boolean doRequest = false;
-
- final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
- if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
- mInnerFields.mUpdateRotation = true;
- doRequest = true;
- }
- if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
- mInnerFields.mWallpaperMayChange = true;
- doRequest = true;
- }
- if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
- mInnerFields.mWallpaperForceHidingChanged = true;
- doRequest = true;
- }
- if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
- mInnerFields.mOrientationChangeComplete = false;
- } else {
- mInnerFields.mOrientationChangeComplete = true;
- mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
- if (mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
- doRequest = true;
- }
- }
- if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
- mTurnOnScreen = true;
- }
- if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
- mInnerFields.mWallpaperActionPending = true;
- }
-
- return doRequest;
- }
-
/** If a window that has an animation specifying a colored background and the current wallpaper
* is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
* suddenly disappear. */
@@ -9998,7 +8563,7 @@
return leakedSurface || killedApps;
}
- private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
+ boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
WindowState newFocus = computeFocusedWindowLocked();
if (mCurrentFocus != newFocus) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
@@ -10027,7 +8592,8 @@
if (imWindowChanged && oldFocus != mInputMethodWindow) {
// Focus of the input method window changed. Perform layout if needed.
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
- performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
+ mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
+ updateInputWindows);
focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
} else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
// Client will do the layout, but we need to assign layers
@@ -10040,7 +8606,8 @@
// The change in focus caused us to need to do a layout. Okay.
displayContent.layoutNeeded = true;
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
- performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
+ mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
+ updateInputWindows);
}
}
@@ -10068,7 +8635,7 @@
return null;
}
- private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
+ WindowState findFocusedWindowLocked(DisplayContent displayContent) {
final WindowList windows = displayContent.getWindowList();
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
@@ -10192,7 +8759,7 @@
}
}
- private void stopFreezingDisplayLocked() {
+ void stopFreezingDisplayLocked() {
if (!mDisplayFrozen) {
return;
}
@@ -10399,7 +8966,7 @@
synchronized (mWindowMap) {
int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
updateStatusBarVisibilityLocked(visibility);
- performLayoutAndPlaceSurfacesLocked();
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -11013,13 +9580,6 @@
synchronized (mWindowMap) { }
}
- void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
- if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
- Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
- Integer.toHexString(pendingLayoutChanges));
- }
- }
-
private DisplayContent newDisplayContentLocked(final Display display) {
DisplayContent displayContent = new DisplayContent(display, this);
final int displayId = display.getDisplayId();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 761e5eb..7e15dd5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -18,6 +18,7 @@
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
@@ -1255,6 +1256,20 @@
mInputWindowHandle.inputChannel = null;
}
+ void handleFlagDimBehind() {
+ if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isDisplayedLw() && !mExiting) {
+ final Task task = getTask();
+ if (task == null) {
+ return;
+ }
+ task.setContinueDimming();
+ if (!task.isDimming(mWinAnimator)) {
+ if (WindowManagerService.localLOGV) Slog.v(TAG, "Win " + this + " start dimming.");
+ task.startDimmingIfNeeded(mWinAnimator);
+ }
+ }
+ }
+
private class DeathRecipient implements IBinder.DeathRecipient {
@Override
public void binderDied() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 109e627..a79d2aa 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -27,8 +27,8 @@
import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerService.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerService.localLOGV;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
import android.content.Context;
import android.graphics.Matrix;
@@ -424,8 +424,9 @@
finishExit();
final int displayId = mWin.getDisplayId();
mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
- if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats(
- "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS)
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
if (mWin.mAppToken != null) {
mWin.mAppToken.updateReportedVisibilityLocked();
@@ -1184,7 +1185,7 @@
+ " screen=" + (screenAnimation ?
screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
return;
- } else if (mIsWallpaper && mService.mInnerFields.mWallpaperActionPending) {
+ } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
new file mode 100644
index 0000000..ce07a9d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -0,0 +1,1523 @@
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.WindowManagerService.DEBUG;
+import static com.android.server.wm.WindowManagerService.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
+import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
+import static com.android.server.wm.WindowManagerService.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerService.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerService.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerService.H.*;
+import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
+import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
+import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerService.TAG;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.Debug;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+import java.util.ArrayList;
+
+/**
+ * Positions windows and their surfaces.
+ *
+ * It sets positions of windows by calculating their frames and then applies this by positioning
+ * surfaces according to these frames. Z layer is still assigned withing WindowManagerService.
+ */
+class WindowSurfacePlacer {
+ private final WindowManagerService mService;
+ private final WallpaperController mWallpaperControllerLocked;
+
+ private boolean mInLayout = false;
+
+ /** Only do a maximum of 6 repeated layouts. After that quit */
+ private int mLayoutRepeatCount;
+
+ static final int SET_UPDATE_ROTATION = 1 << 0;
+ static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
+ static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
+ static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
+ static final int SET_TURN_ON_SCREEN = 1 << 4;
+ static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5;
+
+ boolean mWallpaperMayChange = false;
+ boolean mOrientationChangeComplete = true;
+ boolean mWallpaperActionPending = false;
+
+ private boolean mWallpaperForceHidingChanged = false;
+ private Object mLastWindowFreezeSource = null;
+ private Session mHoldScreen = null;
+ private boolean mObscured = false;
+ private boolean mSyswin = false;
+ private float mScreenBrightness = -1;
+ private float mButtonBrightness = -1;
+ private long mUserActivityTimeout = -1;
+ private boolean mUpdateRotation = false;
+ private final Rect mTmpStartRect = new Rect();
+
+ // Set to true when the display contains content to show the user.
+ // When false, the display manager may choose to mirror or blank the display.
+ private boolean mDisplayHasContent = false;
+
+ // Only set while traversing the default display based on its content.
+ // Affects the behavior of mirroring on secondary displays.
+ private boolean mObscureApplicationContentOnSecondaryDisplays = false;
+
+ private float mPreferredRefreshRate = 0;
+
+ private int mPreferredModeId = 0;
+
+ public WindowSurfacePlacer(WindowManagerService service) {
+ mService = service;
+ mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
+ }
+
+ final void performSurfacePlacement() {
+ int loopCount = 6;
+ do {
+ mService.mTraversalScheduled = false;
+ performSurfacePlacementLoop();
+ mService.mH.removeMessages(DO_TRAVERSAL);
+ loopCount--;
+ } while (mService.mTraversalScheduled && loopCount > 0);
+ mWallpaperActionPending = false;
+ }
+
+ private void performSurfacePlacementLoop() {
+ if (mInLayout) {
+ if (DEBUG) {
+ throw new RuntimeException("Recursive call!");
+ }
+ Slog.w(TAG,
+ "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
+ + Debug.getCallers(3));
+ return;
+ }
+
+ if (mService.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;
+ }
+
+ if (!mService.mDisplayReady) {
+ // Not yet initialized, nothing to do.
+ return;
+ }
+
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
+ mInLayout = true;
+
+ boolean recoveringMemory = false;
+ if (!mService.mForceRemoves.isEmpty()) {
+ recoveringMemory = true;
+ // Wait a little bit for things to settle down, and off we go.
+ while (!mService.mForceRemoves.isEmpty()) {
+ WindowState ws = mService.mForceRemoves.remove(0);
+ Slog.i(TAG, "Force removing: " + ws);
+ mService.removeWindowInnerLocked(ws);
+ }
+ Slog.w(TAG,
+ "Due to memory failure, waiting a bit for next layout");
+ Object tmp = new Object();
+ synchronized (tmp) {
+ try {
+ tmp.wait(250);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ try {
+ performSurfacePlacementInner(recoveringMemory);
+
+ mInLayout = false;
+
+ if (mService.needsLayout()) {
+ if (++mLayoutRepeatCount < 6) {
+ mService.requestTraversalLocked();
+ } else {
+ Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
+ mLayoutRepeatCount = 0;
+ }
+ } else {
+ mLayoutRepeatCount = 0;
+ }
+
+ if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
+ mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
+ mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
+ }
+ } catch (RuntimeException e) {
+ mInLayout = false;
+ Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
+ }
+
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+
+ void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
+ if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
+ Slog.v(TAG, "Layouts looping: " + msg +
+ ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges));
+ }
+ }
+
+ // "Something has changed! Let's make it correct now."
+ private void performSurfacePlacementInner(boolean recoveringMemory) {
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.v(TAG,
+ "performSurfacePlacementInner: entry. Called by "
+ + Debug.getCallers(3));
+ }
+
+ int i;
+ boolean updateInputWindowsNeeded = false;
+
+ if (mService.mFocusMayChange) {
+ mService.mFocusMayChange = false;
+ updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
+ UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+ }
+
+ // Initialize state of exiting tokens.
+ final int numDisplays = mService.mDisplayContents.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
+ for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
+ displayContent.mExitingTokens.get(i).hasVisible = false;
+ }
+ }
+
+ for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+ // Initialize state of exiting applications.
+ final AppTokenList exitingAppTokens =
+ mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+ for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+ exitingAppTokens.get(tokenNdx).hasVisible = false;
+ }
+ }
+
+ mHoldScreen = null;
+ mScreenBrightness = -1;
+ mButtonBrightness = -1;
+ mUserActivityTimeout = -1;
+ mObscureApplicationContentOnSecondaryDisplays = false;
+
+ mService.mTransactionSequence++;
+
+ final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
+ final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
+ final int defaultDw = defaultInfo.logicalWidth;
+ final int defaultDh = defaultInfo.logicalHeight;
+
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
+ SurfaceControl.openTransaction();
+ try {
+
+ if (mService.mWatermark != null) {
+ mService.mWatermark.positionSurface(defaultDw, defaultDh);
+ }
+ if (mService.mStrictModeFlash != null) {
+ mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+ }
+ if (mService.mCircularDisplayMask != null) {
+ mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
+ mService.mRotation);
+ }
+ if (mService.mEmulatorDisplayOverlay != null) {
+ mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
+ mService.mRotation);
+ }
+
+ boolean focusDisplayed = false;
+
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
+ boolean updateAllDrawn = false;
+ WindowList windows = displayContent.getWindowList();
+ DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final int displayId = displayContent.getDisplayId();
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+ final int innerDw = displayInfo.appWidth;
+ final int innerDh = displayInfo.appHeight;
+ final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+
+ // Reset for each display.
+ mDisplayHasContent = false;
+ mPreferredRefreshRate = 0;
+ mPreferredModeId = 0;
+
+ int repeats = 0;
+ do {
+ repeats++;
+ if (repeats > 6) {
+ Slog.w(TAG, "Animation repeat aborted after too many iterations");
+ displayContent.layoutNeeded = false;
+ break;
+ }
+
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
+ "On entry to LockedInner", displayContent.pendingLayoutChanges);
+
+ if ((displayContent.pendingLayoutChanges &
+ FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
+ mWallpaperControllerLocked.adjustWallpaperWindows()) {
+ mService.assignLayersLocked(windows);
+ displayContent.layoutNeeded = true;
+ }
+
+ if (isDefaultDisplay && (displayContent.pendingLayoutChanges
+ & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ "Computing new config from layout");
+ if (mService.updateOrientationFromAppTokensLocked(true)) {
+ displayContent.layoutNeeded = true;
+ mService.mH.sendEmptyMessage(
+ SEND_NEW_CONFIGURATION);
+ }
+ }
+
+ if ((displayContent.pendingLayoutChanges
+ & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+ displayContent.layoutNeeded = true;
+ }
+
+ // FIRST LOOP: Perform a layout, if needed.
+ if (repeats < LAYOUT_REPEAT_THRESHOLD) {
+ performLayoutLockedInner(displayContent, repeats == 1,
+ false /*updateInputWindows*/);
+ } else {
+ Slog.w(TAG, "Layout repeat skipped after too many iterations");
+ }
+
+ // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+ // it is animating.
+ displayContent.pendingLayoutChanges = 0;
+
+ if (isDefaultDisplay) {
+ mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
+ for (i = windows.size() - 1; i >= 0; i--) {
+ WindowState w = windows.get(i);
+ if (w.mHasSurface) {
+ mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs,
+ w.mAttachedWindow);
+ }
+ }
+ displayContent.pendingLayoutChanges |=
+ mService.mPolicy.finishPostLayoutPolicyLw();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
+ "after finishPostLayoutPolicyLw",
+ displayContent.pendingLayoutChanges);
+ }
+ } while (displayContent.pendingLayoutChanges != 0);
+
+ mObscured = false;
+ mSyswin = false;
+ displayContent.resetDimming();
+
+ // Only used if default window
+ final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
+
+ final int N = windows.size();
+ for (i=N-1; i>=0; i--) {
+ WindowState w = windows.get(i);
+ final Task task = w.getTask();
+ if (task == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) {
+ continue;
+ }
+
+ final boolean obscuredChanged = w.mObscured != mObscured;
+
+ // Update effect.
+ w.mObscured = mObscured;
+ if (!mObscured) {
+ handleNotObscuredLocked(w, innerDw, innerDh);
+ }
+
+ if (task != null && !task.getContinueDimming()) {
+ w.handleFlagDimBehind();
+ }
+
+ if (isDefaultDisplay && obscuredChanged
+ && mWallpaperControllerLocked.isWallpaperTarget(w)
+ && w.isVisibleLw()) {
+ // This is the wallpaper target and its obscured state
+ // changed... make sure the current wallaper's visibility
+ // has been updated accordingly.
+ mWallpaperControllerLocked.updateWallpaperVisibility();
+ }
+
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+ // If the window has moved due to its containing content frame changing, then
+ // notify the listeners and optionally animate it.
+ if (w.hasMoved()) {
+ // Frame has moved, containing content frame has also moved, and we're not
+ // currently animating... let's do something.
+ final int left = w.mFrame.left;
+ final int top = w.mFrame.top;
+ if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) {
+ Animation a = AnimationUtils.loadAnimation(mService.mContext,
+ com.android.internal.R.anim.window_move_from_decor);
+ winAnimator.setAnimation(a);
+ winAnimator.mAnimDw = w.mLastFrame.left - left;
+ winAnimator.mAnimDh = w.mLastFrame.top - top;
+ winAnimator.mAnimateMove = true;
+ winAnimator.mAnimatingMove = true;
+ }
+
+ //TODO (multidisplay): Accessibility supported only for the default display.
+ if (mService.mAccessibilityController != null
+ && displayId == Display.DEFAULT_DISPLAY) {
+ mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+ }
+
+ try {
+ w.mClient.moved(left, top);
+ } catch (RemoteException e) {
+ }
+ }
+
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+ w.mContentChanged = false;
+
+ // Moved from updateWindowsAndWallpaperLocked().
+ if (w.mHasSurface) {
+ // Take care of the window being ready to display.
+ final boolean committed =
+ winAnimator.commitFinishDrawingLocked();
+ if (isDefaultDisplay && committed) {
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // HACK: When a dream is shown, it may at that
+ // point hide the lock screen. So we need to
+ // redo the layout to let the phone window manager
+ // make this happen.
+ displayContent.pendingLayoutChanges |=
+ FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) {
+ debugLayoutRepeats(
+ "dream and commitFinishDrawingLocked true",
+ displayContent.pendingLayoutChanges);
+ }
+ }
+ if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+ if (DEBUG_WALLPAPER_LIGHT)
+ Slog.v(TAG,
+ "First draw done in potential wallpaper target " + w);
+ mWallpaperMayChange = true;
+ displayContent.pendingLayoutChanges |=
+ FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) {
+ debugLayoutRepeats(
+ "wallpaper and commitFinishDrawingLocked true",
+ displayContent.pendingLayoutChanges);
+ }
+ }
+ }
+
+ winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (DEBUG_STARTING_WINDOW && atoken != null
+ && w == atoken.startingWindow) {
+ Slog.d(TAG, "updateWindows: starting " + w
+ + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
+ + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+ }
+ if (atoken != null
+ && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+ if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
+ atoken.lastTransactionSequence = mService.mTransactionSequence;
+ atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+ atoken.startingDisplayed = false;
+ }
+ if ((w.isOnScreenIgnoringKeyguard()
+ || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
+ && !w.mExiting && !w.mDestroying) {
+ if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Eval win " + w + ": isDrawn="
+ + w.isDrawnLw()
+ + ", isAnimating=" + winAnimator.isAnimating());
+ if (!w.isDrawnLw()) {
+ Slog.v(TAG, "Not displayed: s="
+ + winAnimator.mSurfaceControl
+ + " pv=" + w.mPolicyVisibility
+ + " mDrawState=" + winAnimator.drawStateToString()
+ + " ah=" + w.mAttachedHidden
+ + " th=" + atoken.hiddenRequested
+ + " a=" + winAnimator.mAnimating);
+ }
+ }
+ if (w != atoken.startingWindow) {
+ if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
+ atoken.numInterestingWindows++;
+ if (w.isDrawnLw()) {
+ atoken.numDrawnWindows++;
+ if (DEBUG_VISIBILITY
+ || DEBUG_ORIENTATION)
+ Slog.v(TAG,
+ "tokenMayBeDrawn: " + atoken
+ + " freezingScreen="
+ + atoken.mAppAnimator.freezingScreen
+ + " mAppFreezing=" + w.mAppFreezing);
+ updateAllDrawn = true;
+ }
+ }
+ } else if (w.isDrawnLw()) {
+ atoken.startingDisplayed = true;
+ }
+ }
+ }
+
+ if (isDefaultDisplay && someoneLosingFocus && (w == mService.mCurrentFocus)
+ && w.isDisplayedLw()) {
+ focusDisplayed = true;
+ }
+
+ mService.updateResizingWindows(w);
+ }
+
+ mService.mDisplayManagerInternal.setDisplayProperties(displayId,
+ mDisplayHasContent,
+ mPreferredRefreshRate,
+ mPreferredModeId,
+ true /* inTraversal, must call performTraversalInTrans... below */);
+
+ mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded();
+
+ if (updateAllDrawn) {
+ updateAllDrawnLocked(displayContent);
+ }
+ }
+
+ if (focusDisplayed) {
+ mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
+ }
+
+ // Give the display manager a chance to adjust properties
+ // like display rotation if it needs to.
+ mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+
+ } catch (RuntimeException e) {
+ Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+ }
+
+ final WindowList defaultWindows = defaultDisplay.getWindowList();
+
+ // If we are ready to perform an app transition, check through
+ // all of the app tokens to be shown and see if they are ready
+ // to go.
+ if (mService.mAppTransition.isReady()) {
+ defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
+ if (DEBUG_LAYOUT_REPEATS)
+ debugLayoutRepeats("after handleAppTransitionReadyLocked",
+ defaultDisplay.pendingLayoutChanges);
+ }
+
+ if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
+ // We have finished the animation of an app transition. To do
+ // this, we have delayed a lot of operations like showing and
+ // hiding apps, moving apps in Z-order, etc. The app token list
+ // reflects the correct Z-order, but the window list may now
+ // be out of sync with it. So here we will just rebuild the
+ // entire app window list. Fun!
+ defaultDisplay.pendingLayoutChanges |=
+ mService.handleAnimatingStoppedAndTransitionLocked();
+ if (DEBUG_LAYOUT_REPEATS)
+ debugLayoutRepeats("after handleAnimStopAndXitionLock",
+ defaultDisplay.pendingLayoutChanges);
+ }
+
+ if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
+ && !mService.mAppTransition.isReady()) {
+ // At this point, there was a window with a wallpaper that
+ // was force hiding other windows behind it, but now it
+ // is going away. This may be simple -- just animate
+ // away the wallpaper and its window -- or it may be
+ // hard -- the wallpaper now needs to be shown behind
+ // something that was hidden.
+ defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS)
+ debugLayoutRepeats("after animateAwayWallpaperLocked",
+ defaultDisplay.pendingLayoutChanges);
+ }
+ mWallpaperForceHidingChanged = false;
+
+ if (mWallpaperMayChange) {
+ if (DEBUG_WALLPAPER_LIGHT)
+ Slog.v(TAG, "Wallpaper may change! Adjusting");
+ defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
+ defaultDisplay.pendingLayoutChanges);
+ }
+
+ if (mService.mFocusMayChange) {
+ mService.mFocusMayChange = false;
+ if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ false /*updateInputWindows*/)) {
+ updateInputWindowsNeeded = true;
+ defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ }
+ }
+
+ if (mService.needsLayout()) {
+ defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
+ defaultDisplay.pendingLayoutChanges);
+ }
+
+ for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
+ WindowState win = mService.mResizingWindows.get(i);
+ if (win.mAppFreezing) {
+ // Don't remove this window until rotation has completed.
+ continue;
+ }
+ win.reportResized();
+ mService.mResizingWindows.remove(i);
+ }
+
+ if (DEBUG_ORIENTATION && mService.mDisplayFrozen)
+ Slog.v(TAG,
+ "With display frozen, orientationChangeComplete="
+ + mOrientationChangeComplete);
+ if (mOrientationChangeComplete) {
+ if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+ mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
+ mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
+ mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
+ }
+ mService.stopFreezingDisplayLocked();
+ }
+
+ // Destroy the surface of any windows that are no longer visible.
+ boolean wallpaperDestroyed = false;
+ i = mService.mDestroySurface.size();
+ if (i > 0) {
+ do {
+ i--;
+ WindowState win = mService.mDestroySurface.get(i);
+ win.mDestroying = false;
+ if (mService.mInputMethodWindow == win) {
+ mService.mInputMethodWindow = null;
+ }
+ if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
+ wallpaperDestroyed = true;
+ }
+ win.mWinAnimator.destroySurfaceLocked();
+ } while (i > 0);
+ mService.mDestroySurface.clear();
+ }
+
+ // Time to remove any exiting tokens?
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
+ ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
+ for (i = exitingTokens.size() - 1; i >= 0; i--) {
+ WindowToken token = exitingTokens.get(i);
+ if (!token.hasVisible) {
+ exitingTokens.remove(i);
+ if (token.windowType == TYPE_WALLPAPER) {
+ mWallpaperControllerLocked.removeWallpaperToken(token);
+ }
+ }
+ }
+ }
+
+ // Time to remove any exiting applications?
+ for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+ // Initialize state of exiting applications.
+ final AppTokenList exitingAppTokens =
+ mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+ for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
+ AppWindowToken token = exitingAppTokens.get(i);
+ if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
+ (!token.mIsExiting || token.allAppWindows.isEmpty())) {
+ // Make sure there is no animation running on this token,
+ // so any windows associated with it will be removed as
+ // soon as their animations are complete
+ token.mAppAnimator.clearAnimation();
+ token.mAppAnimator.animating = false;
+ if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT)
+ Slog.v(TAG,
+ "performLayout: App token exiting now removed" + token);
+ token.removeAppFromTaskLocked();
+ }
+ }
+ }
+
+ if (wallpaperDestroyed) {
+ defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ defaultDisplay.layoutNeeded = true;
+ }
+
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
+ if (displayContent.pendingLayoutChanges != 0) {
+ displayContent.layoutNeeded = true;
+ }
+ }
+
+ // Finally update all input windows now that the window changes have stabilized.
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ mService.setHoldScreenLocked(mHoldScreen);
+ if (!mService.mDisplayFrozen) {
+ if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
+ mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
+ } else {
+ mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
+ toBrightnessOverride(mScreenBrightness));
+ }
+ if (mButtonBrightness < 0
+ || mButtonBrightness > 1.0f) {
+ mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
+ } else {
+ mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
+ toBrightnessOverride(mButtonBrightness));
+ }
+ mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
+ mUserActivityTimeout);
+ }
+
+ if (mService.mTurnOnScreen) {
+ if (mService.mAllowTheaterModeWakeFromLayout
+ || Settings.Global.getInt(mService.mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0) == 0) {
+ if (DEBUG_VISIBILITY || DEBUG_POWER) {
+ Slog.v(TAG, "Turning screen on after layout!");
+ }
+ mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+ "android.server.wm:TURN_ON");
+ }
+ mService.mTurnOnScreen = false;
+ }
+
+ if (mUpdateRotation) {
+ if (DEBUG_ORIENTATION) Slog.d(TAG,
+ "Performing post-rotate rotation");
+ if (mService.updateRotationUncheckedLocked(false)) {
+ mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ } else {
+ mUpdateRotation = false;
+ }
+ }
+
+ if (mService.mWaitingForDrawnCallback != null ||
+ (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
+ !mUpdateRotation)) {
+ mService.checkDrawnWindowsLocked();
+ }
+
+ final int N = mService.mPendingRemove.size();
+ if (N > 0) {
+ if (mService.mPendingRemoveTmp.length < N) {
+ mService.mPendingRemoveTmp = new WindowState[N+10];
+ }
+ mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
+ mService.mPendingRemove.clear();
+ DisplayContentList displayList = new DisplayContentList();
+ for (i = 0; i < N; i++) {
+ WindowState w = mService.mPendingRemoveTmp[i];
+ mService.removeWindowInnerLocked(w);
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (displayContent != null && !displayList.contains(displayContent)) {
+ displayList.add(displayContent);
+ }
+ }
+
+ for (DisplayContent displayContent : displayList) {
+ mService.assignLayersLocked(displayContent.getWindowList());
+ displayContent.layoutNeeded = true;
+ }
+ }
+
+ // Remove all deferred displays stacks, tasks, and activities.
+ for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ mService.mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
+ }
+
+ if (updateInputWindowsNeeded) {
+ mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+ mService.setFocusTaskRegion();
+
+ // Check to see if we are now in a state where the screen should
+ // be enabled, because the window obscured flags have changed.
+ mService.enableScreenIfNeededLocked();
+
+ mService.scheduleAnimationLocked();
+
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.e(TAG,
+ "performSurfacePlacementInner exit: animating="
+ + mService.mAnimator.mAnimating);
+ }
+ }
+
+ boolean isInLayout() {
+ return mInLayout;
+ }
+
+ final void performLayoutLockedInner(final DisplayContent displayContent,
+ boolean initial, boolean updateInputWindows) {
+ if (!displayContent.layoutNeeded) {
+ return;
+ }
+ displayContent.layoutNeeded = false;
+ WindowList windows = displayContent.getWindowList();
+ boolean isDefaultDisplay = displayContent.isDefaultDisplay;
+
+ DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+
+ if (mService.mInputConsumer != null) {
+ mService.mInputConsumer.layout(dw, dh);
+ }
+
+ final int N = windows.size();
+ int i;
+
+ if (DEBUG_LAYOUT) {
+ Slog.v(TAG, "-------------------------------------");
+ Slog.v(TAG, "performLayout: needed="
+ + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
+ }
+
+ mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation);
+ if (isDefaultDisplay) {
+ // Not needed on non-default displays.
+ mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
+ mService.mScreenRect.set(0, 0, dw, dh);
+ }
+
+ mService.mPolicy.getContentRectLw(mService.mTmpContentRect);
+ displayContent.resize(mService.mTmpContentRect);
+
+ int seq = mService.mLayoutSeq+1;
+ if (seq < 0) seq = 0;
+ mService.mLayoutSeq = seq;
+
+ boolean behindDream = false;
+
+ // First perform layout of any root windows (not attached
+ // to another window).
+ int topAttached = -1;
+ for (i = N-1; i >= 0; i--) {
+ final WindowState win = windows.get(i);
+
+ // Don't do layout of a window if it is not visible, or
+ // soon won't be visible, to avoid wasting time and funky
+ // changes while a window is animating away.
+ final boolean gone = (behindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs))
+ || win.isGoneForLayoutLw();
+
+ if (DEBUG_LAYOUT && !win.mLayoutAttached) {
+ Slog.v(TAG, "1ST PASS " + win
+ + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
+ + " mLayoutAttached=" + win.mLayoutAttached
+ + " screen changed=" + win.isConfigChanged());
+ final AppWindowToken atoken = win.mAppToken;
+ if (gone) Slog.v(TAG, " GONE: mViewVisibility="
+ + win.mViewVisibility + " mRelayoutCalled="
+ + win.mRelayoutCalled + " hidden="
+ + win.mRootToken.hidden + " hiddenRequested="
+ + (atoken != null && atoken.hiddenRequested)
+ + " mAttachedHidden=" + win.mAttachedHidden);
+ else Slog.v(TAG, " VIS: mViewVisibility="
+ + win.mViewVisibility + " mRelayoutCalled="
+ + win.mRelayoutCalled + " hidden="
+ + win.mRootToken.hidden + " hiddenRequested="
+ + (atoken != null && atoken.hiddenRequested)
+ + " mAttachedHidden=" + win.mAttachedHidden);
+ }
+
+ // If this view is GONE, then skip it -- keep the current
+ // frame, and let the caller know so they can ignore it
+ // if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal,
+ // just don't display").
+ if (!gone || !win.mHaveFrame || win.mLayoutNeeded
+ || ((win.isConfigChanged() || win.setInsetsChanged()) &&
+ ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
+ (win.mHasSurface && win.mAppToken != null &&
+ win.mAppToken.layoutConfigChanges)))) {
+ if (!win.mLayoutAttached) {
+ if (initial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ win.mContentChanged = false;
+ }
+ if (win.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it
+ // does stuff like hide the status bar we won't get a
+ // bad transition when it goes away.
+ behindDream = true;
+ }
+ win.mLayoutNeeded = false;
+ win.prelayout();
+ mService.mPolicy.layoutWindowLw(win, null);
+ win.mLayoutSeq = seq;
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ " LAYOUT: mFrame="
+ + win.mFrame + " mContainingFrame="
+ + win.mContainingFrame + " mDisplayFrame="
+ + win.mDisplayFrame);
+ } else {
+ if (topAttached < 0) topAttached = i;
+ }
+ }
+ }
+
+ boolean attachedBehindDream = false;
+
+ // Now perform layout of attached windows, which usually
+ // depend on the position of the window they are attached to.
+ // XXX does not deal with windows that are attached to windows
+ // that are themselves attached.
+ for (i = topAttached; i >= 0; i--) {
+ final WindowState win = windows.get(i);
+
+ if (win.mLayoutAttached) {
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame + " mViewVisibility="
+ + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled);
+ // If this view is GONE, then skip it -- keep the current
+ // frame, and let the caller know so they can ignore it
+ // if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal,
+ // just don't display").
+ if (attachedBehindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) {
+ continue;
+ }
+ if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
+ || !win.mHaveFrame || win.mLayoutNeeded) {
+ if (initial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ win.mContentChanged = false;
+ }
+ win.mLayoutNeeded = false;
+ win.prelayout();
+ mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow);
+ win.mLayoutSeq = seq;
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ " LAYOUT: mFrame=" + win.mFrame + " mContainingFrame="
+ + win.mContainingFrame + " mDisplayFrame=" + win.mDisplayFrame);
+ }
+ } else if (win.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it
+ // does stuff like hide the status bar we won't get a
+ // bad transition when it goes away.
+ attachedBehindDream = behindDream;
+ }
+ }
+
+ // Window frames may have changed. Tell the input dispatcher about it.
+ mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+ if (updateInputWindows) {
+ mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+
+ mService.mPolicy.finishLayoutLw();
+ }
+
+ /**
+ * @param windows List of windows on default display.
+ * @return bitmap indicating if another pass through layout must be made.
+ */
+ private int handleAppTransitionReadyLocked(WindowList windows) {
+ int appsCount = mService.mOpeningApps.size();
+ if (!transitionGoodToGo(appsCount)) {
+ return 0;
+ }
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
+ int transit = mService.mAppTransition.getAppTransition();
+ if (mService.mSkipAppTransitionAnimation) {
+ transit = AppTransition.TRANSIT_UNSET;
+ }
+ mService.mSkipAppTransitionAnimation = false;
+ mService.mNoAnimationNotifyOnTransitionFinished.clear();
+
+ mService.mH.removeMessages(APP_TRANSITION_TIMEOUT);
+
+ mService.rebuildAppWindowListLocked();
+
+ mWallpaperMayChange = false;
+
+ // The top-most window will supply the layout params,
+ // and we will determine it below.
+ WindowManager.LayoutParams animLp = null;
+ int bestAnimLayer = -1;
+ boolean fullscreenAnim = false;
+ boolean voiceInteraction = false;
+
+ final WindowState lowerWallpaperTarget =
+ mWallpaperControllerLocked.getLowerWallpaperTarget();
+ final WindowState upperWallpaperTarget =
+ mWallpaperControllerLocked.getUpperWallpaperTarget();
+
+ boolean openingAppHasWallpaper = false;
+ boolean closingAppHasWallpaper = false;
+ final AppWindowToken lowerWallpaperAppToken;
+ final AppWindowToken upperWallpaperAppToken;
+ if (lowerWallpaperTarget == null) {
+ lowerWallpaperAppToken = upperWallpaperAppToken = null;
+ } else {
+ lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken;
+ upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
+ }
+
+ int i;
+ // Do a first pass through the tokens for two
+ // things:
+ // (1) Determine if both the closing and opening
+ // app token sets are wallpaper targets, in which
+ // case special animations are needed
+ // (since the wallpaper needs to stay static
+ // behind them).
+ // (2) Find the layout params of the top-most
+ // application window in the tokens, which is
+ // what will control the animation theme.
+ final int closingAppsCount = mService.mClosingApps.size();
+ appsCount = closingAppsCount + mService.mOpeningApps.size();
+ for (i = 0; i < appsCount; i++) {
+ final AppWindowToken wtoken;
+ if (i < closingAppsCount) {
+ wtoken = mService.mClosingApps.valueAt(i);
+ if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+ closingAppHasWallpaper = true;
+ }
+ } else {
+ wtoken = mService.mOpeningApps.valueAt(i - closingAppsCount);
+ if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+ openingAppHasWallpaper = true;
+ }
+ }
+
+ voiceInteraction |= wtoken.voiceInteraction;
+
+ if (wtoken.appFullscreen) {
+ WindowState ws = wtoken.findMainWindow();
+ if (ws != null) {
+ animLp = ws.mAttrs;
+ bestAnimLayer = ws.mLayer;
+ fullscreenAnim = true;
+ }
+ } else if (!fullscreenAnim) {
+ WindowState ws = wtoken.findMainWindow();
+ if (ws != null) {
+ if (ws.mLayer > bestAnimLayer) {
+ animLp = ws.mAttrs;
+ bestAnimLayer = ws.mLayer;
+ }
+ }
+ }
+ }
+
+ transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
+ closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
+
+ // If all closing windows are obscured, then there is
+ // no need to do an animation. This is the case, for
+ // example, when this transition is being done behind
+ // the lock screen.
+ if (!mService.mPolicy.allowAppAnimationsLw()) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Animations disallowed by keyguard or dream.");
+ animLp = null;
+ }
+
+ processApplicationsAnimatingInPlace(transit);
+
+ AppWindowToken topClosingApp = null;
+ int topClosingLayer = 0;
+ appsCount = mService.mClosingApps.size();
+ for (i = 0; i < appsCount; i++) {
+ AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Now closing app " + wtoken);
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ wtoken.inPendingTransaction = false;
+ mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false,
+ voiceInteraction);
+ wtoken.updateReportedVisibilityLocked();
+ // Force the allDrawn flag, because we want to start
+ // this guy's animations regardless of whether it's
+ // gotten drawn.
+ wtoken.allDrawn = true;
+ wtoken.deferClearAllDrawn = false;
+ // Ensure that apps that are mid-starting are also scheduled to have their
+ // starting windows removed after the animation is complete
+ if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
+ mService.scheduleRemoveStartingWindowLocked(wtoken);
+ }
+ mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+ if (animLp != null) {
+ int layer = -1;
+ for (int j = 0; j < wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topClosingApp == null || layer > topClosingLayer) {
+ topClosingApp = wtoken;
+ topClosingLayer = layer;
+ }
+ }
+ }
+
+ AppWindowToken topOpeningApp = null;
+ appsCount = mService.mOpeningApps.size();
+ for (i = 0; i < appsCount; i++) {
+ AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Now opening app" + wtoken);
+
+ if (!appAnimator.usingTransferredAnimation) {
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ }
+ wtoken.inPendingTransaction = false;
+ if (!mService.setTokenVisibilityLocked(
+ wtoken, animLp, true, transit, false, voiceInteraction)){
+ // This token isn't going to be animating. Add it to the list of tokens to
+ // be notified of app transition complete since the notification will not be
+ // sent be the app window animator.
+ mService.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
+ }
+ wtoken.updateReportedVisibilityLocked();
+ wtoken.waitingToShow = false;
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int windowsCount = wtoken.allAppWindows.size();
+ for (int j = 0; j < windowsCount; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mService.mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+ int topOpeningLayer = 0;
+ if (animLp != null) {
+ int layer = -1;
+ for (int j = 0; j < wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topOpeningApp == null || layer > topOpeningLayer) {
+ topOpeningApp = wtoken;
+ topOpeningLayer = layer;
+ }
+ }
+ createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
+ }
+
+ AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
+ topOpeningApp.mAppAnimator;
+ AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+ topClosingApp.mAppAnimator;
+
+ mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
+ mService.mAppTransition.postAnimationCallback();
+ mService.mAppTransition.clear();
+
+ mService.mOpeningApps.clear();
+ mService.mClosingApps.clear();
+
+ // This has changed the visibility of windows, so perform
+ // a new layout to get them all up-to-date.
+ mService.getDefaultDisplayContentLocked().layoutNeeded = true;
+
+ // TODO(multidisplay): IMEs are only supported on the default display.
+ if (windows == mService.getDefaultWindowListLocked()
+ && !mService.moveInputMethodWindowsIfNeededLocked(true)) {
+ mService.assignLayersLocked(windows);
+ }
+ mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ true /*updateInputWindows*/);
+ mService.mFocusMayChange = false;
+ mService.notifyActivityDrawnForKeyguard();
+ return FINISH_LAYOUT_REDO_LAYOUT
+ | FINISH_LAYOUT_REDO_CONFIG;
+
+ }
+
+ private boolean transitionGoodToGo(int appsCount) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Checking " + appsCount + " opening apps (frozen="
+ + mService.mDisplayFrozen + " timeout="
+ + mService.mAppTransition.isTimeout() + ")...");
+ if (!mService.mAppTransition.isTimeout()) {
+ for (int i = 0; i < appsCount; i++) {
+ AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "Check opening app=" + wtoken + ": allDrawn="
+ + wtoken.allDrawn + " startingDisplayed="
+ + wtoken.startingDisplayed + " startingMoved="
+ + wtoken.startingMoved);
+ if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
+ return false;
+ }
+ }
+
+ // If the wallpaper is visible, we need to check it's ready too.
+ return !mWallpaperControllerLocked.isWallpaperVisible() ||
+ mWallpaperControllerLocked.wallpaperTransitionReady();
+ }
+ return true;
+ }
+
+ private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
+ boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget,
+ WindowState upperWallpaperTarget) {
+ // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
+ final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
+ final WindowState oldWallpaper =
+ mWallpaperControllerLocked.isWallpaperTargetAnimating()
+ ? null : wallpaperTarget;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New wallpaper target=" + wallpaperTarget
+ + ", oldWallpaper=" + oldWallpaper
+ + ", lower target=" + lowerWallpaperTarget
+ + ", upper target=" + upperWallpaperTarget);
+ mService.mAnimateWallpaperWithTarget = false;
+ if (closingAppHasWallpaper && openingAppHasWallpaper) {
+ if (DEBUG_APP_TRANSITIONS)
+ Slog.v(TAG, "Wallpaper animation!");
+ switch (transit) {
+ case AppTransition.TRANSIT_ACTIVITY_OPEN:
+ case AppTransition.TRANSIT_TASK_OPEN:
+ case AppTransition.TRANSIT_TASK_TO_FRONT:
+ transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
+ break;
+ case AppTransition.TRANSIT_ACTIVITY_CLOSE:
+ case AppTransition.TRANSIT_TASK_CLOSE:
+ case AppTransition.TRANSIT_TASK_TO_BACK:
+ transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
+ break;
+ }
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit: " + AppTransition.appTransitionToString(transit));
+ } else if ((oldWallpaper != null) && !mService.mOpeningApps.isEmpty()
+ && !mService.mOpeningApps.contains(oldWallpaper.mAppToken)) {
+ // We are transitioning from an activity with
+ // a wallpaper to one without.
+ transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit away from wallpaper: "
+ + AppTransition.appTransitionToString(transit));
+ } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()) {
+ // We are transitioning from an activity without
+ // a wallpaper to now showing the wallpaper
+ transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit into wallpaper: "
+ + AppTransition.appTransitionToString(transit));
+ } else {
+ mService.mAnimateWallpaperWithTarget = true;
+ }
+ return transit;
+ }
+
+ /**
+ * @param w WindowState this method is applied to.
+ * @param innerDw Width of app window.
+ * @param innerDh Height of app window.
+ */
+ private void handleNotObscuredLocked(final WindowState w, final int innerDw, final int innerDh) {
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+ final int attrFlags = attrs.flags;
+ final boolean canBeSeen = w.isDisplayedLw();
+ final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
+
+ if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
+ // This window completely covers everything behind it,
+ // so we want to leave all of them as undimmed (for
+ // performance reasons).
+ mObscured = true;
+ }
+
+ if (w.mHasSurface) {
+ if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
+ mHoldScreen = w.mSession;
+ }
+ if (!mSyswin && w.mAttrs.screenBrightness >= 0
+ && mScreenBrightness < 0) {
+ mScreenBrightness = w.mAttrs.screenBrightness;
+ }
+ if (!mSyswin && w.mAttrs.buttonBrightness >= 0
+ && mButtonBrightness < 0) {
+ mButtonBrightness = w.mAttrs.buttonBrightness;
+ }
+ if (!mSyswin && w.mAttrs.userActivityTimeout >= 0
+ && mUserActivityTimeout < 0) {
+ mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+ }
+
+ final int type = attrs.type;
+ if (canBeSeen
+ && (type == TYPE_SYSTEM_DIALOG
+ || type == TYPE_SYSTEM_ERROR
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
+ mSyswin = true;
+ }
+
+ if (canBeSeen) {
+ // This function assumes that the contents of the default display are
+ // processed first before secondary displays.
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (displayContent != null && displayContent.isDefaultDisplay) {
+ // While a dream or keyguard is showing, obscure ordinary application
+ // content on secondary displays (by forcibly enabling mirroring unless
+ // there is other content we want to show) but still allow opaque
+ // keyguard dialogs to be shown.
+ if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mObscureApplicationContentOnSecondaryDisplays = true;
+ }
+ mDisplayHasContent = true;
+ } else if (displayContent != null &&
+ (!mObscureApplicationContentOnSecondaryDisplays
+ || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+ // Allow full screen keyguard presentation dialogs to be seen.
+ mDisplayHasContent = true;
+ }
+ if (mPreferredRefreshRate == 0
+ && w.mAttrs.preferredRefreshRate != 0) {
+ mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+ }
+ if (mPreferredModeId == 0
+ && w.mAttrs.preferredDisplayModeId != 0) {
+ mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+ }
+ }
+ }
+ }
+
+ private void updateAllDrawnLocked(DisplayContent displayContent) {
+ // See if any windows have been drawn, so they (and others
+ // associated with them) can now be shown.
+ ArrayList<TaskStack> stacks = displayContent.getStacks();
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+ for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+ final AppWindowToken wtoken = tokens.get(tokenNdx);
+ if (!wtoken.allDrawn) {
+ int numInteresting = wtoken.numInterestingWindows;
+ if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+ if (DEBUG_VISIBILITY)
+ Slog.v(TAG, "allDrawn: " + wtoken
+ + " interesting=" + numInteresting
+ + " drawn=" + wtoken.numDrawnWindows);
+ wtoken.allDrawn = true;
+ // Force an additional layout pass where WindowStateAnimator#
+ // commitFinishDrawingLocked() will call performShowLocked().
+ displayContent.layoutNeeded = true;
+ mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN,
+ wtoken.token).sendToTarget();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static int toBrightnessOverride(float value) {
+ return (int)(value * PowerManager.BRIGHTNESS_ON);
+ }
+
+ private void processApplicationsAnimatingInPlace(int transit) {
+ if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
+ // Find the focused window
+ final WindowState win = mService.findFocusedWindowLocked(
+ mService.getDefaultDisplayContentLocked());
+ if (win != null) {
+ final AppWindowToken wtoken = win.mAppToken;
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS)
+ Slog.v(TAG, "Now animating app in place " + wtoken);
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ mService.updateTokenInPlaceLocked(wtoken, transit);
+ wtoken.updateReportedVisibilityLocked();
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int N = wtoken.allAppWindows.size();
+ for (int j = 0; j < N; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+ mService.mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ }
+ }
+ }
+
+ private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
+ int openingLayer, int closingLayer) {
+ AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
+ if (openingAppAnimator == null || openingAppAnimator.animation == null) {
+ return;
+ }
+ final int taskId = appToken.mTask.mTaskId;
+ Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
+ if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) {
+ return;
+ }
+ // This thumbnail animation is very special, we need to have
+ // an extra surface with the thumbnail included with the animation.
+ Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight());
+ try {
+ // TODO(multi-display): support other displays
+ final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
+ final Display display = displayContent.getDisplay();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+ // Create a new surface for the thumbnail
+ SurfaceControl surfaceControl = new SurfaceControl(mService.mFxSession,
+ "thumbnail anim", dirty.width(), dirty.height(),
+ PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ surfaceControl.setLayerStack(display.getLayerStack());
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ }
+
+ // Draw the thumbnail onto the surface
+ Surface drawSurface = new Surface();
+ drawSurface.copyFrom(surfaceControl);
+ Canvas c = drawSurface.lockCanvas(dirty);
+ c.drawBitmap(thumbnailHeader, 0, 0, null);
+ drawSurface.unlockCanvasAndPost(c);
+ drawSurface.release();
+
+ // Get the thumbnail animation
+ Animation anim;
+ if (mService.mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+ // If this is a multi-window scenario, we use the windows frame as
+ // destination of the thumbnail header animation. If this is a full screen
+ // window scenario, we use the whole display as the target.
+ WindowState win = appToken.findMainWindow();
+ Rect appRect = win != null ? win.getContentFrameLw() :
+ new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+ // For the new aspect-scaled transition, we want it to always show
+ // above the animating opening/closing window, and we want to
+ // synchronize its thumbnail surface with the surface for the
+ // open/close animation (only on the way down)
+ anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
+ thumbnailHeader, taskId);
+ Log.d(TAG, "assigning thumbnail force above layer: "
+ + openingLayer + " " + closingLayer);
+ openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
+ openingAppAnimator.deferThumbnailDestruction =
+ !mService.mAppTransition.isNextThumbnailTransitionScaleUp();
+ } else {
+ anim = mService.mAppTransition.createThumbnailScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader);
+ }
+ anim.restrictDuration(MAX_ANIMATION_DURATION);
+ anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
+
+ openingAppAnimator.thumbnail = surfaceControl;
+ openingAppAnimator.thumbnailLayer = openingLayer;
+ openingAppAnimator.thumbnailAnimation = anim;
+ mService.mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect);
+ openingAppAnimator.thumbnailX = mTmpStartRect.left;
+ openingAppAnimator.thumbnailY = mTmpStartRect.top;
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w="
+ + dirty.width() + " h=" + dirty.height(), e);
+ openingAppAnimator.clearThumbnail();
+ }
+ }
+
+ boolean copyAnimToLayoutParamsLocked() {
+ boolean doRequest = false;
+
+ final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
+ if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
+ mUpdateRotation = true;
+ doRequest = true;
+ }
+ if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
+ mWallpaperMayChange = true;
+ doRequest = true;
+ }
+ if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
+ mWallpaperForceHidingChanged = true;
+ doRequest = true;
+ }
+ if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
+ mOrientationChangeComplete = false;
+ } else {
+ mOrientationChangeComplete = true;
+ mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
+ if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+ doRequest = true;
+ }
+ }
+ if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
+ mService.mTurnOnScreen = true;
+ }
+ if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
+ mWallpaperActionPending = true;
+ }
+
+ return doRequest;
+ }
+}
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index a91ddb8..cbf8fc2 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -55,6 +55,7 @@
public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8;
public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14;
+ public static final int HWADDR_LEN = 16;
public static final int MAX_OPTION_LEN = 255;
/**
* IP layer definitions.
@@ -399,7 +400,7 @@
buf.put(mRelayIp.getAddress());
buf.put(mClientMac);
buf.position(buf.position() +
- (16 - mClientMac.length) // pad addr to 16 bytes
+ (HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes
+ 64 // empty server host name (64 bytes)
+ 128); // empty boot file name (128 bytes)
buf.putInt(0x63825363); // magic number
@@ -786,7 +787,7 @@
byte type = packet.get();
byte hwType = packet.get();
- byte addrLen = packet.get();
+ int addrLen = packet.get() & 0xff;
byte hops = packet.get();
transactionId = packet.getInt();
secs = packet.getShort();
@@ -807,6 +808,16 @@
return null;
}
+ // Some DHCP servers have been known to announce invalid client hardware address values such
+ // as 0xff. The legacy DHCP client accepted these becuause it does not check the length at
+ // all but only checks that the interface MAC address matches the first bytes of the address
+ // in the packets. We're a bit stricter: if the length is obviously invalid (i.e., bigger
+ // than the size of the field), we fudge it to 6 (Ethernet). http://b/23725795
+ // TODO: evaluate whether to make this test more liberal.
+ if (addrLen > HWADDR_LEN) {
+ addrLen = ETHER_BROADCAST.length;
+ }
+
clientMac = new byte[addrLen];
packet.get(clientMac);
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index da1df1a..cd3b8bb 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -333,6 +333,76 @@
}
@SmallTest
+ public void testBadHwaddrLength() throws Exception {
+ final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+ // IP header.
+ "450001518d0600004011144dc0a82b01c0a82bf7" +
+ // UDP header.
+ "00430044013d9ac7" +
+ // BOOTP header.
+ "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+ // MAC address.
+ "30766ff2a90c00000000000000000000" +
+ // Server name.
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ // File.
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ // Options
+ "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
+ "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"
+ ).toCharArray(), false));
+ String expectedClientMac = "30766FF2A90C";
+
+ final int hwAddrLenOffset = 20 + 8 + 2;
+ assertEquals(6, packet.get(hwAddrLenOffset));
+
+ // Expect the expected.
+ DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+ assertNotNull(offerPacket);
+ assertEquals(6, offerPacket.getClientMac().length);
+ assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+
+ // Reduce the hardware address length and verify that it shortens the client MAC.
+ packet.flip();
+ packet.put(hwAddrLenOffset, (byte) 5);
+ offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+ assertNotNull(offerPacket);
+ assertEquals(5, offerPacket.getClientMac().length);
+ assertEquals(expectedClientMac.substring(0, 10),
+ HexDump.toHexString(offerPacket.getClientMac()));
+
+ packet.flip();
+ packet.put(hwAddrLenOffset, (byte) 3);
+ offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+ assertNotNull(offerPacket);
+ assertEquals(3, offerPacket.getClientMac().length);
+ assertEquals(expectedClientMac.substring(0, 6),
+ HexDump.toHexString(offerPacket.getClientMac()));
+
+ // Set the the hardware address length to 0xff and verify that we a) don't treat it as -1
+ // and crash, and b) hardcode it to 6.
+ packet.flip();
+ packet.put(hwAddrLenOffset, (byte) -1);
+ offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+ assertNotNull(offerPacket);
+ assertEquals(6, offerPacket.getClientMac().length);
+ assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+
+ // Set the the hardware address length to a positive invalid value (> 16) and verify that we
+ // hardcode it to 6.
+ packet.flip();
+ packet.put(hwAddrLenOffset, (byte) 17);
+ offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+ assertNotNull(offerPacket);
+ assertEquals(6, offerPacket.getClientMac().length);
+ assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+ }
+
+ @SmallTest
public void testPadAndOverloadedOptionsOffer() throws Exception {
// A packet observed in the real world that is interesting for two reasons:
//
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index fd9fc98..51e14d3 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -54,7 +54,7 @@
* Timeout in which we are waiting for the system to start the mock
* accessibility services.
*/
- private static final long TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES = 300;
+ private static final long TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES = 1000;
/**
* Timeout used for testing that a service is notified only upon a
@@ -68,6 +68,12 @@
private IAccessibilityManager mManagerService;
@Override
+ protected void setUp() throws Exception {
+ // Reset the state.
+ ensureOnlyMockServicesEnabled(getContext(), false, false);
+ }
+
+ @Override
public void setContext(Context context) {
super.setContext(context);
if (MyFirstMockAccessibilityService.sComponentName == null) {
@@ -92,6 +98,9 @@
@LargeTest
public void testAddClient_AccessibilityDisabledThenEnabled() throws Exception {
+ // at least some service must be enabled, otherwise accessibility will always be disabled.
+ ensureOnlyMockServicesEnabled(mContext, true, false);
+
// make sure accessibility is disabled
ensureAccessibilityEnabled(mContext, false);
@@ -99,7 +108,8 @@
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
+ final int stateFlagsDisabled =
+ mManagerService.addClient(mockClient, UserHandle.USER_CURRENT);
boolean enabledAccessibilityDisabled =
(stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
@@ -111,11 +121,11 @@
ensureAccessibilityEnabled(mContext, true);
// invoke the method under test
- final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
+ final int stateFlagsEnabled =
+ mManagerService.addClient(mockClient, UserHandle.USER_CURRENT);
boolean enabledAccessibilityEnabled =
(stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
-
// check expected result
assertTrue("The client must be enabled since accessibility is enabled.",
enabledAccessibilityEnabled);
@@ -123,6 +133,9 @@
@LargeTest
public void testAddClient_AccessibilityEnabledThenDisabled() throws Exception {
+ // at least some service must be enabled, otherwise accessibility will always be disabled.
+ ensureOnlyMockServicesEnabled(mContext, true, false);
+
// enable accessibility before registering the client
ensureAccessibilityEnabled(mContext, true);
@@ -130,7 +143,8 @@
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
+ final int stateFlagsEnabled =
+ mManagerService.addClient(mockClient, UserHandle.USER_CURRENT);
boolean enabledAccessibilityEnabled =
(stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
@@ -142,7 +156,8 @@
ensureAccessibilityEnabled(mContext, false);
// invoke the method under test
- final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
+ final int stateFlagsDisabled =
+ mManagerService.addClient(mockClient, UserHandle.USER_CURRENT);
boolean enabledAccessibilityDisabled =
(stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
@@ -162,7 +177,7 @@
// look for the two mock services
for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList(
- UserHandle.USER_OWNER)) {
+ UserHandle.USER_CURRENT)) {
ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
if (packageName.equals(serviceInfo.packageName)) {
if (firstMockServiceClassName.equals(serviceInfo.name)) {
@@ -181,12 +196,12 @@
@LargeTest
public void testSendAccessibilityEvent_OneService_MatchingPackageAndEventType()
throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility service
ensureOnlyMockServicesEnabled(mContext, true, false);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the mock service
MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
service.setServiceInfo(MockAccessibilityService.createDefaultInfo());
@@ -203,7 +218,7 @@
service.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(service);
@@ -211,12 +226,12 @@
@LargeTest
public void testSendAccessibilityEvent_OneService_NotMatchingPackage() throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility service
ensureOnlyMockServicesEnabled(mContext, true, false);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the mock service
MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
service.setServiceInfo(MockAccessibilityService.createDefaultInfo());
@@ -233,7 +248,7 @@
service.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(service);
@@ -241,12 +256,12 @@
@LargeTest
public void testSendAccessibilityEvent_OneService_NotMatchingEventType() throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility service
ensureOnlyMockServicesEnabled(mContext, true, false);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the mock service
MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
service.setServiceInfo(MockAccessibilityService.createDefaultInfo());
@@ -263,7 +278,7 @@
service.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(service);
@@ -271,12 +286,12 @@
@LargeTest
public void testSendAccessibilityEvent_OneService_NotifivationAfterTimeout() throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility service
ensureOnlyMockServicesEnabled(mContext, true, false);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the mock service
MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
AccessibilityServiceInfo info = MockAccessibilityService.createDefaultInfo();
@@ -299,8 +314,8 @@
service.replay();
// send the events
- mManagerService.sendAccessibilityEvent(firstEvent, UserHandle.USER_OWNER);
- mManagerService.sendAccessibilityEvent(secondEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(firstEvent, UserHandle.USER_CURRENT);
+ mManagerService.sendAccessibilityEvent(secondEvent, UserHandle.USER_CURRENT);
// wait for #sendAccessibilityEvent to reach the backing service
Thread.sleep(TIMEOUT_BINDER_CALL);
@@ -322,12 +337,12 @@
@LargeTest
public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_DiffFeedback()
throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility services
ensureOnlyMockServicesEnabled(mContext, true, true);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the first mock service
MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
AccessibilityServiceInfo firstInfo = MockAccessibilityService.createDefaultInfo();
@@ -356,7 +371,7 @@
secondService.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(firstService);
@@ -366,12 +381,12 @@
@LargeTest
public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType()
throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility services
ensureOnlyMockServicesEnabled(mContext, true, true);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the first mock service
MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo());
@@ -395,7 +410,7 @@
secondService.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(firstService);
@@ -405,12 +420,12 @@
@LargeTest
public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_OneDefault()
throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility services
ensureOnlyMockServicesEnabled(mContext, true, true);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the first mock service
MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo();
@@ -436,7 +451,7 @@
secondService.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(firstService);
@@ -446,12 +461,12 @@
@LargeTest
public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_TwoDefault()
throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility services
ensureOnlyMockServicesEnabled(mContext, true, true);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the first mock service
MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo();
@@ -479,7 +494,7 @@
secondService.replay();
// send the event
- mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);
+ mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(firstService);
@@ -488,12 +503,12 @@
@LargeTest
public void testInterrupt() throws Exception {
- // set the accessibility setting value
- ensureAccessibilityEnabled(mContext, true);
-
// enable the mock accessibility services
ensureOnlyMockServicesEnabled(mContext, true, true);
+ // set the accessibility setting value
+ ensureAccessibilityEnabled(mContext, true);
+
// configure the first mock service
MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo());
@@ -514,7 +529,7 @@
secondService.replay();
// call the method under test
- mManagerService.interrupt(UserHandle.USER_OWNER);
+ mManagerService.interrupt(UserHandle.USER_CURRENT);
// verify if all expected methods have been called
assertMockServiceVerifiedWithinTimeout(firstService);
@@ -534,7 +549,7 @@
sentEvent.setContentDescription("ContentDescription");
sentEvent.setCurrentItemIndex(1);
sentEvent.setEnabled(true);
- sentEvent.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
+ sentEvent.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
sentEvent.setEventTime(1000);
sentEvent.setFromIndex(1);
sentEvent.setFullScreen(true);
@@ -568,8 +583,8 @@
* @throws Exception If any error occurs.
*/
private void ensureAccessibilityEnabled(Context context, boolean enabled) throws Exception {
- boolean isEnabled = (Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1 ? true : false);
+ boolean isEnabled = Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
if (isEnabled == enabled) {
return;
@@ -608,13 +623,14 @@
servicesToEnable.append(MySecondMockAccessibilityService.sComponentName).append(":");
}
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, servicesToEnable.toString());
+
+ // Optimization. If things will not change, we don't have to do anything.
if (servicesToEnable.equals(enabledServices)) {
return;
}
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, servicesToEnable.toString());
-
// we have enabled the services of interest and need to wait until they
// are instantiated and started (if needed) and the system binds to them
boolean firstMockServiceOK = false;
@@ -664,13 +680,13 @@
throws Exception {
Exception lastVerifyException = null;
long beginTime = SystemClock.uptimeMillis();
- long pollTmeout = TIMEOUT_BINDER_CALL / 5;
+ long pollTimeout = TIMEOUT_BINDER_CALL / 5;
// poll until the timeout has elapsed
while (SystemClock.uptimeMillis() - beginTime < TIMEOUT_BINDER_CALL) {
// sleep first since immediate call will always fail
try {
- Thread.sleep(pollTmeout);
+ Thread.sleep(pollTimeout);
} catch (InterruptedException ie) {
/* ignore */
}
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index e7366ea..026a2ad 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -16,14 +16,11 @@
package com.android.server;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reportMatcher;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-
-import org.easymock.IArgumentMatcher;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.os.UserHandle;
@@ -35,6 +32,9 @@
import android.view.accessibility.IAccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
import java.util.ArrayList;
import java.util.List;
@@ -49,78 +49,65 @@
*/
public static final long TIMEOUT_BINDER_CALL = 50;
- /**
- * The reusable mock {@link IAccessibilityManager}.
- */
- private final IAccessibilityManager mMockServiceInterface =
- createStrictMock(IAccessibilityManager.class);
+ @Mock
+ private IAccessibilityManager mMockService;
@Override
public void setUp() throws Exception {
- reset(mMockServiceInterface);
+ MockitoAnnotations.initMocks(this);
+ }
+
+ private AccessibilityManager createManager(boolean enabled) throws Exception {
+ if (enabled) {
+ when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt()))
+ .thenReturn(AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
+ } else {
+ when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt()))
+ .thenReturn(0);
+ }
+
+ AccessibilityManager manager =
+ new AccessibilityManager(mContext, mMockService, UserHandle.USER_CURRENT);
+
+ verify(mMockService).addClient(any(IAccessibilityManagerClient.class), anyInt());
+
+ return manager;
}
@MediumTest
public void testGetAccessibilityServiceList() throws Exception {
// create a list of installed accessibility services the mock service returns
- List<AccessibilityServiceInfo> expectedServices = new ArrayList<AccessibilityServiceInfo>();
+ List<AccessibilityServiceInfo> expectedServices = new ArrayList<>();
AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
accessibilityServiceInfo.packageNames = new String[] { "foo.bar" };
expectedServices.add(accessibilityServiceInfo);
// configure the mock service behavior
- IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
- UserHandle.USER_OWNER)).andReturn(
- AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
- expect(mockServiceInterface.getInstalledAccessibilityServiceList(UserHandle.USER_OWNER))
- .andReturn(expectedServices);
- replay(mockServiceInterface);
+ when(mMockService.getInstalledAccessibilityServiceList(anyInt()))
+ .thenReturn(expectedServices);
// invoke the method under test
- AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
- UserHandle.USER_OWNER);
+ AccessibilityManager manager = createManager(true);
List<AccessibilityServiceInfo> receivedServices =
- manager.getInstalledAccessibilityServiceList();
+ manager.getInstalledAccessibilityServiceList();
+ verify(mMockService).getInstalledAccessibilityServiceList(UserHandle.USER_CURRENT);
// check expected result (list equals() compares it contents as well)
- assertEquals("All expected services must be returned", receivedServices, expectedServices);
-
- // verify the mock service was properly called
- verify(mockServiceInterface);
+ assertEquals("All expected services must be returned", expectedServices, receivedServices);
}
@MediumTest
public void testInterrupt() throws Exception {
- // configure the mock service behavior
- IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
- UserHandle.USER_OWNER)).andReturn(
- AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
- mockServiceInterface.interrupt(UserHandle.USER_OWNER);
- replay(mockServiceInterface);
-
- // invoke the method under test
- AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
- UserHandle.USER_OWNER);
+ AccessibilityManager manager = createManager(true);
manager.interrupt();
- // verify the mock service was properly called
- verify(mockServiceInterface);
+ verify(mMockService).interrupt(UserHandle.USER_CURRENT);
}
@LargeTest
public void testIsEnabled() throws Exception {
- // configure the mock service behavior
- IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
- UserHandle.USER_OWNER)).andReturn(
- AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
- replay(mockServiceInterface);
-
// invoke the method under test
- AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
- UserHandle.USER_OWNER);
+ AccessibilityManager manager = createManager(true);
boolean isEnabledServiceEnabled = manager.isEnabled();
// check expected result
@@ -138,63 +125,32 @@
// check expected result
assertFalse("Must be disabled since the mock service is disabled",
isEnabledServcieDisabled);
-
- // verify the mock service was properly called
- verify(mockServiceInterface);
}
@MediumTest
public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception {
- // create an event to be dispatched
AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
- // configure the mock service behavior
- IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
- UserHandle.USER_OWNER)).andReturn(
- AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
- expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent),
- UserHandle.USER_OWNER)).andReturn(true);
- expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent),
- UserHandle.USER_OWNER)).andReturn(false);
- replay(mockServiceInterface);
+ when(mMockService.sendAccessibilityEvent(eq(sentEvent), anyInt()))
+ .thenReturn(true /* should recycle event object */)
+ .thenReturn(false /* should not recycle event object */);
- // invoke the method under test (manager and service in different processes)
- AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
- UserHandle.USER_OWNER);
+ AccessibilityManager manager = createManager(true);
manager.sendAccessibilityEvent(sentEvent);
- // check expected result
- AccessibilityEvent nextEventDifferentProcesses = AccessibilityEvent.obtain();
- assertSame("The manager and the service are in different processes, so the event must be " +
- "recycled", sentEvent, nextEventDifferentProcesses);
+ assertSame("The event should be recycled.", sentEvent, AccessibilityEvent.obtain());
- // invoke the method under test (manager and service in the same process)
manager.sendAccessibilityEvent(sentEvent);
- // check expected result
- AccessibilityEvent nextEventSameProcess = AccessibilityEvent.obtain();
- assertNotSame("The manager and the service are in the same process, so the event must not" +
- "be recycled", sentEvent, nextEventSameProcess);
-
- // verify the mock service was properly called
- verify(mockServiceInterface);
+ assertNotSame("The event should not be recycled.", sentEvent, AccessibilityEvent.obtain());
}
@MediumTest
public void testSendAccessibilityEvent_AccessibilityDisabled() throws Exception {
- // create an event to be dispatched
AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
- // configure the mock service behavior
- IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(),
- UserHandle.USER_OWNER)).andReturn(0);
- replay(mockServiceInterface);
+ AccessibilityManager manager = createManager(false /* disabled */);
- // invoke the method under test (accessibility disabled)
- AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface,
- UserHandle.USER_OWNER);
try {
manager.sendAccessibilityEvent(sentEvent);
fail("No accessibility events are sent if accessibility is disabled");
@@ -202,73 +158,5 @@
// check expected result
assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage());
}
-
- // verify the mock service was properly called
- verify(mockServiceInterface);
- }
-
- /**
- * Determines if an {@link AccessibilityEvent} passed as a method argument
- * matches expectations.
- *
- * @param matched The event to check.
- * @return True if expectations are matched.
- */
- private static AccessibilityEvent eqAccessibilityEvent(AccessibilityEvent matched) {
- reportMatcher(new AccessibilityEventMather(matched));
- return null;
- }
-
- /**
- * Determines if an {@link IAccessibilityManagerClient} passed as a method argument
- * matches expectations which in this case are that any instance is accepted.
- *
- * @return <code>null</code>.
- */
- private static IAccessibilityManagerClient anyIAccessibilityManagerClient() {
- reportMatcher(new AnyIAccessibilityManagerClientMather());
- return null;
- }
-
- /**
- * Matcher for {@link AccessibilityEvent}s.
- */
- private static class AccessibilityEventMather implements IArgumentMatcher {
- private AccessibilityEvent mExpectedEvent;
-
- public AccessibilityEventMather(AccessibilityEvent expectedEvent) {
- mExpectedEvent = expectedEvent;
- }
-
- public boolean matches(Object matched) {
- if (!(matched instanceof AccessibilityEvent)) {
- return false;
- }
- AccessibilityEvent receivedEvent = (AccessibilityEvent) matched;
- return mExpectedEvent.getEventType() == receivedEvent.getEventType();
- }
-
- public void appendTo(StringBuffer buffer) {
- buffer.append("sendAccessibilityEvent()");
- buffer.append(" with event type \"");
- buffer.append(mExpectedEvent.getEventType());
- buffer.append("\"");
- }
- }
-
- /**
- * Matcher for {@link IAccessibilityManagerClient}s.
- */
- private static class AnyIAccessibilityManagerClientMather implements IArgumentMatcher {
- public boolean matches(Object matched) {
- if (!(matched instanceof IAccessibilityManagerClient)) {
- return false;
- }
- return true;
- }
-
- public void appendTo(StringBuffer buffer) {
- buffer.append("addClient() with any IAccessibilityManagerClient");
- }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java b/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java
index 1bc9b86..e1c5cee 100644
--- a/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java
+++ b/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java
@@ -62,7 +62,7 @@
*/
public static AccessibilityServiceInfo createDefaultInfo() {
AccessibilityServiceInfo defaultInfo = new AccessibilityServiceInfo();
- defaultInfo.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED;
+ defaultInfo.eventTypes = AccessibilityEvent.TYPE_ANNOUNCEMENT;
defaultInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE;
defaultInfo.flags = 0;
defaultInfo.notificationTimeout = 0;