diff options
Diffstat (limited to 'services/core/java')
32 files changed, 606 insertions, 268 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 1366149..7d427d6 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -23,6 +23,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -915,7 +916,7 @@ public class AppOpsService extends IAppOpsService.Stub { boolean success = false; try { XmlPullParser parser = Xml.newPullParser(); - parser.setInput(stream, null); + parser.setInput(stream, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { @@ -1075,7 +1076,7 @@ public class AppOpsService extends IAppOpsService.Stub { try { XmlSerializer out = new FastXmlSerializer(); - out.setOutput(stream, "utf-8"); + out.setOutput(stream, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, "app-ops"); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0961ffe..16b3dcf 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1982,7 +1982,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (msg.arg1 == 0) { setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null); } else { - NetworkAgentInfo nai = null; + final NetworkAgentInfo nai; synchronized (mNetworkForNetId) { nai = mNetworkForNetId.get(msg.arg2); } @@ -1990,6 +1990,7 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } + nai.captivePortalDetected = true; setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj); } @@ -2384,7 +2385,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Only prompt if the network is unvalidated and was explicitly selected by the user, and if // we haven't already been told to switch to it regardless of whether it validated or not. - if (nai == null || nai.everValidated || + // Also don't prompt on captive portals because we're already prompting the user to sign in. + if (nai == null || nai.everValidated || nai.captivePortalDetected || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) { return; } diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 5dbf4c9..9b7b2d3 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -71,6 +71,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; /** * Keeps track of device idleness and drives low power mode based on that. @@ -679,7 +680,7 @@ public class DeviceIdleController extends SystemService { } try { XmlPullParser parser = Xml.newPullParser(); - parser.setInput(stream, null); + parser.setInput(stream, StandardCharsets.UTF_8.name()); readConfigFileLocked(parser); } catch (XmlPullParserException e) { } finally { @@ -756,7 +757,7 @@ public class DeviceIdleController extends SystemService { try { synchronized (this) { XmlSerializer out = new FastXmlSerializer(); - out.setOutput(memStream, "utf-8"); + out.setOutput(memStream, StandardCharsets.UTF_8.name()); writeConfigFileLocked(out); } } catch (IOException e) { diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index f5d323d..256a662 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -126,6 +126,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -3521,7 +3522,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { fos = subtypesFile.startWrite(); final XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); out.startTag(null, NODE_SUBTYPES); @@ -3567,7 +3568,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { fis = subtypesFile.openRead(); final XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int type = parser.getEventType(); // Skip parsing until START_TAG while ((type = parser.next()) != XmlPullParser.START_TAG diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 003d0e7..c32de41 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -1204,7 +1204,7 @@ class MountService extends IMountService.Stub try { fis = mSettingsFile.openRead(); final XmlPullParser in = Xml.newPullParser(); - in.setInput(fis, null); + in.setInput(fis, StandardCharsets.UTF_8.name()); int type; while ((type = in.next()) != END_DOCUMENT) { @@ -1244,7 +1244,7 @@ class MountService extends IMountService.Stub fos = mSettingsFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, TAG_VOLUMES); writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY); diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java index 0de8c8d..e0e6070 100644 --- a/services/core/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java @@ -216,9 +216,9 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { mWakeLock.acquire(); - Log.i(TAG, "MSG_NEW_DEVICE_STATE "); + Log.i(TAG, "MSG_NEW_DEVICE_STATE"); Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, - mHeadsetState, newName); + mHeadsetState, ""); mHandler.sendMessage(msg); mHeadsetState = headsetState; diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java index d64e39f..925fae0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java +++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java @@ -51,6 +51,7 @@ class ActivityManagerDebugConfig { static final boolean DEBUG_FOCUS = false; static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false; static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false; + static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false; static final boolean DEBUG_LRU = DEBUG_ALL || false; static final boolean DEBUG_MU = DEBUG_ALL || false; static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false; @@ -82,6 +83,7 @@ class ActivityManagerDebugConfig { static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : ""; static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : ""; static final String POSTFIX_LOCKSCREEN = (APPEND_CATEGORY_NAME) ? "_LOCKSCREEN" : ""; + static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LOCKTASK" : ""; static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : ""; static final String POSTFIX_MU = "_MU"; static final String POSTFIX_OOM_ADJ = (APPEND_CATEGORY_NAME) ? "_OomAdj" : ""; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0ee1ae4..2158395 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -235,6 +235,7 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.ref.WeakReference; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -264,6 +265,7 @@ public final class ActivityManagerService extends ActivityManagerNative private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE; private static final String TAG_LOCKSCREEN = TAG + POSTFIX_LOCKSCREEN; + private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; private static final String TAG_LRU = TAG + POSTFIX_LRU; private static final String TAG_MU = TAG + POSTFIX_MU; private static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ; @@ -7671,7 +7673,7 @@ public final class ActivityManagerService extends ActivityManagerNative fos = mGrantFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, TAG_URI_GRANTS); for (UriPermission.Snapshot perm : persist) { @@ -7706,7 +7708,7 @@ public final class ActivityManagerService extends ActivityManagerNative try { fis = mGrantFile.openRead(); final XmlPullParser in = Xml.newPullParser(); - in.setInput(fis, null); + in.setInput(fis, StandardCharsets.UTF_8.name()); int type; while ((type = in.next()) != END_DOCUMENT) { @@ -8761,6 +8763,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException("updateLockTaskPackage called from non-system process"); } synchronized (this) { + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":" + packages); mLockTaskPackages.put(userId, packages); mStackSupervisor.onLockTaskPackagesUpdatedLocked(); } @@ -8768,6 +8771,7 @@ public final class ActivityManagerService extends ActivityManagerNative void startLockTaskModeLocked(TaskRecord task) { + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "startLockTaskModeLocked: " + task); if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { return; } @@ -8784,6 +8788,7 @@ public final class ActivityManagerService extends ActivityManagerNative task.mLockTaskUid = callingUid; if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) { // startLockTask() called by app and task mode is lockTaskModeDefault. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user"); StatusBarManagerInternal statusBarManager = LocalServices.getService(StatusBarManagerInternal.class); if (statusBarManager != null) { @@ -8796,6 +8801,8 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("Invalid task, not in foreground"); } } + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, isSystemInitiated ? "Locking pinned" : + "Locking fully"); mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ? ActivityManager.LOCK_TASK_MODE_PINNED : ActivityManager.LOCK_TASK_MODE_LOCKED, diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 54ea6d7..f304828 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -117,6 +117,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Set; @@ -124,6 +125,7 @@ public final class ActivityStackSupervisor implements DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM; private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; + private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; @@ -1183,7 +1185,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final TaskRecord task = r.task; if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { - setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "lockTaskLaunchMode attribute"); + setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE"); } final ActivityStack stack = task.stack; @@ -3327,6 +3329,18 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + private String lockTaskModeToString() { + switch (mLockTaskModeState) { + case LOCK_TASK_MODE_LOCKED: + return "LOCKED"; + case LOCK_TASK_MODE_PINNED: + return "PINNED"; + case LOCK_TASK_MODE_NONE: + return "NONE"; + default: return "unknown=" + mLockTaskModeState; + } + } + public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack); pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack); @@ -3334,7 +3348,16 @@ public final class ActivityStackSupervisor implements DisplayListener { pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers); - pw.print(prefix); pw.println("mLockTaskModeTasks" + mLockTaskModeTasks); + pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString()); + final SparseArray<String[]> packages = mService.mLockTaskPackages; + if (packages.size() > 0) { + pw.println(" mLockTaskPackages (userId:packages)="); + for (int i = 0; i < packages.size(); ++i) { + pw.print(prefix); pw.print(prefix); pw.print(packages.keyAt(i)); + pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i))); + } + } + pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks); } ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { @@ -3654,6 +3677,8 @@ public final class ActivityStackSupervisor implements DisplayListener { void removeLockedTaskLocked(final TaskRecord task) { if (mLockTaskModeTasks.remove(task) && mLockTaskModeTasks.isEmpty()) { // Last one. + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task + + " last task, reverting locktask mode. Callers=" + Debug.getCallers(3)); final Message lockTaskMsg = Message.obtain(); lockTaskMsg.arg1 = task.userId; lockTaskMsg.what = LOCK_TASK_END_MSG; @@ -3679,20 +3704,26 @@ public final class ActivityStackSupervisor implements DisplayListener { removeLockedTaskLocked(lockedTask); if (!mLockTaskModeTasks.isEmpty()) { // There are locked tasks remaining, can only finish this task, not unlock it. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskModeLocked: Tasks remaining, can't unlock"); lockedTask.performClearTaskLocked(); resumeTopActivitiesLocked(); return; } } + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskModeLocked: No tasks to unlock. Callers=" + Debug.getCallers(4)); return; } // Should have already been checked, but do it again. if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskModeLocked: Can't lock due to auth"); return; } if (isLockTaskModeViolation(task)) { - Slog.e(TAG, "setLockTaskMode: Attempt to start an unauthorized lock task."); + Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); return; } @@ -3706,6 +3737,8 @@ public final class ActivityStackSupervisor implements DisplayListener { mHandler.sendMessage(lockTaskMsg); } // Add it or move it to the top. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskModeLocked: Locking to " + task + + " Callers=" + Debug.getCallers(4)); mLockTaskModeTasks.remove(task); mLockTaskModeTasks.add(task); @@ -3759,6 +3792,13 @@ public final class ActivityStackSupervisor implements DisplayListener { stack.onLockTaskPackagesUpdatedLocked(); } } + final ActivityRecord r = topRunningActivityLocked(); + final TaskRecord task = r != null ? r.task : null; + if (mLockTaskModeTasks.isEmpty() && task != null + && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { + // This task must have just been authorized. + setLockTaskModeLocked(task, ActivityManager.LOCK_TASK_MODE_LOCKED, "package updated"); + } if (didSomething) { resumeTopActivitiesLocked(); } diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java index 0fe9231..814e8b4 100644 --- a/services/core/java/com/android/server/am/CompatModePackages.java +++ b/services/core/java/com/android/server/am/CompatModePackages.java @@ -21,6 +21,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.*; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -86,7 +87,7 @@ public final class CompatModePackages { try { fis = mFile.openRead(); XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int eventType = parser.getEventType(); while (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_DOCUMENT) { @@ -362,7 +363,7 @@ public final class CompatModePackages { try { fos = mFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); out.startTag(null, "compat-packages"); diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 5e9f2b0..f653e9e 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -63,6 +63,7 @@ import java.util.ArrayList; final class TaskRecord { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; + private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; private static final String TAG_TASKS = TAG + POSTFIX_TASKS; static final String ATTR_TASKID = "task_id"; @@ -134,12 +135,11 @@ final class TaskRecord { /** Can't be put in lockTask mode. */ final static int LOCK_TASK_AUTH_DONT_LOCK = 0; - /** Can enter lockTask with user approval if not already in lockTask. */ + /** Can enter lockTask with user approval. Can never start over existing lockTask task. */ final static int LOCK_TASK_AUTH_PINNABLE = 1; /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */ final static int LOCK_TASK_AUTH_LAUNCHABLE = 2; - /** Enters LOCK_TASK_MODE_LOCKED via startLockTask(), enters LOCK_TASK_MODE_PINNED from - * Overview. Can start over existing lockTask task. */ + /** Can enter lockTask with user approval. Can start over existing lockTask task. */ final static int LOCK_TASK_AUTH_WHITELISTED = 3; int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE; @@ -744,21 +744,31 @@ final class TaskRecord { void setLockTaskAuth() { switch (mLockTaskMode) { case LOCK_TASK_LAUNCH_MODE_DEFAULT: + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + + " mLockTaskAuth=" + (isLockTaskWhitelistedLocked() ? + "WHITELISTED" : "PINNABLE")); mLockTaskAuth = isLockTaskWhitelistedLocked() ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE; break; case LOCK_TASK_LAUNCH_MODE_NEVER: + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + + " mLockTaskAuth=" + (mPrivileged ? "DONT_LOCK" : "PINNABLE")); mLockTaskAuth = mPrivileged ? LOCK_TASK_AUTH_DONT_LOCK : LOCK_TASK_AUTH_PINNABLE; break; case LOCK_TASK_LAUNCH_MODE_ALWAYS: + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + + " mLockTaskAuth=" + (mPrivileged ? "LAUNCHABLE" : "PINNABLE")); mLockTaskAuth = mPrivileged ? LOCK_TASK_AUTH_LAUNCHABLE: LOCK_TASK_AUTH_PINNABLE; break; case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED: + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + + " mLockTaskAuth=" + (isLockTaskWhitelistedLocked() ? + "LAUNCHABLE" : "PINNABLE")); mLockTaskAuth = isLockTaskWhitelistedLocked() ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; break; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 47ddfec..6c83192 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -564,8 +564,6 @@ public class AudioService extends IAudioService.Stub { return "card=" + card + ";device=" + device + ";"; } - private final String DEVICE_NAME_A2DP = "a2dp-device"; - /////////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////////// @@ -4387,7 +4385,7 @@ public class AudioService extends IAudioService.Stub { } // must be called synchronized on mConnectedDevices - private void makeA2dpDeviceAvailable(String address) { + private void makeA2dpDeviceAvailable(String address, String name) { // enable A2DP before notifying A2DP connection to avoid unecessary processing in // audio policy manager VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; @@ -4395,12 +4393,12 @@ public class AudioService extends IAudioService.Stub { AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); setBluetoothA2dpOnInt(true); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_AVAILABLE, address, DEVICE_NAME_A2DP); + AudioSystem.DEVICE_STATE_AVAILABLE, address, name); // Reset A2DP suspend state each time a new sink is connected AudioSystem.setParameters("A2dpSuspended=false"); mConnectedDevices.put( makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address), - new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, DEVICE_NAME_A2DP, + new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name, address)); } @@ -4414,7 +4412,7 @@ public class AudioService extends IAudioService.Stub { mAvrcpAbsVolSupported = false; } AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, DEVICE_NAME_A2DP); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, ""); mConnectedDevices.remove( makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address)); synchronized (mCurAudioRoutes) { @@ -4444,17 +4442,17 @@ public class AudioService extends IAudioService.Stub { // must be called synchronized on mConnectedDevices private void makeA2dpSrcAvailable(String address) { AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_AVAILABLE, address, DEVICE_NAME_A2DP); + AudioSystem.DEVICE_STATE_AVAILABLE, address, ""); mConnectedDevices.put( makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address), - new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, DEVICE_NAME_A2DP, + new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "", address)); } // must be called synchronized on mConnectedDevices private void makeA2dpSrcUnavailable(String address) { AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, DEVICE_NAME_A2DP); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, ""); mConnectedDevices.remove( makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address)); } @@ -4520,7 +4518,7 @@ public class AudioService extends IAudioService.Stub { makeA2dpDeviceUnavailableNow(mDockAddress); } } - makeA2dpDeviceAvailable(address); + makeA2dpDeviceAvailable(address, btDevice.getName()); synchronized (mCurAudioRoutes) { String name = btDevice.getAliasName(); if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) { @@ -4871,7 +4869,7 @@ public class AudioService extends IAudioService.Stub { if (btDevice == null) { return; } - + address = btDevice.getAddress(); BluetoothClass btClass = btDevice.getBluetoothClass(); if (btClass != null) { @@ -4891,9 +4889,11 @@ public class AudioService extends IAudioService.Stub { } boolean connected = (state == BluetoothProfile.STATE_CONNECTED); + + String btDeviceName = btDevice.getName(); boolean success = - handleDeviceConnection(connected, outDevice, address, "Bluetooth Headset") && - handleDeviceConnection(connected, inDevice, address, "Bluetooth Headset"); + handleDeviceConnection(connected, outDevice, address, btDeviceName) && + handleDeviceConnection(connected, inDevice, address, btDeviceName); if (success) { synchronized (mScoClients) { if (connected) { diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 8a7c902..eac748f 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -50,12 +50,11 @@ public class NetworkAgentInfo { public final NetworkMisc networkMisc; // Indicates if netd has been told to create this Network. Once created the appropriate routing // rules are setup and routes are added so packets can begin flowing over the Network. - // NOTE: This is a sticky bit; once set it is never cleared. + // This is a sticky bit; once set it is never cleared. public boolean created; // Set to true if this Network successfully passed validation or if it did not satisfy the // default NetworkRequest in which case validation will not be attempted. - // NOTE: This is a sticky bit; once set it is never cleared even if future validation attempts - // fail. + // This is a sticky bit; once set it is never cleared even if future validation attempts fail. public boolean everValidated; // The result of the last validation attempt on this network (true if validated, false if not). @@ -65,6 +64,10 @@ public class NetworkAgentInfo { // TODO: Fix the network scoring code, remove this, and rename everValidated to validated. public boolean lastValidated; + // Whether a captive portal was ever detected on this network. + // This is a sticky bit; once set it is never cleared. + public boolean captivePortalDetected; + // This represents the last score received from the NetworkAgent. private int currentScore; // Penalty applied to scores of Networks that have not been validated. @@ -101,9 +104,6 @@ public class NetworkAgentInfo { currentScore = score; networkMonitor = new NetworkMonitor(context, handler, this, defaultRequest); networkMisc = misc; - created = false; - everValidated = false; - lastValidated = false; } public void addRequest(NetworkRequest networkRequest) { @@ -166,6 +166,7 @@ public class NetworkAgentInfo { "created{" + created + "} " + "explicitlySelected{" + networkMisc.explicitlySelected + "} " + "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + + "captivePortalDetected{" + captivePortalDetected + "} " + "}"; } diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index f154c73..d68b615 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -58,6 +58,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; @@ -1814,7 +1815,7 @@ public class SyncStorageEngine extends Handler { Log.v(TAG_FILE, "Reading " + mAccountInfoFile.getBaseFile()); } XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int eventType = parser.getEventType(); while (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_DOCUMENT) { @@ -2153,7 +2154,7 @@ public class SyncStorageEngine extends Handler { try { fos = mAccountInfoFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -2445,7 +2446,7 @@ public class SyncStorageEngine extends Handler { } XmlPullParser parser; parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int eventType = parser.getEventType(); while (eventType != XmlPullParser.START_TAG && @@ -2581,7 +2582,7 @@ public class SyncStorageEngine extends Handler { } fos = mPendingFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); for (int i = 0; i < N; i++) { PendingOperation pop = mPendingOperations.get(i); @@ -2634,7 +2635,7 @@ public class SyncStorageEngine extends Handler { try { XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); writePendingOperationLocked(op, out); out.endDocument(); mPendingFile.finishWrite(fos); diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 080665a..0462035 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -34,6 +34,8 @@ import android.view.SurfaceControl; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,6 +49,21 @@ import java.util.regex.Pattern; * service as usual. The UI handler is only used by the {@link OverlayDisplayWindow}. * </p><p> * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. + * </p><p> + * This adapter is configured via the + * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be + * formatted as follows: + * <pre> + * [mode1]|[mode2]|...,[flag1],[flag2],... + * </pre> + * with each mode specified as: + * <pre> + * [width]x[height]/[densityDpi] + * </pre> + * Supported flags: + * <ul> + * <li><pre>secure</pre>: creates a secure display</li> + * </ul> * </p> */ final class OverlayDisplayAdapter extends DisplayAdapter { @@ -58,8 +75,10 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private static final int MAX_WIDTH = 4096; private static final int MAX_HEIGHT = 4096; - private static final Pattern SETTING_PATTERN = - Pattern.compile("(\\d+)x(\\d+)/(\\d+)(,[a-z]+)*"); + private static final Pattern DISPLAY_PATTERN = + Pattern.compile("([^,]+)(,[a-z]+)*"); + private static final Pattern MODE_PATTERN = + Pattern.compile("(\\d+)x(\\d+)/(\\d+)"); // Unique id prefix for overlay displays. private static final String UNIQUE_ID_PREFIX = "overlay:"; @@ -136,40 +155,49 @@ final class OverlayDisplayAdapter extends DisplayAdapter { int count = 0; for (String part : value.split(";")) { - Matcher matcher = SETTING_PATTERN.matcher(part); - if (matcher.matches()) { + Matcher displayMatcher = DISPLAY_PATTERN.matcher(part); + if (displayMatcher.matches()) { if (count >= 4) { Slog.w(TAG, "Too many overlay display devices specified: " + value); break; } - try { - int width = Integer.parseInt(matcher.group(1), 10); - int height = Integer.parseInt(matcher.group(2), 10); - int densityDpi = Integer.parseInt(matcher.group(3), 10); - String flagString = matcher.group(4); - if (width >= MIN_WIDTH && width <= MAX_WIDTH - && height >= MIN_HEIGHT && height <= MAX_HEIGHT - && densityDpi >= DisplayMetrics.DENSITY_LOW - && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) { - int number = ++count; - String name = getContext().getResources().getString( - com.android.internal.R.string.display_manager_overlay_display_name, - number); - int gravity = chooseOverlayGravity(number); - boolean secure = flagString != null && flagString.contains(",secure"); - - Slog.i(TAG, "Showing overlay display device #" + number - + ": name=" + name + ", width=" + width + ", height=" + height - + ", densityDpi=" + densityDpi + ", secure=" + secure); - - mOverlays.add(new OverlayDisplayHandle(name, - width, height, densityDpi, gravity, secure, number)); + String modeString = displayMatcher.group(1); + String flagString = displayMatcher.group(2); + ArrayList<OverlayMode> modes = new ArrayList<>(); + for (String mode : modeString.split("\\|")) { + Matcher modeMatcher = MODE_PATTERN.matcher(mode); + if (modeMatcher.matches()) { + try { + int width = Integer.parseInt(modeMatcher.group(1), 10); + int height = Integer.parseInt(modeMatcher.group(2), 10); + int densityDpi = Integer.parseInt(modeMatcher.group(3), 10); + if (width >= MIN_WIDTH && width <= MAX_WIDTH + && height >= MIN_HEIGHT && height <= MAX_HEIGHT + && densityDpi >= DisplayMetrics.DENSITY_LOW + && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) { + modes.add(new OverlayMode(width, height, densityDpi)); + continue; + } + } catch (NumberFormatException ex) { + } + } else if (mode.isEmpty()) { continue; } - } catch (NumberFormatException ex) { } - } else if (part.isEmpty()) { - continue; + if (!modes.isEmpty()) { + int number = ++count; + String name = getContext().getResources().getString( + com.android.internal.R.string.display_manager_overlay_display_name, + number); + int gravity = chooseOverlayGravity(number); + boolean secure = flagString != null && flagString.contains(",secure"); + + Slog.i(TAG, "Showing overlay display device #" + number + + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray())); + + mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, secure, number)); + continue; + } } Slog.w(TAG, "Malformed overlay display devices setting: " + value); } @@ -189,36 +217,41 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } } - private final class OverlayDisplayDevice extends DisplayDevice { + private abstract class OverlayDisplayDevice extends DisplayDevice { private final String mName; - private final int mWidth; - private final int mHeight; private final float mRefreshRate; private final long mDisplayPresentationDeadlineNanos; - private final int mDensityDpi; private final boolean mSecure; - private final Display.Mode mMode; + private final List<OverlayMode> mRawModes; + private final Display.Mode[] mModes; + private final int mDefaultMode; private int mState; private SurfaceTexture mSurfaceTexture; private Surface mSurface; private DisplayDeviceInfo mInfo; + private int mActiveMode; public OverlayDisplayDevice(IBinder displayToken, String name, - int width, int height, float refreshRate, long presentationDeadlineNanos, - int densityDpi, boolean secure, int state, + List<OverlayMode> modes, int activeMode, int defaultMode, + float refreshRate, long presentationDeadlineNanos, + boolean secure, int state, SurfaceTexture surfaceTexture, int number) { super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number); mName = name; - mWidth = width; - mHeight = height; mRefreshRate = refreshRate; mDisplayPresentationDeadlineNanos = presentationDeadlineNanos; - mDensityDpi = densityDpi; mSecure = secure; mState = state; mSurfaceTexture = surfaceTexture; - mMode = createMode(width, height, refreshRate); + mRawModes = modes; + mModes = new Display.Mode[modes.size()]; + for (int i = 0; i < modes.size(); i++) { + OverlayMode mode = modes.get(i); + mModes[i] = createMode(mode.mWidth, mode.mHeight, refreshRate); + } + mActiveMode = activeMode; + mDefaultMode = defaultMode; } public void destroyLocked() { @@ -248,17 +281,19 @@ final class OverlayDisplayAdapter extends DisplayAdapter { @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { if (mInfo == null) { + Display.Mode mode = mModes[mActiveMode]; + OverlayMode rawMode = mRawModes.get(mActiveMode); mInfo = new DisplayDeviceInfo(); mInfo.name = mName; mInfo.uniqueId = getUniqueId(); - mInfo.width = mWidth; - mInfo.height = mHeight; - mInfo.modeId = mMode.getModeId(); - mInfo.defaultModeId = mMode.getModeId(); - mInfo.supportedModes = new Display.Mode[] { mMode }; - mInfo.densityDpi = mDensityDpi; - mInfo.xDpi = mDensityDpi; - mInfo.yDpi = mDensityDpi; + mInfo.width = mode.getPhysicalWidth(); + mInfo.height = mode.getPhysicalHeight(); + mInfo.modeId = mode.getModeId(); + mInfo.defaultModeId = mModes[0].getModeId(); + mInfo.supportedModes = mModes; + mInfo.densityDpi = rawMode.mDensityDpi; + mInfo.xDpi = rawMode.mDensityDpi; + mInfo.yDpi = rawMode.mDensityDpi; mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos + 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; @@ -271,6 +306,40 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } return mInfo; } + + @Override + public void requestModeInTransactionLocked(int id) { + int index = -1; + if (id == 0) { + // Use the default. + index = 0; + } else { + for (int i = 0; i < mModes.length; i++) { + if (mModes[i].getModeId() == id) { + index = i; + break; + } + } + } + if (index == -1) { + Slog.w(TAG, "Unable to locate mode " + id + ", reverting to default."); + index = mDefaultMode; + } + if (mActiveMode == index) { + return; + } + mActiveMode = index; + mInfo = null; + sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); + onModeChangedLocked(index); + } + + /** + * Called when the device switched to a new mode. + * + * @param index index of the mode in the list of modes + */ + public abstract void onModeChangedLocked(int index); } /** @@ -280,27 +349,32 @@ final class OverlayDisplayAdapter extends DisplayAdapter { * Guarded by the {@link DisplayManagerService.SyncRoot} lock. */ private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener { + private static final int DEFAULT_MODE_INDEX = 0; + private final String mName; - private final int mWidth; - private final int mHeight; - private final int mDensityDpi; + private final List<OverlayMode> mModes; private final int mGravity; private final boolean mSecure; private final int mNumber; private OverlayDisplayWindow mWindow; private OverlayDisplayDevice mDevice; + private int mActiveMode; - public OverlayDisplayHandle(String name, int width, - int height, int densityDpi, int gravity, boolean secure, int number) { + public OverlayDisplayHandle(String name, List<OverlayMode> modes, int gravity, + boolean secure, int number) { mName = name; - mWidth = width; - mHeight = height; - mDensityDpi = densityDpi; + mModes = modes; mGravity = gravity; mSecure = secure; mNumber = number; + mActiveMode = 0; + + showLocked(); + } + + private void showLocked() { mUiHandler.post(mShowRunnable); } @@ -309,15 +383,28 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mUiHandler.post(mDismissRunnable); } + private void onActiveModeChangedLocked(int index) { + mUiHandler.removeCallbacks(mResizeRunnable); + mActiveMode = index; + if (mWindow != null) { + mUiHandler.post(mResizeRunnable); + } + } + // Called on the UI thread. @Override public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, long presentationDeadlineNanos, int state) { synchronized (getSyncRoot()) { IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure); - mDevice = new OverlayDisplayDevice(displayToken, mName, - mWidth, mHeight, refreshRate, presentationDeadlineNanos, - mDensityDpi, mSecure, state, surfaceTexture, mNumber); + mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode, + DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos, + mSecure, state, surfaceTexture, mNumber) { + @Override + public void onModeChangedLocked(int index) { + onActiveModeChangedLocked(index); + } + }; sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED); } @@ -347,9 +434,8 @@ final class OverlayDisplayAdapter extends DisplayAdapter { public void dumpLocked(PrintWriter pw) { pw.println(" " + mName + ":"); - pw.println(" mWidth=" + mWidth); - pw.println(" mHeight=" + mHeight); - pw.println(" mDensityDpi=" + mDensityDpi); + pw.println(" mModes=" + Arrays.toString(mModes.toArray())); + pw.println(" mActiveMode=" + mActiveMode); pw.println(" mGravity=" + mGravity); pw.println(" mSecure=" + mSecure); pw.println(" mNumber=" + mNumber); @@ -366,8 +452,9 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private final Runnable mShowRunnable = new Runnable() { @Override public void run() { + OverlayMode mode = mModes.get(mActiveMode); OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), - mName, mWidth, mHeight, mDensityDpi, mGravity, mSecure, + mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mSecure, OverlayDisplayHandle.this); window.show(); @@ -392,5 +479,47 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } } }; + + // Runs on the UI thread. + private final Runnable mResizeRunnable = new Runnable() { + @Override + public void run() { + OverlayMode mode; + OverlayDisplayWindow window; + synchronized (getSyncRoot()) { + if (mWindow == null) { + return; + } + mode = mModes.get(mActiveMode); + window = mWindow; + } + window.resize(mode.mWidth, mode.mHeight, mode.mDensityDpi); + } + }; + } + + /** + * A display mode for an overlay display. + */ + private static final class OverlayMode { + final int mWidth; + final int mHeight; + final int mDensityDpi; + + OverlayMode(int width, int height, int densityDpi) { + mWidth = width; + mHeight = height; + mDensityDpi = densityDpi; + } + + @Override + public String toString() { + return new StringBuilder("{") + .append("width=").append(mWidth) + .append(", height=").append(mHeight) + .append(", densityDpi=").append(mDensityDpi) + .append("}") + .toString(); + } } } diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java index 786889a..f23caf2 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java @@ -60,9 +60,9 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { private final Context mContext; private final String mName; - private final int mWidth; - private final int mHeight; - private final int mDensityDpi; + private int mWidth; + private int mHeight; + private int mDensityDpi; private final int mGravity; private final boolean mSecure; private final Listener mListener; @@ -97,19 +97,9 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { Listener listener) { mContext = context; mName = name; - mWidth = width; - mHeight = height; - mDensityDpi = densityDpi; mGravity = gravity; mSecure = secure; mListener = listener; - mTitle = context.getResources().getString( - com.android.internal.R.string.display_manager_overlay_display_title, - mName, mWidth, mHeight, mDensityDpi); - if (secure) { - mTitle += context.getResources().getString( - com.android.internal.R.string.display_manager_overlay_display_secure_suffix); - } mDisplayManager = (DisplayManager)context.getSystemService( Context.DISPLAY_SERVICE); @@ -119,6 +109,8 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { mDefaultDisplay = mWindowManager.getDefaultDisplay(); updateDefaultDisplayInfo(); + resize(width, height, densityDpi, false /* doLayout */); + createWindow(); } @@ -145,6 +137,26 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { } } + public void resize(int width, int height, int densityDpi) { + resize(width, height, densityDpi, true /* doLayout */); + } + + private void resize(int width, int height, int densityDpi, boolean doLayout) { + mWidth = width; + mHeight = height; + mDensityDpi = densityDpi; + mTitle = mContext.getResources().getString( + com.android.internal.R.string.display_manager_overlay_display_title, + mName, mWidth, mHeight, mDensityDpi); + if (mSecure) { + mTitle += mContext.getResources().getString( + com.android.internal.R.string.display_manager_overlay_display_secure_suffix); + } + if (doLayout) { + relayout(); + } + } + public void relayout() { if (mWindowVisible) { updateWindowParams(); diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 67b3695..d676b35 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -35,6 +35,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import libcore.io.IoUtils; @@ -195,7 +196,7 @@ final class PersistentDataStore { XmlPullParser parser; try { parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream(is), null); + parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name()); loadFromXml(parser); } catch (IOException ex) { Slog.w(TAG, "Failed to load display manager persistent store data.", ex); @@ -215,7 +216,7 @@ final class PersistentDataStore { boolean success = false; try { XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(new BufferedOutputStream(os), "utf-8"); + serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name()); saveToXml(serializer); serializer.flush(); success = true; @@ -284,4 +285,4 @@ final class PersistentDataStore { serializer.endTag(null, "display-manager-state"); serializer.endDocument(); } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java index 92fa813..f6d7244 100644 --- a/services/core/java/com/android/server/input/PersistentDataStore.java +++ b/services/core/java/com/android/server/input/PersistentDataStore.java @@ -37,6 +37,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -214,7 +215,7 @@ final class PersistentDataStore { XmlPullParser parser; try { parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream(is), null); + parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name()); loadFromXml(parser); } catch (IOException ex) { Slog.w(InputManagerService.TAG, "Failed to load input manager persistent store data.", ex); @@ -234,7 +235,7 @@ final class PersistentDataStore { boolean success = false; try { XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(new BufferedOutputStream(os), "utf-8"); + serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name()); saveToXml(serializer); serializer.flush(); success = true; diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index b64c677..24d4f15 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -41,6 +41,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -292,7 +293,7 @@ public class JobStore { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(baos, "utf-8"); + out.setOutput(baos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -450,7 +451,7 @@ public class JobStore { private List<JobStatus> readJobMapImpl(FileInputStream fis) throws XmlPullParserException, IOException { XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int eventType = parser.getEventType(); while (eventType != XmlPullParser.START_TAG && diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 0ae6735..24ab3b8 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -170,6 +170,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -1290,7 +1291,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub try { fis = mPolicyFile.openRead(); final XmlPullParser in = Xml.newPullParser(); - in.setInput(fis, null); + in.setInput(fis, StandardCharsets.UTF_8.name()); int type; int version = VERSION_INIT; @@ -1425,7 +1426,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub fos = mPolicyFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, TAG_POLICY_LIST); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 290fb65..ec039b0 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -120,6 +120,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashSet; @@ -391,7 +392,7 @@ public class NotificationManagerService extends SystemService { try { infile = mPolicyFile.openRead(); final XmlPullParser parser = Xml.newPullParser(); - parser.setInput(infile, null); + parser.setInput(infile, StandardCharsets.UTF_8.name()); int type; String tag; @@ -449,7 +450,7 @@ public class NotificationManagerService extends SystemService { try { final XmlSerializer out = new FastXmlSerializer(); - out.setOutput(stream, "utf-8"); + out.setOutput(stream, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, TAG_BODY); out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION)); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 09096ff..a1738a2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -105,6 +105,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; @@ -323,7 +324,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { try { fis = mSessionsFile.openRead(); final XmlPullParser in = Xml.newPullParser(); - in.setInput(fis, null); + in.setInput(fis, StandardCharsets.UTF_8.name()); int type; while ((type = in.next()) != END_DOCUMENT) { @@ -410,7 +411,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { fos = mSessionsFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(fos, "utf-8"); + out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, TAG_SESSIONS); final int size = mSessions.size(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 19210c9..944fa52 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4137,7 +4137,9 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { final int count = candidates.size(); - // First, try to use the domain prefered App + // First, try to use the domain prefered App. Partition the candidates into four lists: + // one for the final results, one for the "do not use ever", one for "undefined status" + // and finally one for "Browser App type". for (int n=0; n<count; n++) { ResolveInfo info = candidates.get(n); String packageName = info.activityInfo.packageName; @@ -4159,19 +4161,19 @@ public class PackageManagerService extends IPackageManager.Stub { } } } + // Add all undefined Apps as we want them to appear in the Disambiguation dialog. + result.addAll(undefinedList); // If there is nothing selected, add all candidates and remove the ones that the User // has explicitely put into the INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER state and - // also remove any undefined ones and Browser Apps ones. - // If there is still none after this pass, add all undefined one and Browser Apps and + // also remove Browser Apps ones. + // If there is still none after this pass, add all Browser Apps and // let the User decide with the Disambiguation dialog if there are several ones. if (result.size() == 0) { result.addAll(candidates); } result.removeAll(neverList); result.removeAll(matchAllList); - result.removeAll(undefinedList); if (result.size() == 0) { - result.addAll(undefinedList); if ((flags & MATCH_ALL) != 0) { result.addAll(matchAllList); } else { @@ -11459,6 +11461,21 @@ public class PackageManagerService extends IPackageManager.Stub { replace = true; if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); } + + // Prevent apps opting out from runtime permissions + if (replace) { + PackageParser.Package oldPackage = mPackages.get(pkgName); + final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion; + final int newTargetSdk = pkg.applicationInfo.targetSdkVersion; + if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1 + && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) { + res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE, + "Package " + pkg.packageName + " new target SDK " + newTargetSdk + + " doesn't support runtime permissions but the old" + + " target SDK " + oldTargetSdk + " does."); + return; + } + } } PackageSetting ps = mSettings.mPackages.get(pkgName); @@ -13037,7 +13054,7 @@ public class PackageManagerService extends IPackageManager.Stub { ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); try { final XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(dataStream, "utf-8"); + serializer.setOutput(dataStream, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.startTag(null, TAG_PREFERRED_BACKUP); @@ -13066,7 +13083,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { final XmlPullParser parser = Xml.newPullParser(); - parser.setInput(new ByteArrayInputStream(backup), null); + parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG @@ -13848,7 +13865,7 @@ public class PackageManagerService extends IPackageManager.Stub { BufferedOutputStream str = new BufferedOutputStream(fout); XmlSerializer serializer = new FastXmlSerializer(); try { - serializer.setOutput(str, "utf-8"); + serializer.setOutput(str, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output", true); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 2e9656a..76ef19f 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -94,6 +94,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -1346,7 +1347,7 @@ final class Settings { str = new FileInputStream(userPackagesStateFile); } final XmlPullParser parser = Xml.newPullParser(); - parser.setInput(str, null); + parser.setInput(str, StandardCharsets.UTF_8.name()); int type; while ((type=parser.next()) != XmlPullParser.START_TAG @@ -1598,7 +1599,7 @@ final class Settings { final BufferedOutputStream str = new BufferedOutputStream(fstr); final XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(str, "utf-8"); + serializer.setOutput(str, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -1922,7 +1923,7 @@ final class Settings { //XmlSerializer serializer = XmlUtils.serializerInstance(); XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(str, "utf-8"); + serializer.setOutput(str, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -2339,7 +2340,7 @@ final class Settings { str = new FileInputStream(mSettingsFilename); } XmlPullParser parser = Xml.newPullParser(); - parser.setInput(str, null); + parser.setInput(str, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG @@ -4288,7 +4289,7 @@ final class Settings { out = destination.startWrite(); XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(out, "utf-8"); + serializer.setOutput(out, StandardCharsets.UTF_8.name()); serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startDocument(null, true); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e463fad..40c8ca3 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -70,6 +70,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -670,7 +671,7 @@ public class UserManagerService extends IUserManager.Stub { try { fis = userListFile.openRead(); XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { @@ -823,7 +824,7 @@ public class UserManagerService extends IUserManager.Stub { // XmlSerializer serializer = XmlUtils.serializerInstance(); final XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(bos, "utf-8"); + serializer.setOutput(bos, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -882,7 +883,7 @@ public class UserManagerService extends IUserManager.Stub { // XmlSerializer serializer = XmlUtils.serializerInstance(); final XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(bos, "utf-8"); + serializer.setOutput(bos, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -964,7 +965,7 @@ public class UserManagerService extends IUserManager.Stub { new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX)); fis = userFile.openRead(); XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { @@ -1569,7 +1570,7 @@ public class UserManagerService extends IUserManager.Stub { try { fis = restrictionsFile.openRead(); XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); + parser.setInput(fis, StandardCharsets.UTF_8.name()); XmlUtils.nextElement(parser); if (parser.getEventType() != XmlPullParser.START_TAG) { Slog.e(LOG_TAG, "Unable to read restrictions file " @@ -1658,7 +1659,7 @@ public class UserManagerService extends IUserManager.Stub { final BufferedOutputStream bos = new BufferedOutputStream(fos); final XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(bos, "utf-8"); + serializer.setOutput(bos, StandardCharsets.UTF_8.name()); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java index fcfaaea..f9b5b9a 100644 --- a/services/core/java/com/android/server/tv/PersistentDataStore.java +++ b/services/core/java/com/android/server/tv/PersistentDataStore.java @@ -44,6 +44,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -167,7 +168,7 @@ final class PersistentDataStore { XmlPullParser parser; try { parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream(is), null); + parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name()); loadFromXml(parser); } catch (IOException | XmlPullParserException ex) { Slog.w(TAG, "Failed to load tv input manager persistent store data.", ex); @@ -200,7 +201,7 @@ final class PersistentDataStore { boolean success = false; try { XmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(new BufferedOutputStream(os), "utf-8"); + serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name()); saveToXml(serializer); serializer.flush(); success = true; diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index e649e48..a869c20 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -39,6 +39,7 @@ import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; +import android.media.tv.DvbDeviceInfo; import android.media.tv.ITvInputClient; import android.media.tv.ITvInputHardware; import android.media.tv.ITvInputHardwareCallback; @@ -64,6 +65,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -80,23 +82,34 @@ import com.android.server.SystemService; import org.xmlpull.v1.XmlPullParserException; +import java.io.File; import java.io.FileDescriptor; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; +import java.lang.IllegalArgumentException; +import java.lang.Integer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** This class provides a system service that manages television inputs. */ public final class TvInputManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "TvInputManagerService"; + // Pattern for selecting the DVB frontend devices from the list of files in the /dev directory. + private static final Pattern sFrontEndDevicePattern = + Pattern.compile("^dvb([0-9]+)\\.frontend([0-9]+)$"); + private final Context mContext; private final TvInputHardwareManager mTvInputHardwareManager; @@ -1507,6 +1520,74 @@ public final class TvInputManagerService extends SystemService { } @Override + public List<DvbDeviceInfo> getDvbDeviceList() throws RemoteException { + if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires DVB_DEVICE permission"); + } + + final long identity = Binder.clearCallingIdentity(); + try { + ArrayList<DvbDeviceInfo> deviceInfos = new ArrayList<>(); + File devDirectory = new File("/dev"); + for (String fileName : devDirectory.list()) { + Matcher matcher = sFrontEndDevicePattern.matcher(fileName); + if (matcher.find()) { + int adapterId = Integer.parseInt(matcher.group(1)); + int deviceId = Integer.parseInt(matcher.group(2)); + deviceInfos.add(new DvbDeviceInfo(adapterId, deviceId)); + } + } + return Collections.unmodifiableList(deviceInfos); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) + throws RemoteException { + if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires DVB_DEVICE permission"); + } + + final long identity = Binder.clearCallingIdentity(); + try { + String deviceFileName; + switch (device) { + case TvInputManager.DVB_DEVICE_DEMUX: + deviceFileName = String.format("/dev/dvb%d.demux%d", info.getAdapterId(), + info.getDeviceId()); + break; + case TvInputManager.DVB_DEVICE_DVR: + deviceFileName = String.format("/dev/dvb%d.dvr%d", info.getAdapterId(), + info.getDeviceId()); + break; + case TvInputManager.DVB_DEVICE_FRONTEND: + deviceFileName = String.format("/dev/dvb%d.frontend%d", info.getAdapterId(), + info.getDeviceId()); + break; + default: + throw new IllegalArgumentException("Invalid DVB device: " + device); + } + try { + // The DVB frontend device only needs to be opened in read/write mode, which + // allows performing tuning operations. The DVB demux and DVR device are enough + // to be opened in read only mode. + return ParcelFileDescriptor.open(new File(deviceFileName), + TvInputManager.DVB_DEVICE_FRONTEND == device + ? ParcelFileDescriptor.MODE_READ_WRITE + : ParcelFileDescriptor.MODE_READ_ONLY); + } catch (FileNotFoundException e) { + return null; + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) throws RemoteException { if (mContext.checkCallingPermission( diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 755c414..7784884 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -79,6 +79,7 @@ import java.io.FileNotFoundException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.List; import org.xmlpull.v1.XmlPullParser; @@ -589,12 +590,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { void switchUser(int userId, IRemoteCallback reply) { synchronized (mLock) { mCurrentUserId = userId; - WallpaperData wallpaper = mWallpaperMap.get(userId); - if (wallpaper == null) { - wallpaper = new WallpaperData(userId); - mWallpaperMap.put(userId, wallpaper); - loadSettingsLocked(userId); - } + WallpaperData wallpaper = getWallpaperSafeLocked(userId); // Not started watching yet, in case wallpaper data was loaded for other reasons. if (wallpaper.wallpaperObserver == null) { wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); @@ -717,10 +713,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } synchronized (mLock) { int userId = UserHandle.getCallingUserId(); - WallpaperData wallpaper = mWallpaperMap.get(userId); - if (wallpaper == null) { - throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); - } + WallpaperData wallpaper = getWallpaperSafeLocked(userId); if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } @@ -782,10 +775,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } synchronized (mLock) { int userId = UserHandle.getCallingUserId(); - WallpaperData wallpaper = mWallpaperMap.get(userId); - if (wallpaper == null) { - throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); - } + WallpaperData wallpaper = getWallpaperSafeLocked(userId); if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) { throw new IllegalArgumentException("padding must be positive: " + padding); } @@ -866,10 +856,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { synchronized (mLock) { if (DEBUG) Slog.v(TAG, "setWallpaper"); int userId = UserHandle.getCallingUserId(); - WallpaperData wallpaper = mWallpaperMap.get(userId); - if (wallpaper == null) { - throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); - } + WallpaperData wallpaper = getWallpaperSafeLocked(userId); final long ident = Binder.clearCallingIdentity(); try { ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper); @@ -1165,7 +1152,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { try { stream = new FileOutputStream(journal.chooseForWrite(), false); XmlSerializer out = new FastXmlSerializer(); - out.setOutput(stream, "utf-8"); + out.setOutput(stream, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, "wp"); @@ -1229,6 +1216,22 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return Integer.parseInt(value); } + /** + * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could + * happen during user switch. The async user switch observer may not have received + * the event yet. We use this safe method when we don't care about this ordering and just + * want to update the data. The data is going to be applied when the user switch observer + * is eventually executed. + */ + private WallpaperData getWallpaperSafeLocked(int userId) { + WallpaperData wallpaper = mWallpaperMap.get(userId); + if (wallpaper == null) { + loadSettingsLocked(userId); + wallpaper = mWallpaperMap.get(userId); + } + return wallpaper; + } + private void loadSettingsLocked(int userId) { if (DEBUG) Slog.v(TAG, "loadSettingsLocked"); @@ -1248,7 +1251,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { try { stream = new FileInputStream(file); XmlPullParser parser = Xml.newPullParser(); - parser.setInput(stream, null); + parser.setInput(stream, StandardCharsets.UTF_8.name()); int type; do { diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 9033c9c..0357de2 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -289,11 +289,13 @@ public class AppTransition implements Dump { return mNextAppTransitionStartY; } - void prepare() { + boolean prepare() { if (!isRunning()) { mAppTransitionState = APP_STATE_IDLE; notifyAppTransitionPendingLocked(); + return true; } + return false; } void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) { @@ -953,8 +955,8 @@ public class AppTransition implements Dump { : com.android.internal.R.anim.voice_activity_open_exit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation voice:" - + " anim=" + a + " transit=" + transit + " isEntrance=" + enter - + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " transit=" + appTransitionToString(transit) + + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE || transit == TRANSIT_TASK_CLOSE || transit == TRANSIT_TASK_TO_BACK)) { @@ -963,22 +965,23 @@ public class AppTransition implements Dump { : com.android.internal.R.anim.voice_activity_close_exit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation voice:" - + " anim=" + a + " transit=" + transit + " isEntrance=" + enter - + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " transit=" + appTransitionToString(transit) + + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { a = loadAnimationRes(mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) { a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" - + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" - + " transit=" + transit + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" + + " transit=" + appTransitionToString(transit) + + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { a = createClipRevealAnimationLocked(transit, enter, appFrame); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, @@ -990,7 +993,7 @@ public class AppTransition implements Dump { if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP || mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) { @@ -1003,7 +1006,7 @@ public class AppTransition implements Dump { "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + animName - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP || @@ -1018,7 +1021,7 @@ public class AppTransition implements Dump { "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN"; Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + animName - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } } else { @@ -1084,7 +1087,7 @@ public class AppTransition implements Dump { "applyAnimation:" + " anim=" + a + " animAttr=0x" + Integer.toHexString(animAttr) - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } return a; @@ -1188,7 +1191,7 @@ public class AppTransition implements Dump { @Override public String toString() { - return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); + return "mNextAppTransition=" + appTransitionToString(mNextAppTransition); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 21011e8..3feec82 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -16,6 +16,11 @@ package com.android.server.wm; +import static com.android.server.wm.WindowManagerService.DEBUG_ANIM; +import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS; +import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; + import android.graphics.Matrix; import android.util.Slog; import android.util.TimeUtils; @@ -78,7 +83,11 @@ public class AppWindowAnimator { boolean deferFinalFrameCleanup; /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */ - ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>(); + ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<>(); + + /** True if the current animation was transferred from another AppWindowAnimator. + * See {@link #transferCurrentAnimation}*/ + boolean usingTransferredAnimation = false; static final Animation sDummyAnimation = new DummyAnimation(); @@ -102,9 +111,9 @@ public class AppWindowAnimator { int zorder = anim.getZAdjustment(); int adj = 0; if (zorder == Animation.ZORDER_TOP) { - adj = WindowManagerService.TYPE_LAYER_OFFSET; + adj = TYPE_LAYER_OFFSET; } else if (zorder == Animation.ZORDER_BOTTOM) { - adj = -WindowManagerService.TYPE_LAYER_OFFSET; + adj = -TYPE_LAYER_OFFSET; } if (animLayerAdjustment != adj) { @@ -140,6 +149,7 @@ public class AppWindowAnimator { mAppToken.allDrawn = false; mAppToken.deferClearAllDrawn = false; } + usingTransferredAnimation = false; } public boolean isAnimating() { @@ -154,19 +164,38 @@ public class AppWindowAnimator { deferThumbnailDestruction = false; } + void transferCurrentAnimation( + AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) { + + if (animation != null) { + toAppAnimator.animation = animation; + animation = null; + toAppAnimator.animating = animating; + toAppAnimator.animLayerAdjustment = animLayerAdjustment; + animLayerAdjustment = 0; + toAppAnimator.updateLayers(); + updateLayers(); + toAppAnimator.usingTransferredAnimation = true; + } + if (transferWinAnimator != null) { + mAllAppWinAnimators.remove(transferWinAnimator); + toAppAnimator.mAllAppWinAnimators.add(transferWinAnimator); + transferWinAnimator.mAppAnimator = toAppAnimator; + } + } + void updateLayers() { - final int N = mAppToken.allAppWindows.size(); + final int windowCount = mAppToken.allAppWindows.size(); final int adj = animLayerAdjustment; thumbnailLayer = -1; - for (int i=0; i<N; i++) { + for (int i = 0; i < windowCount; i++) { final WindowState w = mAppToken.allAppWindows.get(i); final WindowStateAnimator winAnimator = w.mWinAnimator; winAnimator.mAnimLayer = w.mLayer + adj; if (winAnimator.mAnimLayer > thumbnailLayer) { thumbnailLayer = winAnimator.mAnimLayer; } - if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " - + winAnimator.mAnimLayer); + if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + winAnimator.mAnimLayer); if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { mService.setInputMethodAnimLayerAdjustment(adj); } @@ -191,11 +220,11 @@ public class AppWindowAnimator { // cache often used attributes locally final float tmpFloats[] = mService.mTmpFloats; thumbnailTransformation.getMatrix().getValues(tmpFloats); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] + ", " + tmpFloats[Matrix.MTRANS_Y], null); thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() + " layer=" + thumbnailLayer + " matrix=[" + tmpFloats[Matrix.MSCALE_X] @@ -228,14 +257,14 @@ public class AppWindowAnimator { deferFinalFrameCleanup = true; hasMoreFrames = true; } else { - if (false && WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames + - ", xform=" + transformation); + if (false && DEBUG_ANIM) Slog.v(TAG, + "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames + + ", xform=" + transformation); deferFinalFrameCleanup = false; animation = null; clearThumbnail(); - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Finished animation in " + mAppToken + " @ " + currentTime); + if (DEBUG_ANIM) Slog.v(TAG, + "Finished animation in " + mAppToken + " @ " + currentTime); } } hasTransformation = hasMoreFrames; @@ -258,8 +287,8 @@ public class AppWindowAnimator { if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) && animation != null) { if (!animating) { - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Starting animation in " + mAppToken + + if (DEBUG_ANIM) Slog.v(TAG, + "Starting animation in " + mAppToken + " @ " + currentTime + " scale=" + mService.getTransitionAnimationScaleLocked() + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); @@ -306,8 +335,8 @@ public class AppWindowAnimator { mService.moveInputMethodWindowsIfNeededLocked(true); } - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Animation done in " + mAppToken + if (DEBUG_ANIM) Slog.v(TAG, + "Animation done in " + mAppToken + ": reportedVisible=" + mAppToken.reportedVisible); transformation.clear(); diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java index ba995f2..01f878c 100644 --- a/services/core/java/com/android/server/wm/DisplaySettings.java +++ b/services/core/java/com/android/server/wm/DisplaySettings.java @@ -32,6 +32,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.HashMap; /** @@ -108,7 +109,7 @@ public class DisplaySettings { boolean success = false; try { XmlPullParser parser = Xml.newPullParser(); - parser.setInput(stream, null); + parser.setInput(stream, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { @@ -193,7 +194,7 @@ public class DisplaySettings { try { XmlSerializer out = new FastXmlSerializer(); - out.setOutput(stream, "utf-8"); + out.setOutput(stream, StandardCharsets.UTF_8.name()); out.startDocument(null, true); out.startTag(null, "display-settings"); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 77694b6..4972ce4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -495,7 +495,7 @@ public class WindowManagerService extends IWindowManager.Stub String mLastANRState; /** All DisplayContents in the world, kept here */ - SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); + SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2); int mRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -511,7 +511,7 @@ public class WindowManagerService extends IWindowManager.Stub deathRecipient = d; } } - ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); + ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>(); int mDeferredRotationPauseCount; int mSystemDecorLayer = 0; @@ -552,11 +552,10 @@ public class WindowManagerService extends IWindowManager.Stub private final PowerManager.WakeLock mScreenFrozenLock; final AppTransition mAppTransition; - boolean mStartingIconInTransition = false; boolean mSkipAppTransitionAnimation = false; - final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); - final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>(); + final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>(); + final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>(); boolean mIsTouchDevice; @@ -581,7 +580,7 @@ public class WindowManagerService extends IWindowManager.Stub int mInputMethodAnimLayerAdjustment; WindowState mInputMethodWindow = null; - final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); + final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>(); /** Temporary list for comparison. Always clear this after use so we don't end up with * orphaned windows references */ @@ -4146,8 +4145,8 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Prepare app transition: transit=" + transit + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:" + + " transit=" + AppTransition.appTransitionToString(transit) + " " + mAppTransition + " alwaysKeepCurrent=" + alwaysKeepCurrent + " Callers=" + Debug.getCallers(3)); @@ -4166,9 +4165,7 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition.setAppTransition(transit); } } - if (okToDisplay()) { - mAppTransition.prepare(); - mStartingIconInTransition = false; + if (okToDisplay() && mAppTransition.prepare()) { mSkipAppTransitionAnimation = false; } if (mAppTransition.isTransitionSet()) { @@ -4295,19 +4292,16 @@ public class WindowManagerService extends IWindowManager.Stub if (ttoken != null) { WindowState startingWindow = ttoken.startingWindow; if (startingWindow != null) { - if (mStartingIconInTransition) { - // In this case, the starting icon has already - // been displayed, so start letting windows get - // shown immediately without any more transitions. - mSkipAppTransitionAnimation = true; - } + // In this case, the starting icon has already been displayed, so start + // letting windows get shown immediately without any more transitions. + mSkipAppTransitionAnimation = true; + if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Moving existing starting " + startingWindow + " from " + ttoken + " to " + wtoken); final long origId = Binder.clearCallingIdentity(); - // Transfer the starting window over to the new - // token. + // Transfer the starting window over to the new token. wtoken.startingData = ttoken.startingData; wtoken.startingView = ttoken.startingView; wtoken.startingDisplayed = ttoken.startingDisplayed; @@ -4321,7 +4315,6 @@ public class WindowManagerService extends IWindowManager.Stub startingWindow.mToken = wtoken; startingWindow.mRootToken = wtoken; startingWindow.mAppToken = wtoken; - startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { Slog.v(TAG, "Removing starting window: " + startingWindow); @@ -4355,17 +4348,8 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.clientHidden = ttoken.clientHidden; wtoken.sendAppVisibilityToClients(); } - final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; - final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; - if (tAppAnimator.animation != null) { - wAppAnimator.animation = tAppAnimator.animation; - wAppAnimator.animating = tAppAnimator.animating; - wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; - tAppAnimator.animation = null; - tAppAnimator.animLayerAdjustment = 0; - wAppAnimator.updateLayers(); - tAppAnimator.updateLayers(); - } + ttoken.mAppAnimator.transferCurrentAnimation( + wtoken.mAppAnimator, startingWindow.mWinAnimator); updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); @@ -4465,7 +4449,6 @@ public class WindowManagerService extends IWindowManager.Stub } if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); - mStartingIconInTransition = true; wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags); Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); @@ -4566,8 +4549,8 @@ public class WindowManagerService extends IWindowManager.Stub changed = true; } - final int N = wtoken.allAppWindows.size(); - for (int i=0; i<N; i++) { + final int windowsCount = wtoken.allAppWindows.size(); + for (int i = 0; i < windowsCount; i++) { WindowState win = wtoken.allAppWindows.get(i); if (win == wtoken.startingWindow) { continue; @@ -4696,7 +4679,7 @@ public class WindowManagerService extends IWindowManager.Stub // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. if (okToDisplay() && mAppTransition.isTransitionSet()) { - if (!wtoken.startingDisplayed) { + if (!wtoken.startingDisplayed || mSkipAppTransitionAnimation) { if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Setting dummy animation on: " + wtoken); wtoken.mAppAnimator.setDummyAnimation(); @@ -9178,14 +9161,14 @@ public class WindowManagerService extends IWindowManager.Stub public int handleAppTransitionReadyLocked(WindowList windows) { int changes = 0; int i; - int NN = mOpeningApps.size(); + int appsCount = mOpeningApps.size(); boolean goodToGo = true; if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Checking " + NN + " opening apps (frozen=" + "Checking " + appsCount + " opening apps (frozen=" + mDisplayFrozen + " timeout=" + mAppTransition.isTimeout() + ")..."); if (!mAppTransition.isTimeout()) { - for (i=0; i<NN && goodToGo; i++) { + for (i = 0; i < appsCount && goodToGo; i++) { AppWindowToken wtoken = mOpeningApps.valueAt(i); if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Check opening app=" + wtoken + ": allDrawn=" @@ -9238,7 +9221,6 @@ public class WindowManagerService extends IWindowManager.Stub if (mSkipAppTransitionAnimation) { transit = AppTransition.TRANSIT_UNSET; } - mStartingIconInTransition = false; mSkipAppTransitionAnimation = false; mH.removeMessages(H.APP_TRANSITION_TIMEOUT); @@ -9287,17 +9269,17 @@ public class WindowManagerService extends IWindowManager.Stub // (2) Find the layout params of the top-most // application window in the tokens, which is // what will control the animation theme. - final int NC = mClosingApps.size(); - NN = NC + mOpeningApps.size(); - for (i=0; i<NN; i++) { + final int closingAppsCount = mClosingApps.size(); + appsCount = closingAppsCount + mOpeningApps.size(); + for (i = 0; i < appsCount; i++) { final AppWindowToken wtoken; - if (i < NC) { + if (i < closingAppsCount) { wtoken = mClosingApps.valueAt(i); if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { closingAppHasWallpaper = true; } } else { - wtoken = mOpeningApps.valueAt(i - NC); + wtoken = mOpeningApps.valueAt(i - closingAppsCount); if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { openingAppHasWallpaper = true; } @@ -9338,20 +9320,23 @@ public class WindowManagerService extends IWindowManager.Stub transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; break; } - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); + 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: " + transit); + "New transit away from wallpaper: " + + AppTransition.appTransitionToString(transit)); } else if (mWallpaperTarget != null && mWallpaperTarget.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: " + transit); + "New transit into wallpaper: " + + AppTransition.appTransitionToString(transit)); } else { mAnimateWallpaperWithTarget = true; } @@ -9395,21 +9380,24 @@ public class WindowManagerService extends IWindowManager.Stub } } - NN = mOpeningApps.size(); - for (i=0; i<NN; i++) { + 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); - appAnimator.clearThumbnail(); - appAnimator.animation = null; + + if (!appAnimator.usingTransferredAnimation) { + appAnimator.clearThumbnail(); + appAnimator.animation = null; + } wtoken.inPendingTransaction = false; setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); wtoken.updateReportedVisibilityLocked(); wtoken.waitingToShow = false; appAnimator.mAllAppWinAnimators.clear(); - final int N = wtoken.allAppWindows.size(); - for (int j = 0; j < N; j++) { + 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(); @@ -9417,7 +9405,7 @@ public class WindowManagerService extends IWindowManager.Stub if (animLp != null) { int layer = -1; - for (int j=0; j<wtoken.windows.size(); j++) { + for (int j = 0; j < wtoken.windows.size(); j++) { WindowState win = wtoken.windows.get(j); if (win.mWinAnimator.mAnimLayer > layer) { layer = win.mWinAnimator.mAnimLayer; @@ -9429,8 +9417,8 @@ public class WindowManagerService extends IWindowManager.Stub } } } - NN = mClosingApps.size(); - for (i=0; i<NN; i++) { + 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); @@ -9454,7 +9442,7 @@ public class WindowManagerService extends IWindowManager.Stub if (animLp != null) { int layer = -1; - for (int j=0; j<wtoken.windows.size(); j++) { + for (int j = 0; j < wtoken.windows.size(); j++) { WindowState win = wtoken.windows.get(j); if (win.mWinAnimator.mAnimLayer > layer) { layer = win.mWinAnimator.mAnimLayer; @@ -11407,8 +11395,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); - pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); - pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); + pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); pw.println(" mLayoutToAnim:"); mAppTransition.dump(pw, " "); } |