summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/AlarmManagerService.java2
-rw-r--r--services/java/com/android/server/BackupManagerService.java35
-rw-r--r--services/java/com/android/server/ConnectivityService.java9
-rw-r--r--services/java/com/android/server/PowerManagerService.java165
-rw-r--r--services/java/com/android/server/SystemServer.java3
-rw-r--r--services/java/com/android/server/WallpaperManagerService.java130
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java28
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java79
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java2
-rw-r--r--services/java/com/android/server/am/ActivityStack.java49
-rw-r--r--services/java/com/android/server/am/ContentProviderRecord.java8
-rw-r--r--services/java/com/android/server/am/IntentBindRecord.java4
-rw-r--r--services/java/com/android/server/am/PendingIntentRecord.java5
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java2
-rw-r--r--services/java/com/android/server/am/TaskRecord.java4
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java17
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java99
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java345
-rw-r--r--services/java/com/android/server/pm/PackageVerificationResponse.java28
-rw-r--r--services/java/com/android/server/pm/PackageVerificationState.java149
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java2
-rw-r--r--services/java/com/android/server/wm/DragState.java19
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java468
-rw-r--r--services/java/com/android/server/wm/WindowState.java36
24 files changed, 1219 insertions, 469 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 5ffcdc5..b8c44d9 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -477,7 +477,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
: bs.filterStats.entrySet()) {
pw.print(" "); pw.print(fe.getValue().count);
pw.print(" alarms: ");
- pw.println(fe.getKey().getIntent().toShortString(true, false));
+ pw.println(fe.getKey().getIntent().toShortString(false, true, false));
}
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 2938c45..6ac6c98 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -34,6 +34,7 @@ import android.app.backup.IRestoreSession;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -4765,6 +4766,11 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
+ boolean deviceIsProvisioned() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ return (Settings.Secure.getInt(resolver, Settings.Secure.DEVICE_PROVISIONED, 0) != 0);
+ }
+
// Run a *full* backup pass for the given package, writing the resulting data stream
// to the supplied file descriptor. This method is synchronous and does not return
// to the caller until the backup has been completed.
@@ -4785,12 +4791,19 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- if (DEBUG) Slog.v(TAG, "Requesting full backup: apks=" + includeApks
- + " shared=" + includeShared + " all=" + doAllApps
- + " pkgs=" + pkgList);
-
long oldId = Binder.clearCallingIdentity();
try {
+ // Doesn't make sense to do a full backup prior to setup
+ if (!deviceIsProvisioned()) {
+ Slog.i(TAG, "Full backup not supported before setup");
+ return;
+ }
+
+ if (DEBUG) Slog.v(TAG, "Requesting full backup: apks=" + includeApks
+ + " shared=" + includeShared + " all=" + doAllApps
+ + " pkgs=" + pkgList);
+ Slog.i(TAG, "Beginning full backup...");
+
FullBackupParams params = new FullBackupParams(fd, includeApks, includeShared,
doAllApps, pkgList);
final int token = generateToken();
@@ -4822,17 +4835,25 @@ class BackupManagerService extends IBackupManager.Stub {
// just eat it
}
Binder.restoreCallingIdentity(oldId);
+ Slog.d(TAG, "Full backup processing complete.");
}
- if (MORE_DEBUG) Slog.d(TAG, "Full backup done; returning to caller");
}
public void fullRestore(ParcelFileDescriptor fd) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullRestore");
- Slog.i(TAG, "Beginning full restore...");
long oldId = Binder.clearCallingIdentity();
try {
+ // Check whether the device has been provisioned -- we don't handle
+ // full restores prior to completing the setup process.
+ if (!deviceIsProvisioned()) {
+ Slog.i(TAG, "Full restore not permitted before setup");
+ return;
+ }
+
+ Slog.i(TAG, "Beginning full restore...");
+
FullRestoreParams params = new FullRestoreParams(fd);
final int token = generateToken();
synchronized (mFullConfirmations) {
@@ -4863,7 +4884,7 @@ class BackupManagerService extends IBackupManager.Stub {
Slog.w(TAG, "Error trying to close fd after full restore: " + e);
}
Binder.restoreCallingIdentity(oldId);
- Slog.i(TAG, "Full restore completed");
+ Slog.i(TAG, "Full restore processing complete.");
}
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 0153613..991b7da 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -35,6 +35,7 @@ import android.net.EthernetDataTracker;
import android.net.IConnectivityManager;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
+import android.net.INetworkStatsService;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
@@ -306,8 +307,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// the set of network types that can only be enabled by system/sig apps
List mProtectedNetworks;
- public ConnectivityService(
- Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
+ public ConnectivityService(Context context, INetworkManagementService netd,
+ INetworkStatsService statsService, INetworkPolicyManager policyManager) {
if (DBG) log("ConnectivityService starting up");
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
@@ -319,7 +320,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
String id = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);
if (id != null && id.length() > 0) {
- String name = new String("android_").concat(id);
+ String name = new String("android-").concat(id);
SystemProperties.set("net.hostname", name);
}
}
@@ -496,7 +497,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
- mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
+ mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
mTethering.getTetherableWifiRegexs().length != 0 ||
mTethering.getTetherableBluetoothRegexs().length != 0) &&
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index bb21d81..78dbbd6 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -79,6 +79,8 @@ public class PowerManagerService extends IPowerManager.Stub
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
+ static final boolean DEBUG_SCREEN_ON = false;
+
private static final boolean LOG_PARTIAL_WL = false;
// Indicates whether touch-down cycles should be logged as part of the
@@ -161,7 +163,9 @@ public class PowerManagerService extends IPowerManager.Stub
private int mStayOnConditions = 0;
private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
private final int[] mBroadcastWhy = new int[3];
- private boolean mBroadcastingScreenOff = false;
+ private boolean mPreparingForScreenOn = false;
+ private boolean mSkippedScreenOn = false;
+ private boolean mInitialized = false;
private int mPartialCount = 0;
private int mPowerState;
// mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
@@ -557,6 +561,10 @@ public class PowerManagerService extends IPowerManager.Stub
nativeInit();
synchronized (mLocks) {
updateNativePowerStateLocked();
+ // We make sure to start out with the screen on due to user activity.
+ // (They did just boot their device, after all.)
+ forceUserActivityLocked();
+ mInitialized = true;
}
}
@@ -1122,7 +1130,9 @@ public class PowerManagerService extends IPowerManager.Stub
pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
+ " " + ((mNextTimeout-now)/1000) + "s from now");
pw.println(" mDimScreen=" + mDimScreen
- + " mStayOnConditions=" + mStayOnConditions);
+ + " mStayOnConditions=" + mStayOnConditions
+ + " mPreparingForScreenOn=" + mPreparingForScreenOn
+ + " mSkippedScreenOn=" + mSkippedScreenOn);
pw.println(" mScreenOffReason=" + mScreenOffReason
+ " mUserState=" + mUserState);
pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
@@ -1311,8 +1321,23 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
- private void sendNotificationLocked(boolean on, int why)
- {
+ private void sendNotificationLocked(boolean on, int why) {
+ if (!mInitialized) {
+ // No notifications sent until first initialization is done.
+ // This is so that when we are moving from our initial state
+ // which looks like the screen was off to it being on, we do not
+ // go through the process of waiting for the higher-level user
+ // space to be ready before turning up the display brightness.
+ // (And also do not send needless broadcasts about the screen.)
+ return;
+ }
+
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.i(TAG, "sendNotificationLocked: " + on, here);
+ }
+
if (!on) {
mStillNeedSleepNotification = false;
}
@@ -1341,7 +1366,9 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastQueue[0] = on ? 1 : 0;
mBroadcastQueue[1] = -1;
mBroadcastQueue[2] = -1;
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
mBroadcastWakeLock.release();
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
mBroadcastWakeLock.release();
index = 0;
}
@@ -1357,7 +1384,9 @@ public class PowerManagerService extends IPowerManager.Stub
// The broadcast queue has changed; make sure the screen is on if it
// is now possible for it to be.
- updateNativePowerStateLocked();
+ if (mSkippedScreenOn) {
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
+ }
// Now send the message.
if (index >= 0) {
@@ -1371,6 +1400,21 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
+ private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+ new WindowManagerPolicy.ScreenOnListener() {
+ @Override public void onScreenOn() {
+ synchronized (mLocks) {
+ if (mPreparingForScreenOn) {
+ mPreparingForScreenOn = false;
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
+ 4, mBroadcastWakeLock.mCount);
+ mBroadcastWakeLock.release();
+ }
+ }
+ }
+ };
+
private Runnable mNotificationTask = new Runnable()
{
public void run()
@@ -1387,14 +1431,17 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastWhy[i] = mBroadcastWhy[i+1];
}
policy = getPolicyLocked();
- if (value == 0) {
- mBroadcastingScreenOff = true;
+ if (value == 1 && !mPreparingForScreenOn) {
+ mPreparingForScreenOn = true;
+ mBroadcastWakeLock.acquire();
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND,
+ mBroadcastWakeLock.mCount);
}
}
if (value == 1) {
mScreenOnStart = SystemClock.uptimeMillis();
- policy.screenTurnedOn();
+ policy.screenTurningOn(mScreenOnListener);
try {
ActivityManagerNative.getDefault().wakingUp();
} catch (RemoteException e) {
@@ -1432,8 +1479,7 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
mBroadcastWakeLock.mCount);
- mBroadcastingScreenOff = false;
- updateNativePowerStateLocked();
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
mBroadcastWakeLock.release();
}
}
@@ -1464,10 +1510,6 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
- synchronized (mLocks) {
- mBroadcastingScreenOff = false;
- updateNativePowerStateLocked();
- }
mBroadcastWakeLock.release();
}
}
@@ -1630,6 +1672,11 @@ public class PowerManagerService extends IPowerManager.Stub
};
private int setScreenStateLocked(boolean on) {
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Set screen state: " + on, e);
+ }
int err = Power.setScreenState(on);
if (err == 0) {
mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
@@ -1680,7 +1727,7 @@ public class PowerManagerService extends IPowerManager.Stub
} else {
newState &= ~BATTERY_LOW_BIT;
}
- if (newState == mPowerState) {
+ if (newState == mPowerState && mInitialized) {
return;
}
@@ -1706,10 +1753,7 @@ public class PowerManagerService extends IPowerManager.Stub
+ " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
}
- if (mPowerState != newState) {
- updateLightsLocked(newState, 0);
- mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
- }
+ final boolean stateChanged = mPowerState != newState;
if (oldScreenOn != newScreenOn) {
if (newScreenOn) {
@@ -1761,10 +1805,24 @@ public class PowerManagerService extends IPowerManager.Stub
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
mTotalTouchDownTime, mTouchCycles);
if (err == 0) {
- mPowerState |= SCREEN_ON_BIT;
sendNotificationLocked(true, -1);
+ // Update the lights *after* taking care of turning the
+ // screen on, so we do this after our notifications are
+ // enqueued and thus will delay turning on the screen light
+ // until the windows are correctly displayed.
+ if (stateChanged) {
+ updateLightsLocked(newState, 0);
+ }
+ mPowerState |= SCREEN_ON_BIT;
}
+
} else {
+ // Update the lights *before* taking care of turning the
+ // screen off, so we can initiate any animations that are desired.
+ if (stateChanged) {
+ updateLightsLocked(newState, 0);
+ }
+
// cancel light sensor task
mHandler.removeCallbacks(mAutoBrightnessTask);
mLightSensorPendingDecrease = false;
@@ -1787,29 +1845,18 @@ public class PowerManagerService extends IPowerManager.Stub
mLastTouchDown = 0;
}
}
+ } else if (stateChanged) {
+ // Screen on/off didn't change, but lights may have.
+ updateLightsLocked(newState, 0);
}
-
+
+ mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
+
updateNativePowerStateLocked();
}
}
-
+
private void updateNativePowerStateLocked() {
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- // Don't turn screen on if we are currently reporting a screen off.
- // This is to avoid letting the screen go on before things like the
- // lock screen have been displayed due to it going off.
- if (mBroadcastingScreenOff) {
- // Currently broadcasting that the screen is off. Don't
- // allow screen to go on until that is done.
- return;
- }
- for (int i=0; i<mBroadcastQueue.length; i++) {
- if (mBroadcastQueue[i] == 0) {
- // A screen off is currently enqueued.
- return;
- }
- }
- }
nativeSetPowerState(
(mPowerState & SCREEN_ON_BIT) != 0,
(mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
@@ -1835,8 +1882,43 @@ public class PowerManagerService extends IPowerManager.Stub
mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
}
+ private boolean shouldDeferScreenOnLocked() {
+ if (mPreparingForScreenOn) {
+ // Currently waiting for confirmation from the policy that it
+ // is okay to turn on the screen. Don't allow the screen to go
+ // on until that is done.
+ if (DEBUG_SCREEN_ON) Slog.i(TAG,
+ "updateLights: delaying screen on due to mPreparingForScreenOn");
+ return true;
+ } else {
+ // If there is a screen-on command in the notification queue, we
+ // can't turn the screen on until it has been processed (and we
+ // have set mPreparingForScreenOn) or it has been dropped.
+ for (int i=0; i<mBroadcastQueue.length; i++) {
+ if (mBroadcastQueue[i] == 1) {
+ if (DEBUG_SCREEN_ON) Slog.i(TAG,
+ "updateLights: delaying screen on due to notification queue");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private void updateLightsLocked(int newState, int forceState) {
final int oldState = mPowerState;
+
+ // If the screen is not currently on, we will want to delay actually
+ // turning the lights on if we are still getting the UI put up.
+ if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
+ // Don't turn screen on until we know we are really ready to.
+ // This is to avoid letting the screen go on before things like the
+ // lock screen have been displayed.
+ if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) {
+ newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
+ }
+ }
+
if ((newState & SCREEN_ON_BIT) != 0) {
// Only turn on the buttons or keyboard if the screen is also on.
// We should never see the buttons on but not the screen.
@@ -1943,6 +2025,13 @@ public class PowerManagerService extends IPowerManager.Stub
}
mScreenBrightness.setTargetLocked(brightness, steps,
INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+ mScreenBrightness.setTargetLocked(brightness, steps,
+ INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ }
}
if (mSpew) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cdefa00..5006de7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -370,7 +370,8 @@ class ServerThread extends Thread {
try {
Slog.i(TAG, "Connectivity Service");
- connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
+ connectivity = new ConnectivityService(
+ context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 6ceccaf..253e741 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -120,7 +120,8 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
notifyCallbacksLocked();
if (mWallpaperComponent == null || mImageWallpaperPending) {
mImageWallpaperPending = false;
- bindWallpaperComponentLocked(mImageWallpaperComponent, true);
+ bindWallpaperComponentLocked(mImageWallpaperComponent,
+ true, false);
saveSettingsLocked();
}
}
@@ -201,7 +202,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
if (!mWallpaperUpdating && (mLastDiedTime+MIN_WALLPAPER_CRASH_TIME)
> SystemClock.uptimeMillis()) {
Slog.w(TAG, "Reverting to built-in wallpaper!");
- bindWallpaperComponentLocked(null, true);
+ clearWallpaperLocked(true);
}
}
}
@@ -230,9 +231,23 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
mWallpaperUpdating = false;
ComponentName comp = mWallpaperComponent;
clearWallpaperComponentLocked();
- bindWallpaperComponentLocked(comp, false);
+ if (!bindWallpaperComponentLocked(comp, false, false)) {
+ Slog.w(TAG, "Wallpaper no longer available; reverting to default");
+ clearWallpaperLocked(false);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ synchronized (mLock) {
+ if (mWallpaperComponent == null ||
+ !mWallpaperComponent.getPackageName().equals(packageName)) {
+ return;
}
}
+ doPackagesChanged(true);
}
@Override
@@ -265,7 +280,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
changed = true;
if (doit) {
Slog.w(TAG, "Wallpaper uninstalled, removing: " + mWallpaperComponent);
- clearWallpaperLocked();
+ clearWallpaperLocked(false);
}
}
}
@@ -283,7 +298,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
mWallpaperComponent, 0);
} catch (NameNotFoundException e) {
Slog.w(TAG, "Wallpaper component gone, removing: " + mWallpaperComponent);
- clearWallpaperLocked();
+ clearWallpaperLocked(false);
}
}
if (mNextWallpaperComponent != null
@@ -321,45 +336,51 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
public void systemReady() {
if (DEBUG) Slog.v(TAG, "systemReady");
synchronized (mLock) {
+ RuntimeException e = null;
try {
- bindWallpaperComponentLocked(mNextWallpaperComponent, false);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure starting previous wallpaper", e);
- try {
- bindWallpaperComponentLocked(null, false);
- } catch (RuntimeException e2) {
- Slog.w(TAG, "Failure starting default wallpaper", e2);
- clearWallpaperComponentLocked();
+ if (bindWallpaperComponentLocked(mNextWallpaperComponent, false, false)) {
+ return;
}
+ } catch (RuntimeException e1) {
+ e = e1;
}
+ Slog.w(TAG, "Failure starting previous wallpaper", e);
+ clearWallpaperLocked(false);
}
}
public void clearWallpaper() {
if (DEBUG) Slog.v(TAG, "clearWallpaper");
synchronized (mLock) {
- clearWallpaperLocked();
+ clearWallpaperLocked(false);
}
}
- public void clearWallpaperLocked() {
+ public void clearWallpaperLocked(boolean defaultFailed) {
File f = WALLPAPER_FILE;
if (f.exists()) {
f.delete();
}
final long ident = Binder.clearCallingIdentity();
+ RuntimeException e = null;
try {
mImageWallpaperPending = false;
- bindWallpaperComponentLocked(null, false);
- } catch (IllegalArgumentException e) {
- // This can happen if the default wallpaper component doesn't
- // exist. This should be a system configuration problem, but
- // let's not let it crash the system and just live with no
- // wallpaper.
- Slog.e(TAG, "Default wallpaper component not found!", e);
+ if (bindWallpaperComponentLocked(defaultFailed
+ ? mImageWallpaperComponent : null, true, false)) {
+ return;
+ }
+ } catch (IllegalArgumentException e1) {
+ e = e1;
} finally {
Binder.restoreCallingIdentity(ident);
}
+
+ // This can happen if the default wallpaper component doesn't
+ // exist. This should be a system configuration problem, but
+ // let's not let it crash the system and just live with no
+ // wallpaper.
+ Slog.e(TAG, "Default wallpaper component not found!", e);
+ clearWallpaperComponentLocked();
}
public void setDimensionHints(int width, int height) throws RemoteException {
@@ -469,14 +490,14 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
final long ident = Binder.clearCallingIdentity();
try {
mImageWallpaperPending = false;
- bindWallpaperComponentLocked(name, false);
+ bindWallpaperComponentLocked(name, false, true);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
- void bindWallpaperComponentLocked(ComponentName componentName, boolean force) {
+ boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force, boolean fromUser) {
if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
// Has the component changed?
@@ -486,12 +507,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
if (componentName == null) {
if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
// Still using default wallpaper.
- return;
+ return true;
}
} else if (mWallpaperComponent.equals(componentName)) {
// Changing to same wallpaper.
if (DEBUG) Slog.v(TAG, "same wallpaper");
- return;
+ return true;
}
}
}
@@ -516,9 +537,14 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
ServiceInfo si = mContext.getPackageManager().getServiceInfo(componentName,
PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
- throw new SecurityException("Selected service does not require "
+ String msg = "Selected service does not require "
+ android.Manifest.permission.BIND_WALLPAPER
- + ": " + componentName);
+ + ": " + componentName;
+ if (fromUser) {
+ throw new SecurityException(msg);
+ }
+ Slog.w(TAG, msg);
+ return false;
}
WallpaperInfo wi = null;
@@ -535,16 +561,29 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
try {
wi = new WallpaperInfo(mContext, ris.get(i));
} catch (XmlPullParserException e) {
- throw new IllegalArgumentException(e);
+ if (fromUser) {
+ throw new IllegalArgumentException(e);
+ }
+ Slog.w(TAG, e);
+ return false;
} catch (IOException e) {
- throw new IllegalArgumentException(e);
+ if (fromUser) {
+ throw new IllegalArgumentException(e);
+ }
+ Slog.w(TAG, e);
+ return false;
}
break;
}
}
if (wi == null) {
- throw new SecurityException("Selected service is not a wallpaper: "
- + componentName);
+ String msg = "Selected service is not a wallpaper: "
+ + componentName;
+ if (fromUser) {
+ throw new SecurityException(msg);
+ }
+ Slog.w(TAG, msg);
+ return false;
}
}
@@ -561,8 +600,13 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
0));
if (!mContext.bindService(intent, newConn,
Context.BIND_AUTO_CREATE)) {
- throw new IllegalArgumentException("Unable to bind service: "
- + componentName);
+ String msg = "Unable to bind service: "
+ + componentName;
+ if (fromUser) {
+ throw new IllegalArgumentException(msg);
+ }
+ Slog.w(TAG, msg);
+ return false;
}
clearWallpaperComponentLocked();
@@ -577,8 +621,14 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
}
} catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("Unknown component " + componentName);
+ String msg = "Unknown component " + componentName;
+ if (fromUser) {
+ throw new IllegalArgumentException(msg);
+ }
+ Slog.w(TAG, msg);
+ return false;
}
+ return true;
}
void clearWallpaperComponentLocked() {
@@ -611,7 +661,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
} catch (RemoteException e) {
Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
if (!mWallpaperUpdating) {
- bindWallpaperComponentLocked(null, false);
+ bindWallpaperComponentLocked(null, false, false);
}
}
}
@@ -765,13 +815,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
loadSettingsLocked();
if (mNextWallpaperComponent != null &&
!mNextWallpaperComponent.equals(mImageWallpaperComponent)) {
- try {
- bindWallpaperComponentLocked(mNextWallpaperComponent, false);
- } catch (IllegalArgumentException e) {
+ if (!bindWallpaperComponentLocked(mNextWallpaperComponent, false, false)) {
// No such live wallpaper or other failure; fall back to the default
// live wallpaper (since the profile being restored indicated that the
// user had selected a live rather than static one).
- bindWallpaperComponentLocked(null, false);
+ bindWallpaperComponentLocked(null, false, false);
}
success = true;
} else {
@@ -786,7 +834,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
}
if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
if (success) {
- bindWallpaperComponentLocked(null, false);
+ bindWallpaperComponentLocked(null, false, false);
}
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6830055..ed8fa40 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -718,8 +718,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*/
private void manageServicesLocked() {
populateEnabledServicesLocked(mEnabledServices);
- updateServicesStateLocked(mInstalledServices, mEnabledServices);
- disableAccessibilityIfNoEnabledServices(mEnabledServices);
+ final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices,
+ mEnabledServices);
+ // No enabled installed services => disable accessibility to avoid
+ // sending accessibility events with no recipient across processes.
+ if (mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+ }
}
/**
@@ -771,13 +777,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*
* @param installedServices All installed {@link AccessibilityService}s.
* @param enabledServices The {@link ComponentName}s of the enabled services.
+ * @return The number of enabled installed services.
*/
- private void updateServicesStateLocked(List<AccessibilityServiceInfo> installedServices,
+ private int updateServicesStateLocked(List<AccessibilityServiceInfo> installedServices,
Set<ComponentName> enabledServices) {
Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
boolean isEnabled = mIsAccessibilityEnabled;
+ int enabledInstalledServices = 0;
for (int i = 0, count = installedServices.size(); i < count; i++) {
AccessibilityServiceInfo installedService = installedServices.get(i);
ComponentName componentName = ComponentName.unflattenFromString(
@@ -790,6 +798,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
service = new Service(componentName, installedService, false);
}
service.bind();
+ enabledInstalledServices++;
} else {
if (service != null) {
service.unbind();
@@ -801,19 +810,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
}
- }
- /**
- * Disables accessibility if there are no enabled accessibility services which
- * to consume the generated accessibility events.
- *
- * @param enabledServices The set of enabled services.
- */
- private void disableAccessibilityIfNoEnabledServices(Set<ComponentName> enabledServices) {
- if (enabledServices.isEmpty()) {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0);
- }
+ return enabledInstalledServices;
}
/**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 41af137..2942c28 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1631,8 +1631,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (app.conProviders.size() > 0) {
for (ContentProviderRecord cpr : app.conProviders.keySet()) {
- if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
- updateLruProcessInternalLocked(cpr.app, oomAdj,
+ if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
+ updateLruProcessInternalLocked(cpr.proc, oomAdj,
updateActivityTime, i+1);
}
}
@@ -3334,6 +3334,11 @@ public final class ActivityManagerService extends ActivityManagerNative
if ((samePackage || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
+ if (r.finishing) {
+ // If this activity is just finishing, then it is not
+ // interesting as far as something to stop.
+ continue;
+ }
return true;
}
didSomething = true;
@@ -3373,7 +3378,24 @@ public final class ActivityManagerService extends ActivityManagerNative
for (i=0; i<N; i++) {
bringDownServiceLocked(services.get(i), true);
}
-
+
+ ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
+ for (ContentProviderRecord provider : mProvidersByClass.values()) {
+ if (provider.info.packageName.equals(name)
+ && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+ if (!doit) {
+ return true;
+ }
+ didSomething = true;
+ providers.add(provider);
+ }
+ }
+
+ N = providers.size();
+ for (i=0; i<N; i++) {
+ removeDyingProviderLocked(null, providers.get(i));
+ }
+
if (doit) {
if (purgeCache) {
AttributeCache ac = AttributeCache.instance();
@@ -3382,6 +3404,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
mMainStack.resumeTopActivityLocked(null);
+ mMainStack.scheduleIdleLocked();
}
return didSomething;
@@ -3761,6 +3784,12 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.showBootMessage(msg, always);
}
+ public void dismissKeyguardOnNextActivity() {
+ synchronized (this) {
+ mMainStack.dismissKeyguardOnNextActivityLocked();
+ }
+ }
+
final void finishBooting() {
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
@@ -5485,7 +5514,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
ContentProviderRecord cpr = mProvidersByClass.get(comp);
if (cpr == null) {
- cpr = new ContentProviderRecord(cpi, app.info);
+ cpr = new ContentProviderRecord(cpi, app.info, comp);
mProvidersByClass.put(comp, cpr);
}
app.pubProviders.put(cpi.name, cpr);
@@ -5643,25 +5672,25 @@ public final class ActivityManagerService extends ActivityManagerNative
// return it right away.
final boolean countChanged = incProviderCount(r, cpr);
if (countChanged) {
- if (cpr.app != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
// If this is a perceptible app accessing the provider,
// make sure to count it as being accessed and thus
// back up on the LRU list. This is good because
// content providers are often expensive to start.
- updateLruProcessLocked(cpr.app, false, true);
+ updateLruProcessLocked(cpr.proc, false, true);
}
}
- if (cpr.app != null) {
+ if (cpr.proc != null) {
if (false) {
if (cpr.name.flattenToShortString().equals(
"com.android.providers.calendar/.CalendarProvider2")) {
Slog.v(TAG, "****************** KILLING "
+ cpr.name.flattenToShortString());
- Process.killProcess(cpr.app.pid);
+ Process.killProcess(cpr.proc.pid);
}
}
- boolean success = updateOomAdjLocked(cpr.app);
+ boolean success = updateOomAdjLocked(cpr.proc);
if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
// NOTE: there is still a race here where a signal could be
// pending on the process even though we managed to update its
@@ -5676,7 +5705,7 @@ public final class ActivityManagerService extends ActivityManagerNative
"Existing provider " + cpr.name.flattenToShortString()
+ " is crashing; detaching " + r);
boolean lastRef = decProviderCount(r, cpr);
- appDiedLocked(cpr.app, cpr.app.pid, cpr.app.thread);
+ appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
if (!lastRef) {
// This wasn't the last ref our process had on
// the provider... we have now been killed, bail.
@@ -5729,7 +5758,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ cpi.name);
return null;
}
- cpr = new ContentProviderRecord(cpi, ai);
+ cpr = new ContentProviderRecord(cpi, ai, comp);
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
@@ -5864,7 +5893,7 @@ public final class ActivityManagerService extends ActivityManagerNative
//update content provider record entry info
ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
ContentProviderRecord localCpr = mProvidersByClass.get(comp);
- if (localCpr.app == r) {
+ if (localCpr.proc == r) {
//should not happen. taken care of as a local provider
Slog.w(TAG, "removeContentProvider called on local provider: "
+ cpr.info.name + " in process " + r.processName);
@@ -5940,7 +5969,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
synchronized (dst) {
dst.provider = src.provider;
- dst.app = r;
+ dst.proc = r;
dst.notifyAll();
}
updateOomAdjLocked(r);
@@ -7884,6 +7913,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dumpAll) {
pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
+ pw.println(" mDismissKeyguardOnNextActivity: "
+ + mMainStack.mDismissKeyguardOnNextActivity);
}
if (mRecentTasks.size() > 0) {
@@ -8524,7 +8555,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<N; i++) {
sb.setLength(0);
sb.append(" Intent: ");
- intents.get(i).toShortString(sb, true, false);
+ intents.get(i).toShortString(sb, false, true, false);
pw.println(sb.toString());
Bundle bundle = intents.get(i).getExtras();
if (bundle != null) {
@@ -8706,9 +8737,9 @@ public final class ActivityManagerService extends ActivityManagerNative
r.dump(pw, " ");
} else {
pw.print(" * "); pw.print(e.getKey().flattenToShortString());
- if (r.app != null) {
+ if (r.proc != null) {
pw.println(":");
- pw.print(" "); pw.println(r.app);
+ pw.print(" "); pw.println(r.proc);
} else {
pw.println();
}
@@ -8817,7 +8848,8 @@ public final class ActivityManagerService extends ActivityManagerNative
} else if (complete) {
// Complete + brief == give a summary. Isn't that obvious?!?
if (lastTask.intent != null) {
- pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
+ pw.print(prefix); pw.print(" ");
+ pw.println(lastTask.intent.toInsecureString());
}
}
}
@@ -8828,7 +8860,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.dump(pw, innerPrefix);
} else if (complete) {
// Complete + brief == give a summary. Isn't that obvious?!?
- pw.print(innerPrefix); pw.println(r.intent);
+ pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
if (r.app != null) {
pw.print(innerPrefix); pw.println(r.app);
}
@@ -9440,7 +9472,7 @@ public final class ActivityManagerService extends ActivityManagerNative
cpr.notifyAll();
}
- mProvidersByClass.remove(cpr.info.name);
+ mProvidersByClass.remove(cpr.name);
String names[] = cpr.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
mProvidersByName.remove(names[j]);
@@ -9454,9 +9486,10 @@ public final class ActivityManagerService extends ActivityManagerNative
&& capp.pid != MY_PID) {
Slog.i(TAG, "Kill " + capp.processName
+ " (pid " + capp.pid + "): provider " + cpr.info.name
- + " in dying process " + proc.processName);
+ + " in dying process " + (proc != null ? proc.processName : "??"));
EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
- capp.processName, capp.setAdj, "dying provider " + proc.processName);
+ capp.processName, capp.setAdj, "dying provider "
+ + cpr.name.toShortString());
Process.killProcessQuiet(capp.pid);
}
}
@@ -9515,7 +9548,7 @@ public final class ActivityManagerService extends ActivityManagerNative
while (it.hasNext()) {
ContentProviderRecord cpr = it.next();
cpr.provider = null;
- cpr.app = null;
+ cpr.proc = null;
// See if someone is waiting for this provider... in which
// case we don't remove it, but just let it restart.
@@ -10029,7 +10062,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean created = false;
try {
mStringBuilder.setLength(0);
- r.intent.getIntent().toShortString(mStringBuilder, false, true);
+ r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
System.identityHashCode(r), r.shortName,
mStringBuilder.toString(), r.app.pid);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 73ffafb..ce45bfb 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -122,7 +122,7 @@ final class ActivityRecord extends IApplicationToken.Stub {
pw.print(" processName="); pw.println(processName);
pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
pw.print(" app="); pw.println(app);
- pw.print(prefix); pw.println(intent);
+ pw.print(prefix); pw.println(intent.toInsecureString());
pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
pw.print(" task="); pw.println(task);
pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a0aedf9..7bc19ab 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -259,6 +259,11 @@ final class ActivityStack {
*/
boolean mSleepTimeout = false;
+ /**
+ * Dismiss the keyguard after the next activity is displayed?
+ */
+ boolean mDismissKeyguardOnNextActivity = false;
+
int mThumbnailWidth = -1;
int mThumbnailHeight = -1;
@@ -765,9 +770,7 @@ final class ActivityStack {
// Still need to tell some activities to stop; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
+ mStoppingActivities.size() + " activities");
- Message msg = Message.obtain();
- msg.what = IDLE_NOW_MSG;
- mHandler.sendMessage(msg);
+ scheduleIdleLocked();
return;
}
@@ -978,9 +981,7 @@ final class ActivityStack {
// then give up on things going idle and start clearing
// them out.
if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
- Message msg = Message.obtain();
- msg.what = IDLE_NOW_MSG;
- mHandler.sendMessage(msg);
+ scheduleIdleLocked();
} else {
checkReadyForSleepLocked();
}
@@ -2173,7 +2174,7 @@ final class ActivityStack {
}
if (err == START_SUCCESS) {
- Slog.i(TAG, "Starting: " + intent + " from pid "
+ Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid "
+ (callerApp != null ? callerApp.pid : callingPid));
}
@@ -2228,6 +2229,7 @@ final class ActivityStack {
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
+ mDismissKeyguardOnNextActivity = false;
return err;
}
@@ -2239,6 +2241,7 @@ final class ActivityStack {
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
+ mDismissKeyguardOnNextActivity = false;
String msg;
if (!aInfo.exported) {
msg = "Permission Denial: starting " + intent.toString()
@@ -2276,6 +2279,7 @@ final class ActivityStack {
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
+ mDismissKeyguardOnNextActivity = false;
return START_SUCCESS;
}
}
@@ -2299,6 +2303,7 @@ final class ActivityStack {
pal.grantedMode = grantedMode;
pal.onlyIfNeeded = onlyIfNeeded;
mService.mPendingActivityLaunches.add(pal);
+ mDismissKeyguardOnNextActivity = false;
return START_SWITCHES_CANCELED;
}
}
@@ -2317,8 +2322,17 @@ final class ActivityStack {
mService.doPendingActivityLaunchesLocked(false);
}
- return startActivityUncheckedLocked(r, sourceRecord,
+ err = startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
+ if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
+ // Someone asked to have the keyguard dismissed on the next
+ // activity start, but we are not actually doing an activity
+ // switch... just dismiss the keyguard now, because we
+ // probably want to see whatever is behind it.
+ mDismissKeyguardOnNextActivity = false;
+ mService.mWindowManager.dismissKeyguard();
+ }
+ return err;
}
final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
@@ -2987,6 +3001,11 @@ final class ActivityStack {
w.thisTime = w.totalTime;
}
mService.notifyAll();
+
+ if (mDismissKeyguardOnNextActivity) {
+ mDismissKeyguardOnNextActivity = false;
+ mService.mWindowManager.dismissKeyguard();
+ }
}
void sendActivityResultLocked(int callingUid, ActivityRecord r,
@@ -3103,6 +3122,12 @@ final class ActivityStack {
return stops;
}
+ final void scheduleIdleLocked() {
+ Message msg = Message.obtain();
+ msg.what = IDLE_NOW_MSG;
+ mHandler.sendMessage(msg);
+ }
+
final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
Configuration config) {
if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
@@ -3413,9 +3438,7 @@ final class ActivityStack {
// If we already have a few activities waiting to stop,
// then give up on things going idle and start clearing
// them out.
- Message msg = Message.obtain();
- msg.what = IDLE_NOW_MSG;
- mHandler.sendMessage(msg);
+ scheduleIdleLocked();
} else {
checkReadyForSleepLocked();
}
@@ -4126,4 +4149,8 @@ final class ActivityStack {
return true;
}
+
+ public void dismissKeyguardOnNextActivityLocked() {
+ mDismissKeyguardOnNextActivity = true;
+ }
}
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index db235ee..9c55597 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -32,15 +32,15 @@ class ContentProviderRecord extends ContentProviderHolder {
final ApplicationInfo appInfo;
final ComponentName name;
int externals; // number of non-framework processes supported by this provider
- ProcessRecord app; // if non-null, hosting application
+ ProcessRecord proc; // if non-null, hosting process.
ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
String stringName;
- public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
+ public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai, ComponentName _name) {
super(_info);
uid = ai.uid;
appInfo = ai;
- name = new ComponentName(_info.packageName, _info.name);
+ name = _name;
noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
}
@@ -61,7 +61,7 @@ class ContentProviderRecord extends ContentProviderHolder {
pw.print(prefix); pw.print("package=");
pw.print(info.applicationInfo.packageName);
pw.print(" process="); pw.println(info.processName);
- pw.print(prefix); pw.print("app="); pw.println(app);
+ pw.print(prefix); pw.print("proc="); pw.println(proc);
if (launchingApp != null) {
pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp);
}
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index 3a5ca66..2618c77 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -54,7 +54,7 @@ class IntentBindRecord {
void dumpInService(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("intent={");
- pw.print(intent.getIntent().toShortString(true, false));
+ pw.print(intent.getIntent().toShortString(false, true, false));
pw.println('}');
pw.print(prefix); pw.print("binder="); pw.println(binder);
pw.print(prefix); pw.print("requested="); pw.print(requested);
@@ -89,7 +89,7 @@ class IntentBindRecord {
sb.append(service.shortName);
sb.append(':');
if (intent != null) {
- intent.getIntent().toShortString(sb, false, false);
+ intent.getIntent().toShortString(sb, false, false, false);
}
sb.append('}');
return stringName = sb.toString();
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 8ed0cc1..abd2a1f 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -150,7 +150,8 @@ class PendingIntentRecord extends IIntentSender.Stub {
public String toString() {
return "Key{" + typeName() + " pkg=" + packageName
+ " intent="
- + (requestIntent != null ? requestIntent.toShortString(true, false) : "<null>")
+ + (requestIntent != null
+ ? requestIntent.toShortString(false, true, false) : "<null>")
+ " flags=0x" + Integer.toHexString(flags) + "}";
}
@@ -317,7 +318,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
}
if (key.requestIntent != null) {
pw.print(prefix); pw.print("requestIntent=");
- pw.println(key.requestIntent.toShortString(true, true));
+ pw.println(key.requestIntent.toShortString(false, true, true));
}
if (sent || canceled) {
pw.print(prefix); pw.print("sent="); pw.print(sent);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 004e963..257113b 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -192,7 +192,7 @@ class ServiceRecord extends Binder {
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("intent={");
- pw.print(intent.getIntent().toShortString(true, false));
+ pw.print(intent.getIntent().toShortString(false, true, false));
pw.println('}');
pw.print(prefix); pw.print("packageName="); pw.println(packageName);
pw.print(prefix); pw.print("processName="); pw.println(processName);
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 87129ea..a860763 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -94,14 +94,14 @@ class TaskRecord extends ThumbnailHolder {
if (intent != null) {
StringBuilder sb = new StringBuilder(128);
sb.append(prefix); sb.append("intent={");
- intent.toShortString(sb, true, false);
+ intent.toShortString(sb, false, true, false);
sb.append('}');
pw.println(sb.toString());
}
if (affinityIntent != null) {
StringBuilder sb = new StringBuilder(128);
sb.append(prefix); sb.append("affinityIntent={");
- affinityIntent.toShortString(sb, true, false);
+ affinityIntent.toShortString(sb, false, true, false);
sb.append('}');
pw.println(sb.toString());
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 10f6d2c..6b9c088 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -29,6 +29,7 @@ import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
+import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -88,7 +89,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
// upstream type list and the DUN_REQUIRED secure-setting
private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
- private INetworkManagementService mNMService;
+ private final INetworkManagementService mNMService;
+ private final INetworkStatsService mStatsService;
private Looper mLooper;
private HandlerThread mThread;
@@ -124,9 +126,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private boolean mUsbTetherRequested; // true if USB tethering should be started
// when RNDIS is enabled
- public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
+ public Tethering(Context context, INetworkManagementService nmService,
+ INetworkStatsService statsService, Looper looper) {
mContext = context;
mNMService = nmService;
+ mStatsService = statsService;
mLooper = looper;
mIfaces = new HashMap<String, TetherInterfaceSM>();
@@ -913,6 +917,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
case CMD_INTERFACE_DOWN:
if (mMyUpstreamIfaceName != null) {
try {
+ // about to tear down NAT; gather remaining statistics
+ mStatsService.forceUpdate();
+
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {
@@ -957,6 +964,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
if (mMyUpstreamIfaceName != null) {
try {
+ // about to tear down NAT; gather remaining statistics
+ mStatsService.forceUpdate();
+
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {
@@ -995,6 +1005,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
case CMD_TETHER_MODE_DEAD:
if (mMyUpstreamIfaceName != null) {
try {
+ // about to tear down NAT; gather remaining statistics
+ mStatsService.forceUpdate();
+
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index bc65205..aa46795 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -24,8 +24,8 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -43,9 +43,12 @@ import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
+import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -80,6 +83,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
+import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Log;
@@ -121,7 +125,7 @@ import libcore.io.IoUtils;
*/
public class NetworkStatsService extends INetworkStatsService.Stub {
private static final String TAG = "NetworkStats";
- private static final boolean LOGD = true;
+ private static final boolean LOGD = false;
private static final boolean LOGV = false;
/** File header magic number: "ANET" */
@@ -132,7 +136,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final int VERSION_UID_WITH_TAG = 3;
private static final int VERSION_UID_WITH_SET = 4;
- private static final int MSG_PERFORM_POLL = 0x1;
+ private static final int MSG_PERFORM_POLL = 1;
+ private static final int MSG_UPDATE_IFACES = 2;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x10;
@@ -144,6 +149,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager;
private final TrustedTime mTime;
+ private final TelephonyManager mTeleManager;
private final NetworkStatsSettings mSettings;
private final PowerManager.WakeLock mWakeLock;
@@ -227,6 +233,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
mTime = checkNotNull(time, "missing TrustedTime");
+ mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
final PowerManager powerManager = (PowerManager) context.getSystemService(
@@ -279,6 +286,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// ignored; service lives in system_server
}
+ // watch for networkType changes that aren't broadcast through
+ // CONNECTIVITY_ACTION_IMMEDIATE above.
+ mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
+
registerPollAlarmLocked();
registerGlobalAlert();
@@ -288,10 +299,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void shutdownLocked() {
mContext.unregisterReceiver(mConnReceiver);
+ mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
+ mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+
writeNetworkStatsLocked();
if (mUidStatsLoaded) {
writeUidStatsLocked();
@@ -535,14 +549,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
// permission above.
- synchronized (mStatsLock) {
- mWakeLock.acquire();
- try {
- updateIfacesLocked();
- } finally {
- mWakeLock.release();
- }
- }
+ updateIfaces();
}
};
@@ -619,6 +626,46 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
};
+ private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
+ private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+
+ /**
+ * Receiver that watches for {@link TelephonyManager} changes, such as
+ * transitioning between network types.
+ */
+ private PhoneStateListener mPhoneListener = new PhoneStateListener() {
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ final boolean stateChanged = state != mLastPhoneState;
+ final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
+
+ if (networkTypeChanged && !stateChanged) {
+ // networkType changed without a state change, which means we
+ // need to roll our own update. delay long enough for
+ // ConnectivityManager to process.
+ // TODO: add direct event to ConnectivityService instead of
+ // relying on this delay.
+ if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
+ }
+
+ mLastPhoneState = state;
+ mLastPhoneNetworkType = networkType;
+ }
+ };
+
+ private void updateIfaces() {
+ synchronized (mStatsLock) {
+ mWakeLock.acquire();
+ try {
+ updateIfacesLocked();
+ } finally {
+ mWakeLock.release();
+ }
+ }
+ }
+
/**
* Inspect all current {@link NetworkState} to derive mapping from {@code
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
@@ -713,19 +760,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final long threshold = mSettings.getPersistThreshold();
try {
- // record network stats
- final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
- performNetworkPollLocked(networkSnapshot, currentTime);
-
- // persist when enough network data has occurred
- final NetworkStats persistNetworkDelta = computeStatsDelta(
- mLastPersistNetworkSnapshot, networkSnapshot, true);
- final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
- if (persistForce || (persistNetwork && networkPastThreshold)) {
- writeNetworkStatsLocked();
- mLastPersistNetworkSnapshot = networkSnapshot;
- }
-
// record tethering stats; persisted during normal UID cycle below
final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
@@ -744,6 +778,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
}
+
+ // record network stats
+ final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
+ performNetworkPollLocked(networkSnapshot, currentTime);
+
+ // persist when enough network data has occurred
+ final NetworkStats persistNetworkDelta = computeStatsDelta(
+ mLastPersistNetworkSnapshot, networkSnapshot, true);
+ final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
+ if (persistForce || (persistNetwork && networkPastThreshold)) {
+ writeNetworkStatsLocked();
+ mLastPersistNetworkSnapshot = networkSnapshot;
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
} catch (RemoteException e) {
@@ -1356,6 +1403,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
performPoll(flags);
return true;
}
+ case MSG_UPDATE_IFACES: {
+ updateIfaces();
+ return true;
+ }
default: {
return false;
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 105e603..eb135b7 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -72,6 +72,7 @@ import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.ManifestDigest;
import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VerifierInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -113,6 +114,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -158,6 +161,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_INTENT_MATCHING = false;
private static final boolean DEBUG_PACKAGE_SCANNING = false;
private static final boolean DEBUG_APP_DIR_OBSERVER = false;
+ private static final boolean DEBUG_VERIFY = false;
static final boolean MULTIPLE_APPLICATION_UIDS = true;
private static final int RADIO_UID = Process.PHONE_UID;
@@ -208,6 +212,8 @@ public class PackageManagerService extends IPackageManager.Stub {
DEFAULT_CONTAINER_PACKAGE,
"com.android.defcontainer.DefaultContainerService");
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
private static final String LIB_DIR_NAME = "lib";
static final String mTempContainerPrefix = "smdl2tmp";
@@ -349,7 +355,8 @@ public class PackageManagerService extends IPackageManager.Stub {
final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
/** List of packages waiting for verification. */
- final SparseArray<InstallArgs> mPendingVerification = new SparseArray<InstallArgs>();
+ final SparseArray<PackageVerificationState> mPendingVerification
+ = new SparseArray<PackageVerificationState>();
final ArrayList<PackageParser.Package> mDeferredDexOpt =
new ArrayList<PackageParser.Package>();
@@ -427,6 +434,8 @@ public class PackageManagerService extends IPackageManager.Stub {
final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
+ private final String mRequiredVerifierPackage;
+
class PackageHandler extends Handler {
private boolean mBound = false;
final ArrayList<HandlerParams> mPendingInstalls =
@@ -740,9 +749,10 @@ public class PackageManagerService extends IPackageManager.Stub {
} break;
case CHECK_PENDING_VERIFICATION: {
final int verificationId = msg.arg1;
- final InstallArgs args = mPendingVerification.get(verificationId);
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
- if (args != null) {
+ if (state != null) {
+ final InstallArgs args = state.getInstallArgs();
Slog.i(TAG, "Validation timed out for " + args.packageURI.toString());
mPendingVerification.remove(verificationId);
@@ -756,31 +766,38 @@ public class PackageManagerService extends IPackageManager.Stub {
}
case PACKAGE_VERIFIED: {
final int verificationId = msg.arg1;
- final boolean verified = msg.arg2 == 1 ? true : false;
- final InstallArgs args = mPendingVerification.get(verificationId);
- if (args == null) {
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+ if (state == null) {
Slog.w(TAG, "Invalid validation token " + verificationId + " received");
break;
}
- mPendingVerification.remove(verificationId);
+ final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
- int ret;
- if (verified) {
- ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- try {
- ret = args.copyApk(mContainerService, true);
- } catch (RemoteException e) {
- Slog.e(TAG, "Could not contact the ContainerService");
+ state.setVerifierResponse(response.callerUid, response.code);
+
+ if (state.isVerificationComplete()) {
+ mPendingVerification.remove(verificationId);
+
+ final InstallArgs args = state.getInstallArgs();
+
+ int ret;
+ if (state.isInstallAllowed()) {
+ ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ try {
+ ret = args.copyApk(mContainerService, true);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Could not contact the ContainerService");
+ }
+ } else {
+ ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
}
- } else {
- ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
- }
- processPendingInstall(args, ret);
+ processPendingInstall(args, ret);
- mHandler.sendEmptyMessage(MCS_UNBIND);
+ mHandler.sendEmptyMessage(MCS_UNBIND);
+ }
break;
}
@@ -945,7 +962,8 @@ public class PackageManagerService extends IPackageManager.Stub {
} catch (FileNotFoundException e) {
Slog.w(TAG, "Boot class path not found: " + paths[i]);
} catch (IOException e) {
- Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
+ Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
+ + e.getMessage());
}
}
} else {
@@ -968,7 +986,8 @@ public class PackageManagerService extends IPackageManager.Stub {
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
} catch (IOException e) {
- Slog.w(TAG, "Exception reading library: " + lib, e);
+ Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ + e.getMessage());
}
}
}
@@ -1132,10 +1151,49 @@ public class PackageManagerService extends IPackageManager.Stub {
// are all flushed. Not really needed, but keeps things nice and
// tidy.
Runtime.getRuntime().gc();
+
+ mRequiredVerifierPackage = getRequiredVerifierLPr();
} // synchronized (mPackages)
} // synchronized (mInstallLock)
}
+ private String getRequiredVerifierLPr() {
+ final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
+ PackageManager.GET_DISABLED_COMPONENTS);
+
+ String requiredVerifier = null;
+
+ final int N = receivers.size();
+ for (int i = 0; i < N; i++) {
+ final ResolveInfo info = receivers.get(i);
+
+ if (info.activityInfo == null) {
+ continue;
+ }
+
+ final String packageName = info.activityInfo.packageName;
+
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
+ continue;
+ }
+
+ if (!ps.grantedPermissions
+ .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
+ continue;
+ }
+
+ if (requiredVerifier != null) {
+ throw new RuntimeException("There can be only one required verifier");
+ }
+
+ requiredVerifier = packageName;
+ }
+
+ return requiredVerifier;
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -4350,7 +4408,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
if (ps != null) {
- return ps.stopped;
+ // System apps are never considered stopped for purposes of
+ // filtering, because there may be no way for the user to
+ // actually re-launch them.
+ return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4522,7 +4583,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
if (ps != null) {
- return ps.stopped;
+ // System apps are never considered stopped for purposes of
+ // filtering, because there may be no way for the user to
+ // actually re-launch them.
+ return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4849,17 +4913,110 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- public void verifyPendingInstall(int id, int verificationCode)
- throws RemoteException {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, null);
-
+ public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
+ final PackageVerificationResponse response = new PackageVerificationResponse(
+ verificationCode, Binder.getCallingUid());
msg.arg1 = id;
- msg.arg2 = verificationCode;
+ msg.obj = response;
mHandler.sendMessage(msg);
}
+ private ComponentName matchComponentForVerifier(String packageName,
+ List<ResolveInfo> receivers) {
+ ActivityInfo targetReceiver = null;
+
+ final int NR = receivers.size();
+ for (int i = 0; i < NR; i++) {
+ final ResolveInfo info = receivers.get(i);
+ if (info.activityInfo == null) {
+ continue;
+ }
+
+ if (packageName.equals(info.activityInfo.packageName)) {
+ targetReceiver = info.activityInfo;
+ break;
+ }
+ }
+
+ if (targetReceiver == null) {
+ return null;
+ }
+
+ return new ComponentName(targetReceiver.packageName, targetReceiver.name);
+ }
+
+ private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
+ List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
+ if (pkgInfo.verifiers.length == 0) {
+ return null;
+ }
+
+ final int N = pkgInfo.verifiers.length;
+ final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
+ for (int i = 0; i < N; i++) {
+ final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
+
+ final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
+ receivers);
+ if (comp == null) {
+ continue;
+ }
+
+ final int verifierUid = getUidForVerifier(verifierInfo);
+ if (verifierUid == -1) {
+ continue;
+ }
+
+ if (DEBUG_VERIFY) {
+ Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
+ + " with the correct signature");
+ }
+ sufficientVerifiers.add(comp);
+ verificationState.addSufficientVerifier(verifierUid);
+ }
+
+ return sufficientVerifiers;
+ }
+
+ private int getUidForVerifier(VerifierInfo verifierInfo) {
+ synchronized (mPackages) {
+ final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
+ if (pkg == null) {
+ return -1;
+ } else if (pkg.mSignatures.length != 1) {
+ Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+ + " has more than one signature; ignoring");
+ return -1;
+ }
+
+ /*
+ * If the public key of the package's signature does not match
+ * our expected public key, then this is a different package and
+ * we should skip.
+ */
+
+ final byte[] expectedPublicKey;
+ try {
+ final Signature verifierSig = pkg.mSignatures[0];
+ final PublicKey publicKey = verifierSig.getPublicKey();
+ expectedPublicKey = publicKey.getEncoded();
+ } catch (CertificateException e) {
+ return -1;
+ }
+
+ final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
+
+ if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
+ Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+ + " does not have the expected public key; ignoring");
+ return -1;
+ }
+
+ return pkg.applicationInfo.uid;
+ }
+ }
+
public void finishPackageInstall(int token) {
enforceSystemOrRoot("Only the system is allowed to finish installs");
@@ -5229,9 +5386,11 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
- boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
- boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
- boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+ final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+ final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
+ final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+ PackageInfoLite pkgLite = null;
+
if (onInt && onSd) {
// Check if both bits are set.
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
@@ -5253,7 +5412,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Remote call to find out default install location
- final PackageInfoLite pkgLite;
try {
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -5296,21 +5454,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final InstallArgs args = createInstallArgs(this);
+ mArgs = args;
+
if (ret == PackageManager.INSTALL_SUCCEEDED) {
/*
* Determine if we have any installed package verifiers. If we
* do, then we'll defer to them to verify the packages.
*/
- final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION,
- packageURI);
- verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
- PackageManager.GET_DISABLED_COMPONENTS);
- if (isVerificationEnabled() && receivers.size() > 0) {
- if (DEBUG_INSTALL) {
+ final int requiredUid = mRequiredVerifierPackage == null ? -1
+ : getPackageUid(mRequiredVerifierPackage);
+ if (requiredUid != -1 && isVerificationEnabled()) {
+ final Intent verification = new Intent(
+ Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, packageURI);
+ verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
+ PackageManager.GET_DISABLED_COMPONENTS);
+
+ if (DEBUG_VERIFY) {
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
- + verification.toString());
+ + verification.toString() + " with " + pkgLite.verifiers.length
+ + " optional verifiers");
}
final int verificationId = mPendingVerificationToken++;
@@ -5327,35 +5491,70 @@ public class PackageManagerService extends IPackageManager.Stub {
verificationURI);
}
- mPendingVerification.append(verificationId, args);
+ final PackageVerificationState verificationState = new PackageVerificationState(
+ requiredUid, args);
+
+ mPendingVerification.append(verificationId, verificationState);
+
+ final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+ receivers, verificationState);
/*
- * Send the intent to the registered verification agents,
- * but only start the verification timeout after the target
- * BroadcastReceivers have run.
+ * If any sufficient verifiers were listed in the package
+ * manifest, attempt to ask them.
*/
- mContext.sendOrderedBroadcast(verification,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg = mHandler
- .obtainMessage(CHECK_PENDING_VERIFICATION);
- msg.arg1 = verificationId;
- mHandler.sendMessageDelayed(msg, getVerificationTimeout());
- }
- },
- null, 0, null, null);
+ if (sufficientVerifiers != null) {
+ final int N = sufficientVerifiers.size();
+ if (N == 0) {
+ Slog.i(TAG, "Additional verifiers required, but none installed.");
+ ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+ } else {
+ for (int i = 0; i < N; i++) {
+ final ComponentName verifierComponent = sufficientVerifiers.get(i);
+
+ final Intent sufficientIntent = new Intent(verification);
+ sufficientIntent.setComponent(verifierComponent);
+
+ mContext.sendBroadcast(sufficientIntent);
+ }
+ }
+ }
+
+ final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ mRequiredVerifierPackage, receivers);
+ if (ret == PackageManager.INSTALL_SUCCEEDED
+ && mRequiredVerifierPackage != null) {
+ /*
+ * Send the intent to the required verification agent,
+ * but only start the verification timeout after the
+ * target BroadcastReceivers have run.
+ */
+ verification.setComponent(requiredVerifierComponent);
+ mContext.sendOrderedBroadcast(verification,
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg = mHandler
+ .obtainMessage(CHECK_PENDING_VERIFICATION);
+ msg.arg1 = verificationId;
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, null, 0, null, null);
+
+ /*
+ * We don't want the copy to proceed until verification
+ * succeeds, so null out this field.
+ */
+ mArgs = null;
+ }
} else {
- // Create copy only if we are not in an erroneous state.
- // Remote call to initiate copy using temporary file
- mArgs = args;
+ /*
+ * No package verification is enabled, so immediately start
+ * the remote call to initiate copy using temporary file.
+ */
ret = args.copyApk(mContainerService, true);
}
- } else {
- // There was an error, so let the processPendingInstall() break
- // the bad news... uh, through a call in handleReturnCode()
- mArgs = args;
}
mRet = ret;
@@ -7541,6 +7740,8 @@ public class PackageManagerService extends IPackageManager.Stub {
public static final int DUMP_PROVIDERS = 1 << 7;
+ public static final int DUMP_VERIFIERS = 1 << 8;
+
public static final int OPTION_SHOW_FILTERS = 1 << 0;
private int mTypes;
@@ -7633,6 +7834,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.println(" p[ackages]: dump installed packages");
pw.println(" s[hared-users]: dump shared user IDs");
pw.println(" m[essages]: print collected runtime messages");
+ pw.println(" v[erifiers]: print package verifier info");
pw.println(" <package.name>: info about given package");
return;
} else if ("-f".equals(opt)) {
@@ -7665,11 +7867,24 @@ public class PackageManagerService extends IPackageManager.Stub {
dumpState.setDump(DumpState.DUMP_PROVIDERS);
} else if ("m".equals(cmd) || "messages".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_MESSAGES);
+ } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
+ dumpState.setDump(DumpState.DUMP_VERIFIERS);
}
}
// reader
synchronized (mPackages) {
+ if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+ if (dumpState.onTitlePrinted())
+ pw.println(" ");
+ pw.println("Verifiers:");
+ pw.print(" Required: ");
+ pw.print(mRequiredVerifierPackage);
+ pw.print(" (uid=");
+ pw.print(getPackageUid(mRequiredVerifierPackage));
+ pw.println(")");
+ }
+
if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
if (dumpState.onTitlePrinted())
pw.println(" ");
diff --git a/services/java/com/android/server/pm/PackageVerificationResponse.java b/services/java/com/android/server/pm/PackageVerificationResponse.java
new file mode 100644
index 0000000..b2ae0dd
--- /dev/null
+++ b/services/java/com/android/server/pm/PackageVerificationResponse.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+public class PackageVerificationResponse {
+ public final int code;
+
+ public final int callerUid;
+
+ public PackageVerificationResponse(int code, int callerUid) {
+ this.code = code;
+ this.callerUid = callerUid;
+ }
+}
diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/java/com/android/server/pm/PackageVerificationState.java
new file mode 100644
index 0000000..e5b89c1
--- /dev/null
+++ b/services/java/com/android/server/pm/PackageVerificationState.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import com.android.server.pm.PackageManagerService.InstallArgs;
+
+import android.content.pm.PackageManager;
+import android.util.SparseBooleanArray;
+
+/**
+ * Tracks the package verification state for a particular package. Each package
+ * verification has a required verifier and zero or more sufficient verifiers.
+ * Only one of the sufficient verifier list must return affirmative to allow the
+ * package to be considered verified. If there are zero sufficient verifiers,
+ * then package verification is considered complete.
+ */
+class PackageVerificationState {
+ private final InstallArgs mArgs;
+
+ private final SparseBooleanArray mSufficientVerifierUids;
+
+ private final int mRequiredVerifierUid;
+
+ private boolean mSufficientVerificationComplete;
+
+ private boolean mSufficientVerificationPassed;
+
+ private boolean mRequiredVerificationComplete;
+
+ private boolean mRequiredVerificationPassed;
+
+ /**
+ * Create a new package verification state where {@code requiredVerifierUid}
+ * is the user ID for the package that must reply affirmative before things
+ * can continue.
+ *
+ * @param requiredVerifierUid user ID of required package verifier
+ * @param args
+ */
+ public PackageVerificationState(int requiredVerifierUid, InstallArgs args) {
+ mRequiredVerifierUid = requiredVerifierUid;
+ mArgs = args;
+ mSufficientVerifierUids = new SparseBooleanArray();
+ }
+
+ public InstallArgs getInstallArgs() {
+ return mArgs;
+ }
+
+ /**
+ * Add a verifier which is added to our sufficient list.
+ *
+ * @param uid user ID of sufficient verifier
+ */
+ public void addSufficientVerifier(int uid) {
+ mSufficientVerifierUids.put(uid, true);
+ }
+
+ /**
+ * Should be called when a verification is received from an agent so the
+ * state of the package verification can be tracked.
+ *
+ * @param uid user ID of the verifying agent
+ * @return {@code true} if the verifying agent actually exists in our list
+ */
+ public boolean setVerifierResponse(int uid, int code) {
+ if (uid == mRequiredVerifierUid) {
+ mRequiredVerificationComplete = true;
+ switch (code) {
+ case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT:
+ mSufficientVerifierUids.clear();
+ // fall through
+ case PackageManager.VERIFICATION_ALLOW:
+ mRequiredVerificationPassed = true;
+ break;
+ default:
+ mRequiredVerificationPassed = false;
+ }
+ return true;
+ } else {
+ if (mSufficientVerifierUids.get(uid)) {
+ if (code == PackageManager.VERIFICATION_ALLOW) {
+ mSufficientVerificationComplete = true;
+ mSufficientVerificationPassed = true;
+ }
+
+ mSufficientVerifierUids.delete(uid);
+ if (mSufficientVerifierUids.size() == 0) {
+ mSufficientVerificationComplete = true;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns whether verification is considered complete. This means that the
+ * required verifier and at least one of the sufficient verifiers has
+ * returned a positive verification.
+ *
+ * @return {@code true} when verification is considered complete
+ */
+ public boolean isVerificationComplete() {
+ if (!mRequiredVerificationComplete) {
+ return false;
+ }
+
+ if (mSufficientVerifierUids.size() == 0) {
+ return true;
+ }
+
+ return mSufficientVerificationComplete;
+ }
+
+ /**
+ * Returns whether installation should be allowed. This should only be
+ * called after {@link #isVerificationComplete()} returns {@code true}.
+ *
+ * @return {@code true} if installation should be allowed
+ */
+ public boolean isInstallAllowed() {
+ if (!mRequiredVerificationPassed) {
+ return false;
+ }
+
+ if (mSufficientVerificationComplete) {
+ return mSufficientVerificationPassed;
+ }
+
+ return true;
+ }
+}
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index bfa2b39..61c96bb 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -194,7 +194,7 @@ class AppWindowToken extends WindowToken {
// This must be called while inside a transaction.
boolean stepAnimationLocked(long currentTime, int dw, int dh) {
- if (!service.mDisplayFrozen && service.mPolicy.isScreenOn()) {
+ if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
// We will run animations as long as the display isn't frozen.
if (animation == WindowManagerService.sDummyAnimation) {
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index dd440bf..f2e7485 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -125,6 +125,12 @@ class DragState {
mDragWindowHandle.frameTop = 0;
mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
+
+ // Pause rotations before a drag.
+ if (WindowManagerService.DEBUG_ORIENTATION) {
+ Slog.d(WindowManagerService.TAG, "Pausing rotation during drag");
+ }
+ mService.pauseRotationLocked();
}
}
@@ -142,6 +148,12 @@ class DragState {
mDragWindowHandle = null;
mDragApplicationHandle = null;
+
+ // Resume rotations after a drag.
+ if (WindowManagerService.DEBUG_ORIENTATION) {
+ Slog.d(WindowManagerService.TAG, "Resuming rotation after drag");
+ }
+ mService.resumeRotationLocked();
}
}
@@ -257,13 +269,6 @@ class DragState {
// free our resources and drop all the object references
mService.mDragState.reset();
mService.mDragState = null;
-
- if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation");
- boolean changed = mService.setRotationUncheckedLocked(
- WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
- if (changed) {
- mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- }
}
void notifyMoveLw(float x, float y) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 609016b..3ea9e81 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -73,6 +73,7 @@ import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IRemoteCallback;
import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
@@ -91,6 +92,7 @@ import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TypedValue;
@@ -384,6 +386,12 @@ public class WindowManagerService extends IWindowManager.Stub
ArrayList<WindowState> mForceRemoves;
/**
+ * Windows that clients are waiting to have drawn.
+ */
+ ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
+ = new ArrayList<Pair<WindowState, IRemoteCallback>>();
+
+ /**
* Used when rebuilding window list to keep track of windows that have
* been removed.
*/
@@ -419,14 +427,11 @@ public class WindowManagerService extends IWindowManager.Stub
int mAppDisplayWidth = 0;
int mAppDisplayHeight = 0;
int mRotation = 0;
- int mRequestedRotation = 0;
int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
- int mLastRotationFlags;
ArrayList<IRotationWatcher> mRotationWatchers
= new ArrayList<IRotationWatcher>();
- int mDeferredRotation;
- int mDeferredRotationAnimFlags;
+ int mDeferredRotationPauseCount;
boolean mLayoutNeeded = true;
boolean mAnimationPending = false;
@@ -2191,7 +2196,8 @@ public class WindowManagerService extends IWindowManager.Stub
// to hold off on removing the window until the animation is done.
// If the display is frozen, just remove immediately, since the
// animation wouldn't be seen.
- if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
+ if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled
+ && mPolicy.isScreenOnFully()) {
// If we are not currently running the exit animation, we
// need to see about starting one.
if (wasVisible=win.isWinVisibleLw()) {
@@ -2569,7 +2575,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (displayed) {
if (win.mSurface != null && !win.mDrawPending
&& !win.mCommitDrawPending && !mDisplayFrozen
- && mDisplayEnabled && mPolicy.isScreenOn()) {
+ && mDisplayEnabled && mPolicy.isScreenOnFully()) {
applyEnterAnimationLocked(win);
}
if ((win.mAttrs.flags
@@ -2862,7 +2868,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
- if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
int anim = mPolicy.selectAnimationLw(win, transit);
int attr = -1;
Animation a = null;
@@ -2948,7 +2954,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
- if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
Animation a;
if (mNextAppTransitionPackage != null) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -3405,9 +3411,7 @@ public class WindowManagerService extends IWindowManager.Stub
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
- if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
- mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE,
- inTransaction)) {
+ if (updateRotationUncheckedLocked(inTransaction)) {
changed = true;
}
}
@@ -3514,7 +3518,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Prepare app transition: transit=" + transit
+ " mNextAppTransition=" + mNextAppTransition);
- if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
|| mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
mNextAppTransition = transit;
@@ -3598,7 +3602,7 @@ public class WindowManagerService extends IWindowManager.Stub
// If the display is frozen, we won't do anything until the
// actual window is displayed so there is no reason to put in
// the starting window.
- if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn()) {
+ if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully()) {
return;
}
@@ -3880,7 +3884,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 (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()
+ if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()
&& mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
// Already in requested state, don't do anything more.
if (wtoken.hiddenRequested != visible) {
@@ -4008,7 +4012,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
synchronized(mWindowMap) {
- if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
+ if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOnFully()) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
return;
}
@@ -4521,6 +4525,16 @@ public class WindowManagerService extends IWindowManager.Stub
return mPolicy.isKeyguardSecure();
}
+ public void dismissKeyguard() {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires DISABLE_KEYGUARD permission");
+ }
+ synchronized(mWindowMap) {
+ mPolicy.dismissKeyguardLw();
+ }
+ }
+
public void closeSystemDialogs(String reason) {
synchronized(mWindowMap) {
for (int i=mWindows.size()-1; i>=0; i--) {
@@ -4814,8 +4828,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.enableScreenAfterBoot();
// Make sure the last requested orientation has been applied.
- setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
- mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
+ updateRotationUnchecked(false);
}
public void showBootMessage(final CharSequence msg, final boolean always) {
@@ -5034,6 +5047,10 @@ public class WindowManagerService extends IWindowManager.Stub
return bm;
}
+ /**
+ * Freeze rotation changes. (Enable "rotation lock".)
+ * Persists across reboots.
+ */
public void freezeRotation() {
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"freezeRotation()")) {
@@ -5043,9 +5060,13 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation);
- setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0);
+ updateRotationUnchecked(false);
}
+ /**
+ * Thaw rotation changes. (Disable "rotation lock".)
+ * Persists across reboots.
+ */
public void thawRotation() {
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"thawRotation()")) {
@@ -5055,30 +5076,56 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used
- setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0);
+ updateRotationUnchecked(false);
}
- public void setRotation(int rotation,
- boolean alwaysSendConfiguration, int animFlags) {
- if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
- "setRotation()")) {
- throw new SecurityException("Requires SET_ORIENTATION permission");
- }
+ /**
+ * Recalculate the current rotation.
+ *
+ * Called by the window manager policy whenever the state of the system changes
+ * such that the current rotation might need to be updated, such as when the
+ * device is docked or rotated into a new posture.
+ */
+ public void updateRotation(boolean alwaysSendConfiguration) {
+ updateRotationUnchecked(alwaysSendConfiguration);
+ }
- setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
+ /**
+ * Temporarily pauses rotation changes until resumed.
+ *
+ * This can be used to prevent rotation changes from occurring while the user is
+ * performing certain operations, such as drag and drop.
+ *
+ * This call nests and must be matched by an equal number of calls to {@link #resumeRotation}.
+ */
+ void pauseRotationLocked() {
+ mDeferredRotationPauseCount += 1;
}
- public void setRotationUnchecked(int rotation,
- boolean alwaysSendConfiguration, int animFlags) {
- if(DEBUG_ORIENTATION) Slog.v(TAG,
- "setRotationUnchecked(rotation=" + rotation +
- " alwaysSendConfiguration=" + alwaysSendConfiguration +
- " animFlags=" + animFlags);
+ /**
+ * Resumes normal rotation changes after being paused.
+ */
+ void resumeRotationLocked() {
+ if (mDeferredRotationPauseCount > 0) {
+ mDeferredRotationPauseCount -= 1;
+ if (mDeferredRotationPauseCount == 0) {
+ boolean changed = updateRotationUncheckedLocked(false);
+ if (changed) {
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ }
+ }
+ }
+ }
+
+ public void updateRotationUnchecked(
+ boolean alwaysSendConfiguration) {
+ if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
+ + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
long origId = Binder.clearCallingIdentity();
boolean changed;
synchronized(mWindowMap) {
- changed = setRotationUncheckedLocked(rotation, animFlags, false);
+ changed = updateRotationUncheckedLocked(false);
}
if (changed || alwaysSendConfiguration) {
@@ -5089,152 +5136,114 @@ public class WindowManagerService extends IWindowManager.Stub
}
/**
- * Apply a new rotation to the screen, respecting the requests of
- * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
- * re-evaluate the desired rotation.
- *
- * Returns null if the rotation has been changed. In this case YOU
- * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
+ * Updates the current rotation.
+ *
+ * Returns true if the rotation has been changed. In this case YOU
+ * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
*/
- public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) {
- if (mDragState != null
- || (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating())) {
- // Potential rotation during a drag or while waiting for a previous orientation
- // change to finish (rotation animation will be dismissed).
- // Don't do the rotation now, but make a note to perform the rotation later.
- if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation.");
- if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) {
- mDeferredRotation = rotation;
- mDeferredRotationAnimFlags = animFlags;
- }
+ public boolean updateRotationUncheckedLocked(boolean inTransaction) {
+ if (mDeferredRotationPauseCount > 0) {
+ // Rotation updates have been paused temporarily. Defer the update until
+ // updates have been resumed.
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
return false;
}
- boolean changed;
- if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
- if (mDeferredRotation != WindowManagerPolicy.USE_LAST_ROTATION) {
- rotation = mDeferredRotation;
- mRequestedRotation = rotation;
- mLastRotationFlags = mDeferredRotationAnimFlags;
- }
- rotation = mRequestedRotation;
- } else {
- mRequestedRotation = rotation;
- mLastRotationFlags = animFlags;
- }
- mDeferredRotation = WindowManagerPolicy.USE_LAST_ROTATION;
- if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
- rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
- mRotation, mDisplayEnabled);
- if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
-
- int desiredRotation = rotation;
- int lockedRotation = mPolicy.getLockedRotationLw();
- if (lockedRotation >= 0 && rotation != lockedRotation) {
- // We are locked in a rotation but something is requesting
- // a different rotation... we will either keep the locked
- // rotation if it results in the same orientation, or have to
- // switch into an emulated orientation mode.
-
- // First, we know that our rotation is actually going to be
- // the locked rotation.
- rotation = lockedRotation;
-
- // Now the difference between the desired and lockedRotation
- // may mean that the orientation is different... if that is
- // not the case, we can just make the desired rotation be the
- // same as the new locked rotation.
- switch (lockedRotation) {
- case Surface.ROTATION_0:
- if (rotation == Surface.ROTATION_180) {
- desiredRotation = lockedRotation;
- }
- break;
- case Surface.ROTATION_90:
- if (rotation == Surface.ROTATION_270) {
- desiredRotation = lockedRotation;
- }
- break;
- case Surface.ROTATION_180:
- if (rotation == Surface.ROTATION_0) {
- desiredRotation = lockedRotation;
- }
- break;
- case Surface.ROTATION_270:
- if (rotation == Surface.ROTATION_90) {
- desiredRotation = lockedRotation;
- }
- break;
- }
+ if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
+ // Rotation updates cannot be performed while the previous rotation change
+ // animation is still in progress. Skip this update. We will try updating
+ // again after the animation is finished and the display is unfrozen.
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
+ return false;
}
- changed = mDisplayEnabled && mRotation != rotation;
- if (mAltOrientation != (rotation != desiredRotation)) {
- changed = true;
- mAltOrientation = rotation != desiredRotation;
+ if (!mDisplayEnabled) {
+ // No point choosing a rotation if the display is not enabled.
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
+ return false;
}
- if (changed) {
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Rotation changed to " + rotation
- + " from " + mRotation
- + " (forceApp=" + mForcedAppOrientation
- + ", req=" + mRequestedRotation + ")");
- mRotation = rotation;
- mWindowsFreezingScreen = true;
- mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
- mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
- 2000);
- mWaitingForConfig = true;
- mLayoutNeeded = true;
- startFreezingDisplayLocked(inTransaction);
- //Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
- mInputManager.setDisplayOrientation(0, rotation);
- if (mDisplayEnabled) {
- // NOTE: We disable the rotation in the emulator because
- // it doesn't support hardware OpenGL emulation yet.
- if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
- && mScreenRotationAnimation.hasScreenshot()) {
- Surface.freezeDisplay(0);
- if (!inTransaction) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION setRotationUnchecked");
- Surface.openTransaction();
- }
- try {
- if (mScreenRotationAnimation != null) {
- mScreenRotationAnimation.setRotation(rotation);
- }
- } finally {
- if (!inTransaction) {
- Surface.closeTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION setRotationUnchecked");
- }
- }
- Surface.setOrientation(0, rotation, animFlags);
- Surface.unfreezeDisplay(0);
- } else {
- Surface.setOrientation(0, rotation, animFlags);
- }
- rebuildBlackFrame(inTransaction);
- }
+ // TODO: Implement forced rotation changes.
+ // Set mAltOrientation to indicate that the application is receiving
+ // an orientation that has different metrics than it expected.
+ // eg. Portrait instead of Landscape.
- for (int i=mWindows.size()-1; i>=0; i--) {
- WindowState w = mWindows.get(i);
- if (w.mSurface != null) {
- w.mOrientationChanging = true;
- }
+ int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
+ boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
+ mForcedAppOrientation, rotation);
+
+ if (DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Application requested orientation "
+ + mForcedAppOrientation + ", got rotation " + rotation
+ + " which has " + (altOrientation ? "incompatible" : "compatible")
+ + " metrics");
+ }
+
+ if (mRotation == rotation && mAltOrientation == altOrientation) {
+ // No change.
+ return false;
+ }
+
+ if (DEBUG_ORIENTATION) {
+ Slog.v(TAG,
+ "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
+ + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
+ + ", forceApp=" + mForcedAppOrientation);
+ }
+
+ mRotation = rotation;
+ mAltOrientation = altOrientation;
+ mPolicy.setRotationLw(mRotation);
+
+ mWindowsFreezingScreen = true;
+ mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
+ mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000);
+ mWaitingForConfig = true;
+ mLayoutNeeded = true;
+ startFreezingDisplayLocked(inTransaction);
+ mInputManager.setDisplayOrientation(0, rotation);
+
+ // NOTE: We disable the rotation in the emulator because
+ // it doesn't support hardware OpenGL emulation yet.
+ if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+ && mScreenRotationAnimation.hasScreenshot()) {
+ Surface.freezeDisplay(0);
+ if (!inTransaction) {
+ if (SHOW_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION setRotationUnchecked");
+ Surface.openTransaction();
}
- for (int i=mRotationWatchers.size()-1; i>=0; i--) {
- try {
- mRotationWatchers.get(i).onRotationChanged(rotation);
- } catch (RemoteException e) {
+ try {
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.setRotation(rotation);
+ }
+ } finally {
+ if (!inTransaction) {
+ Surface.closeTransaction();
+ if (SHOW_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION setRotationUnchecked");
}
}
- } //end if changed
+ Surface.setOrientation(0, rotation);
+ Surface.unfreezeDisplay(0);
+ } else {
+ Surface.setOrientation(0, rotation);
+ }
+ rebuildBlackFrame(inTransaction);
- return changed;
+ for (int i=mWindows.size()-1; i>=0; i--) {
+ WindowState w = mWindows.get(i);
+ if (w.mSurface != null) {
+ w.mOrientationChanging = true;
+ }
+ }
+ for (int i=mRotationWatchers.size()-1; i>=0; i--) {
+ try {
+ mRotationWatchers.get(i).onRotationChanged(rotation);
+ } catch (RemoteException e) {
+ }
+ }
+ return true;
}
public int getRotation() {
@@ -5723,9 +5732,9 @@ public class WindowManagerService extends IWindowManager.Stub
unrotDh = dh;
}
int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw, unrotDh);
- sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDw, unrotDh);
+ sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDh, unrotDw);
sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw, unrotDh);
- sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDw, unrotDh);
+ sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDh, unrotDw);
return sw;
}
@@ -6295,6 +6304,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int DRAG_END_TIMEOUT = 21;
public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
public static final int BOOT_TIMEOUT = 23;
+ public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
private Session mLastReportedHold;
@@ -6605,11 +6615,6 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- case BOOT_TIMEOUT: {
- performBootTimeout();
- break;
- }
-
case APP_FREEZE_TIMEOUT: {
synchronized (mWindowMap) {
Slog.w(TAG, "App freeze timeout expired.");
@@ -6678,6 +6683,27 @@ public class WindowManagerService extends IWindowManager.Stub
notifyHardKeyboardStatusChange();
break;
}
+
+ case BOOT_TIMEOUT: {
+ performBootTimeout();
+ break;
+ }
+
+ case WAITING_FOR_DRAWN_TIMEOUT: {
+ Pair<WindowState, IRemoteCallback> pair;
+ synchronized (mWindowMap) {
+ pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
+ Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
+ if (!mWaitingForDrawn.remove(pair)) {
+ return;
+ }
+ }
+ try {
+ pair.second.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ break;
+ }
}
}
}
@@ -8112,10 +8138,10 @@ public class WindowManagerService extends IWindowManager.Stub
w.mLastContentInsets.set(w.mContentInsets);
w.mLastVisibleInsets.set(w.mVisibleInsets);
- // If the screen is currently frozen, then keep
- // it frozen until this window draws at its new
+ // If the screen is currently frozen or off, then keep
+ // it frozen/off until this window draws at its new
// orientation.
- if (mDisplayFrozen) {
+ if (mDisplayFrozen || !mPolicy.isScreenOnFully()) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Resizing while display frozen: " + w);
w.mOrientationChanging = true;
@@ -8383,7 +8409,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mDimAnimator != null && mDimAnimator.mDimShown) {
animating |= mDimAnimator.updateSurface(dimming, currentTime,
- mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn());
+ mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully());
}
if (!blurring && mBlurShown) {
@@ -8575,50 +8601,68 @@ public class WindowManagerService extends IWindowManager.Stub
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
- boolean changed = setRotationUncheckedLocked(
- WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
+ boolean changed = updateRotationUncheckedLocked(false);
if (changed) {
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ } else {
+ updateRotation = false;
}
}
- mWindowMap.notifyAll();
+ if (orientationChangeComplete && !needRelayout && !updateRotation) {
+ checkDrawnWindowsLocked();
+ }
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
enableScreenIfNeededLocked();
}
- public void waitForAllDrawn() {
- synchronized (mWindowMap) {
- while (true) {
- final int N = mWindows.size();
- boolean okay = true;
- for (int i=0; i<N && okay; i++) {
- WindowState w = mWindows.get(i);
- if (DEBUG_SCREEN_ON) {
- Slog.i(TAG, "Window " + w + " vis=" + w.isVisibleLw()
- + " obscured=" + w.mObscured + " drawn=" + w.isDrawnLw());
+ void checkDrawnWindowsLocked() {
+ if (mWaitingForDrawn.size() > 0) {
+ for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
+ Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
+ WindowState win = pair.first;
+ //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
+ // + win.mRemoved + " visible=" + win.isVisibleLw()
+ // + " shown=" + win.mSurfaceShown);
+ if (win.mRemoved || !win.isVisibleLw()) {
+ // Window has been removed or made invisible; no draw
+ // will now happen, so stop waiting.
+ Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
+ try {
+ pair.second.sendResult(null);
+ } catch (RemoteException e) {
}
- if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
- if (DEBUG_SCREEN_ON) {
- Slog.i(TAG, "Window not yet drawn: " + w);
- }
- okay = false;
- break;
+ mWaitingForDrawn.remove(pair);
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
+ } else if (win.mSurfaceShown) {
+ // Window is now drawn (and shown).
+ try {
+ pair.second.sendResult(null);
+ } catch (RemoteException e) {
}
- }
- if (okay) {
- return;
- }
- try {
- mWindowMap.wait();
- } catch (InterruptedException e) {
+ mWaitingForDrawn.remove(pair);
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
}
}
}
}
+ public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+ synchronized (mWindowMap) {
+ WindowState win = windowForClientLocked(null, token, true);
+ if (win != null) {
+ Pair<WindowState, IRemoteCallback> pair =
+ new Pair<WindowState, IRemoteCallback>(win, callback);
+ Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
+ mH.sendMessageDelayed(m, 2000);
+ mWaitingForDrawn.add(pair);
+ checkDrawnWindowsLocked();
+ }
+ }
+ }
+
/**
* Must be called with the main window manager lock held.
*/
@@ -8885,7 +8929,7 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- if (mDisplay == null || !mPolicy.isScreenOn()) {
+ if (mDisplay == null || !mPolicy.isScreenOnFully()) {
// No need to freeze the screen before the system is ready or if
// the screen is off.
return;
@@ -8984,8 +9028,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
- configChanged |= setRotationUncheckedLocked(
- WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
+ configChanged |= updateRotationUncheckedLocked(false);
}
if (configChanged) {
@@ -9284,6 +9327,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+ if (mWaitingForDrawn.size() > 0) {
+ pw.println();
+ pw.println(" Clients waiting for these windows to be drawn:");
+ for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
+ Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
+ pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
+ pw.print(": "); pw.println(pair.second);
+ }
+ }
pw.println();
if (mDisplay != null) {
pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
@@ -9349,12 +9401,10 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
pw.print(" mRotation="); pw.print(mRotation);
- pw.print(" mRequestedRotation="); pw.print(mRequestedRotation);
pw.print(" mAltOrientation="); pw.println(mAltOrientation);
pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation);
pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
- pw.print(" mDeferredRotation="); pw.print(mDeferredRotation);
- pw.print(", mDeferredRotationAnimFlags="); pw.println(mDeferredRotationAnimFlags);
+ pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
pw.print(" mAnimationPending="); pw.print(mAnimationPending);
pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 0ee3f17..455d664 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -870,7 +870,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// This must be called while inside a transaction. Returns true if
// there is more animation to run.
boolean stepAnimationLocked(long currentTime, int dw, int dh) {
- if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOn()) {
+ if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOnFully()) {
// We will run animations as long as the display isn't frozen.
if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
@@ -1101,7 +1101,20 @@ final class WindowState implements WindowManagerPolicy.WindowState {
final Matrix tmpMatrix = mTmpMatrix;
// Compute the desired transformation.
- tmpMatrix.setTranslate(0, 0);
+ if (screenAnimation) {
+ // If we are doing a screen animation, the global rotation
+ // applied to windows can result in windows that are carefully
+ // aligned with each other to slightly separate, allowing you
+ // to see what is behind them. An unsightly mess. This...
+ // thing... magically makes it call good: scale each window
+ // slightly (two pixels larger in each dimension, from the
+ // window's center).
+ final float w = frame.width();
+ final float h = frame.height();
+ tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
+ } else {
+ tmpMatrix.reset();
+ }
tmpMatrix.postScale(mGlobalScale, mGlobalScale);
if (selfTransformation) {
tmpMatrix.postConcat(mTransformation.getMatrix());
@@ -1204,11 +1217,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* mPolicyVisibility. Ungh.
*/
public boolean isVisibleOrBehindKeyguardLw() {
+ if (mRootToken.waitingToShow &&
+ mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ return false;
+ }
final AppWindowToken atoken = mAppToken;
- return mSurface != null && !mAttachedHidden
+ final boolean animating = atoken != null
+ ? (atoken.animation != null) : false;
+ return mSurface != null && !mDestroying && !mExiting
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
- && !mDrawPending && !mCommitDrawPending
- && !mExiting && !mDestroying;
+ && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
+ && !mRootToken.hidden)
+ || mAnimation != null || animating);
}
/**
@@ -1351,7 +1371,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
&& (mFrame.top != mLastFrame.top
|| mFrame.left != mLastFrame.left)
&& (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
- && mService.mPolicy.isScreenOn();
+ && mService.mPolicy.isScreenOnFully();
}
boolean isFullscreen(int screenWidth, int screenHeight) {
@@ -1436,7 +1456,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (doAnimation) {
if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
+ mPolicyVisibility + " mAnimation=" + mAnimation);
- if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+ if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
doAnimation = false;
} else if (mPolicyVisibility && mAnimation == null) {
// Check for the case where we are currently visible and
@@ -1462,7 +1482,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean hideLw(boolean doAnimation, boolean requestAnim) {
if (doAnimation) {
- if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+ if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
doAnimation = false;
}
}