summaryrefslogtreecommitdiffstats
path: root/services/java/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android')
-rw-r--r--services/java/com/android/server/AppWidgetService.java40
-rw-r--r--services/java/com/android/server/AppWidgetServiceImpl.java77
-rw-r--r--services/java/com/android/server/BackupManagerService.java234
-rw-r--r--services/java/com/android/server/BootReceiver.java7
-rw-r--r--services/java/com/android/server/ClipboardService.java3
-rw-r--r--services/java/com/android/server/IntentResolver.java25
-rw-r--r--services/java/com/android/server/MountService.java3
-rw-r--r--services/java/com/android/server/WallpaperManagerService.java52
-rw-r--r--services/java/com/android/server/WiredAccessoryObserver.java150
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java283
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java27
-rw-r--r--services/java/com/android/server/am/ActivityStack.java56
-rw-r--r--services/java/com/android/server/am/BroadcastQueue.java2
-rw-r--r--services/java/com/android/server/am/CompatModePackages.java8
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java136
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java614
-rw-r--r--services/java/com/android/server/pm/PackageSetting.java6
-rw-r--r--services/java/com/android/server/pm/PackageSettingBase.java128
-rw-r--r--services/java/com/android/server/pm/Settings.java696
-rw-r--r--services/java/com/android/server/pm/UserManager.java110
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java13
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java116
-rw-r--r--services/java/com/android/server/wm/BlackFrame.java6
-rw-r--r--services/java/com/android/server/wm/DimAnimator.java24
-rw-r--r--services/java/com/android/server/wm/WindowAnimator.java629
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java1228
-rw-r--r--services/java/com/android/server/wm/WindowState.java354
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java298
28 files changed, 3262 insertions, 2063 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 081f1f4..eb024e9 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -170,6 +170,15 @@ class AppWidgetService extends IAppWidgetService.Stub
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mBroadcastReceiver, sdFilter);
+
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, -1));
+ }
+ }, userFilter);
}
@Override
@@ -192,19 +201,6 @@ class AppWidgetService extends IAppWidgetService.Stub
getImplForUser().deleteAllHosts();
}
- void cancelBroadcasts(Provider p) {
- if (p.broadcast != null) {
- mAlarmManager.cancel(p.broadcast);
- long token = Binder.clearCallingIdentity();
- try {
- p.broadcast.cancel();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- p.broadcast = null;
- }
- }
-
@Override
public void bindAppWidgetId(int appWidgetId, ComponentName provider) throws RemoteException {
getImplForUser().bindAppWidgetId(appWidgetId, provider);
@@ -222,8 +218,15 @@ class AppWidgetService extends IAppWidgetService.Stub
return getImplForUser().startListening(host, packageName, hostId, updatedViews);
}
- // TODO: Call this from PackageManagerService when a user is removed
- public void removeUser(int userId) {
+ public void onUserRemoved(int userId) {
+ AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+ if (userId < 1) return;
+
+ if (impl == null) {
+ AppWidgetServiceImpl.getSettingsFile(userId).delete();
+ } else {
+ impl.onUserRemoved();
+ }
}
private AppWidgetServiceImpl getImplForUser() {
@@ -325,9 +328,10 @@ class AppWidgetService extends IAppWidgetService.Stub
service.onConfigurationChanged();
}
} else {
- // TODO: Verify that this only needs to be delivered for the related user and not
- // all the users
- getImplForUser().onBroadcastReceived(intent);
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.onBroadcastReceived(intent);
+ }
}
}
};
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 9c408c4..b24823e 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -27,6 +28,7 @@ import android.content.ServiceConnection;
import android.content.Intent.FilterComparison;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -158,7 +160,7 @@ class AppWidgetServiceImpl {
Context mContext;
Locale mLocale;
- PackageManager mPackageManager;
+ IPackageManager mPm;
AlarmManager mAlarmManager;
ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
@@ -174,7 +176,7 @@ class AppWidgetServiceImpl {
AppWidgetServiceImpl(Context context, int userId) {
mContext = context;
- mPackageManager = context.getPackageManager();
+ mPm = AppGlobals.getPackageManager();
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserId = userId;
}
@@ -1009,16 +1011,19 @@ class AppWidgetServiceImpl {
}
void loadAppWidgetList() {
- PackageManager pm = mPackageManager;
-
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
+ try {
+ List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
- final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
- for (int i = 0; i < N; i++) {
- ResolveInfo ri = broadcastReceivers.get(i);
- addProviderLocked(ri);
+ final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
+ for (int i = 0; i < N; i++) {
+ ResolveInfo ri = broadcastReceivers.get(i);
+ addProviderLocked(ri);
+ }
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
}
}
@@ -1131,7 +1136,7 @@ class AppWidgetServiceImpl {
ActivityInfo activityInfo = ri.activityInfo;
XmlResourceParser parser = null;
try {
- parser = activityInfo.loadXmlMetaData(mPackageManager,
+ parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
if (parser == null) {
Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
@@ -1159,7 +1164,7 @@ class AppWidgetServiceImpl {
info.provider = component;
p.uid = activityInfo.applicationInfo.uid;
- Resources res = mPackageManager
+ Resources res = mContext.getPackageManager()
.getResourcesForApplication(activityInfo.applicationInfo);
TypedArray sa = res.obtainAttributes(attrs,
@@ -1188,7 +1193,7 @@ class AppWidgetServiceImpl {
if (className != null) {
info.configure = new ComponentName(component.getPackageName(), className);
}
- info.label = activityInfo.loadLabel(mPackageManager).toString();
+ info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
info.icon = ri.getIconResource();
info.previewImage = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
@@ -1213,7 +1218,12 @@ class AppWidgetServiceImpl {
}
int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
- PackageInfo pkgInfo = mPackageManager.getPackageInfo(packageName, 0);
+ PackageInfo pkgInfo = null;
+ try {
+ pkgInfo = mPm.getPackageInfo(packageName, 0, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ }
if (pkgInfo == null || pkgInfo.applicationInfo == null) {
throw new PackageManager.NameNotFoundException();
}
@@ -1474,9 +1484,13 @@ class AppWidgetServiceImpl {
}
}
+ static File getSettingsFile(int userId) {
+ return new File("/data/system/users/" + userId + "/" + SETTINGS_FILENAME);
+ }
+
AtomicFile savedStateFile() {
File dir = new File("/data/system/users/" + mUserId);
- File settingsFile = new File(dir, SETTINGS_FILENAME);
+ File settingsFile = getSettingsFile(mUserId);
if (!dir.exists()) {
dir.mkdirs();
if (mUserId == 0) {
@@ -1490,12 +1504,28 @@ class AppWidgetServiceImpl {
return new AtomicFile(settingsFile);
}
+ void onUserRemoved() {
+ // prune the ones we don't want to keep
+ int N = mInstalledProviders.size();
+ for (int i = N - 1; i >= 0; i--) {
+ Provider p = mInstalledProviders.get(i);
+ cancelBroadcasts(p);
+ }
+ getSettingsFile(mUserId).delete();
+ }
+
void addProvidersForPackageLocked(String pkgName) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setPackage(pkgName);
- List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
-
+ List<ResolveInfo> broadcastReceivers;
+ try {
+ broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ return;
+ }
final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
for (int i = 0; i < N; i++) {
ResolveInfo ri = broadcastReceivers.get(i);
@@ -1513,8 +1543,15 @@ class AppWidgetServiceImpl {
HashSet<String> keep = new HashSet<String>();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setPackage(pkgName);
- List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA);
+ List<ResolveInfo> broadcastReceivers;
+ try {
+ broadcastReceivers = mPm.queryIntentReceivers(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_META_DATA, mUserId);
+ } catch (RemoteException re) {
+ // Shouldn't happen, local call
+ return;
+ }
// add the missing ones and collect which ones to keep
int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index a7b08f5..a0d5beb 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -201,9 +201,9 @@ class BackupManagerService extends IBackupManager.Stub {
BackupHandler mBackupHandler;
PendingIntent mRunBackupIntent, mRunInitIntent;
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
- // map UIDs to the set of backup client services within that UID's app set
- final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants
- = new SparseArray<HashSet<ApplicationInfo>>();
+ // map UIDs to the set of participating packages under that UID
+ final SparseArray<HashSet<String>> mBackupParticipants
+ = new SparseArray<HashSet<String>>();
// set of backup services that have pending changes
class BackupRequest {
public String packageName;
@@ -960,7 +960,6 @@ class BackupManagerService extends IBackupManager.Stub {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
// Register for events related to sdcard installation.
@@ -1239,12 +1238,13 @@ class BackupManagerService extends IBackupManager.Stub {
// Enqueue a new backup of every participant
synchronized (mBackupParticipants) {
- int N = mBackupParticipants.size();
+ final int N = mBackupParticipants.size();
for (int i=0; i<N; i++) {
- int uid = mBackupParticipants.keyAt(i);
- HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
- for (ApplicationInfo app: participants) {
- dataChangedImpl(app.packageName);
+ HashSet<String> participants = mBackupParticipants.valueAt(i);
+ if (participants != null) {
+ for (String packageName : participants) {
+ dataChangedImpl(packageName);
+ }
}
}
}
@@ -1302,8 +1302,7 @@ class BackupManagerService extends IBackupManager.Stub {
Bundle extras = intent.getExtras();
String pkgList[] = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
- Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
- Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
Uri uri = intent.getData();
if (uri == null) {
return;
@@ -1312,14 +1311,8 @@ class BackupManagerService extends IBackupManager.Stub {
if (pkgName != null) {
pkgList = new String[] { pkgName };
}
- if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
- // use the existing "add with replacement" logic
- if (MORE_DEBUG) Slog.d(TAG, "PACKAGE_REPLACED, updating package " + pkgName);
- added = replacing = true;
- } else {
- added = Intent.ACTION_PACKAGE_ADDED.equals(action);
- replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
- }
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
added = true;
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1331,20 +1324,23 @@ class BackupManagerService extends IBackupManager.Stub {
if (pkgList == null || pkgList.length == 0) {
return;
}
+
+ final int uid = extras.getInt(Intent.EXTRA_UID);
if (added) {
synchronized (mBackupParticipants) {
if (replacing) {
- updatePackageParticipantsLocked(pkgList);
- } else {
- addPackageParticipantsLocked(pkgList);
+ // This is the package-replaced case; we just remove the entry
+ // under the old uid and fall through to re-add.
+ removePackageParticipantsLocked(pkgList, uid);
}
+ addPackageParticipantsLocked(pkgList);
}
} else {
if (replacing) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
} else {
synchronized (mBackupParticipants) {
- removePackageParticipantsLocked(pkgList);
+ removePackageParticipantsLocked(pkgList, uid);
}
}
}
@@ -1391,12 +1387,12 @@ class BackupManagerService extends IBackupManager.Stub {
for (PackageInfo pkg : targetPkgs) {
if (packageName == null || pkg.packageName.equals(packageName)) {
int uid = pkg.applicationInfo.uid;
- HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
+ HashSet<String> set = mBackupParticipants.get(uid);
if (set == null) {
- set = new HashSet<ApplicationInfo>();
+ set = new HashSet<String>();
mBackupParticipants.put(uid, set);
}
- set.add(pkg.applicationInfo);
+ set.add(pkg.packageName);
if (MORE_DEBUG) Slog.v(TAG, "Agent found; added");
// If we've never seen this app before, schedule a backup for it
@@ -1410,63 +1406,36 @@ class BackupManagerService extends IBackupManager.Stub {
}
// Remove the given packages' entries from our known active set.
- void removePackageParticipantsLocked(String[] packageNames) {
+ void removePackageParticipantsLocked(String[] packageNames, int oldUid) {
if (packageNames == null) {
Slog.w(TAG, "removePackageParticipants with null list");
return;
}
- if (DEBUG) Slog.v(TAG, "removePackageParticipantsLocked: #" + packageNames.length);
- List<PackageInfo> knownPackages = allAgentPackages();
+ if (DEBUG) Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid
+ + " #" + packageNames.length);
for (String pkg : packageNames) {
- removePackageParticipantsLockedInner(pkg, knownPackages);
+ // Known previous UID, so we know which package set to check
+ HashSet<String> set = mBackupParticipants.get(oldUid);
+ if (set != null && set.contains(pkg)) {
+ removePackageFromSetLocked(set, pkg);
+ if (set.isEmpty()) {
+ if (MORE_DEBUG) Slog.v(TAG, " last one of this uid; purging set");
+ mBackupParticipants.remove(oldUid);
+ }
+ }
}
}
- private void removePackageParticipantsLockedInner(String packageName,
- List<PackageInfo> allPackages) {
- if (MORE_DEBUG) {
- Slog.v(TAG, "removePackageParticipantsLockedInner (" + packageName
- + ") removing from " + allPackages.size() + " entries");
- for (PackageInfo p : allPackages) {
- Slog.v(TAG, " - " + p.packageName);
- }
- }
- for (PackageInfo pkg : allPackages) {
- if (packageName == null || pkg.packageName.equals(packageName)) {
- /*
- int uid = -1;
- try {
- PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
- uid = info.applicationInfo.uid;
- } catch (NameNotFoundException e) {
- // we don't know this package name, so just skip it for now
- continue;
- }
- */
- final int uid = pkg.applicationInfo.uid;
- if (MORE_DEBUG) Slog.i(TAG, " found pkg " + packageName + " uid=" + uid);
-
- HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
- if (set != null) {
- // Find the existing entry with the same package name, and remove it.
- // We can't just remove(app) because the instances are different.
- for (ApplicationInfo entry: set) {
- if (MORE_DEBUG) Slog.i(TAG, " checking against " + entry.packageName);
- if (entry.packageName.equals(pkg)) {
- if (MORE_DEBUG) Slog.v(TAG, " removing participant " + pkg);
- set.remove(entry);
- removeEverBackedUp(pkg.packageName);
- break;
- }
- }
- if (set.size() == 0) {
- mBackupParticipants.delete(uid);
- }
- } else {
- if (MORE_DEBUG) Slog.i(TAG, " ... not found in uid mapping");
- }
- }
+ private void removePackageFromSetLocked(final HashSet<String> set,
+ final String packageName) {
+ if (set.contains(packageName)) {
+ // Found it. Remove this one package from the bookkeeping, and
+ // if it's the last participating app under this uid we drop the
+ // (now-empty) set as well.
+ if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName);
+ removeEverBackedUp(packageName);
+ set.remove(packageName);
}
}
@@ -1497,24 +1466,6 @@ class BackupManagerService extends IBackupManager.Stub {
return packages;
}
- // Reset the given package's known backup participants. Unlike add/remove, the update
- // action cannot be passed a null package name.
- void updatePackageParticipantsLocked(String[] packageNames) {
- if (packageNames == null) {
- Slog.e(TAG, "updatePackageParticipants called with null package list");
- return;
- }
- if (DEBUG) Slog.v(TAG, "updatePackageParticipantsLocked: #" + packageNames.length);
-
- if (packageNames.length > 0) {
- List<PackageInfo> allApps = allAgentPackages();
- for (String packageName : packageNames) {
- removePackageParticipantsLockedInner(packageName, allApps);
- addPackageParticipantsLockedInner(packageName, allApps);
- }
- }
- }
-
// Called from the backup task: record that the given app has been successfully
// backed up at least once
void logBackupComplete(String packageName) {
@@ -1986,6 +1937,16 @@ class BackupManagerService extends IBackupManager.Stub {
try {
mCurrentPackage = mPackageManager.getPackageInfo(request.packageName,
PackageManager.GET_SIGNATURES);
+ if (mCurrentPackage.applicationInfo.backupAgentName == null) {
+ // The manifest has changed but we had a stale backup request pending.
+ // This won't happen again because the app won't be requesting further
+ // backups.
+ Slog.i(TAG, "Package " + request.packageName
+ + " no longer supports backup; skipping");
+ addBackupTrace("skipping - no agent, completion is noop");
+ executeNextState(BackupState.RUNNING_QUEUE);
+ return;
+ }
IBackupAgent agent = null;
try {
@@ -2547,6 +2508,8 @@ class BackupManagerService extends IBackupManager.Stub {
finalizeBackup(out);
} catch (RemoteException e) {
Slog.e(TAG, "App died during full backup");
+ } catch (Exception e) {
+ Slog.e(TAG, "Internal exception during full backup", e);
} finally {
tearDown(pkg);
try {
@@ -4681,6 +4644,8 @@ class BackupManagerService extends IBackupManager.Stub {
mTransport.clearBackupData(mPackage);
} catch (RemoteException e) {
// can't happen; the transport is local
+ } catch (Exception e) {
+ Slog.e(TAG, "Transport threw attempting to clear data for " + mPackage);
} finally {
try {
// TODO - need to handle failures
@@ -4758,11 +4723,11 @@ class BackupManagerService extends IBackupManager.Stub {
}
private void dataChangedImpl(String packageName) {
- HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+ HashSet<String> targets = dataChangedTargets(packageName);
dataChangedImpl(packageName, targets);
}
- private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
+ private void dataChangedImpl(String packageName, HashSet<String> targets) {
// Record that we need a backup pass for the caller. Since multiple callers
// may share a uid, we need to note all candidates within that uid and schedule
// a backup pass for each of them.
@@ -4776,27 +4741,23 @@ class BackupManagerService extends IBackupManager.Stub {
synchronized (mQueueLock) {
// Note that this client has made data changes that need to be backed up
- for (ApplicationInfo app : targets) {
- // validate the caller-supplied package name against the known set of
- // packages associated with this uid
- if (app.packageName.equals(packageName)) {
- // Add the caller to the set of pending backups. If there is
- // one already there, then overwrite it, but no harm done.
- BackupRequest req = new BackupRequest(packageName);
- if (mPendingBackups.put(app.packageName, req) == null) {
- if (DEBUG) Slog.d(TAG, "Now staging backup of " + packageName);
-
- // Journal this request in case of crash. The put()
- // operation returned null when this package was not already
- // in the set; we want to avoid touching the disk redundantly.
- writeToJournalLocked(packageName);
+ if (targets.contains(packageName)) {
+ // Add the caller to the set of pending backups. If there is
+ // one already there, then overwrite it, but no harm done.
+ BackupRequest req = new BackupRequest(packageName);
+ if (mPendingBackups.put(packageName, req) == null) {
+ if (DEBUG) Slog.d(TAG, "Now staging backup of " + packageName);
+
+ // Journal this request in case of crash. The put()
+ // operation returned null when this package was not already
+ // in the set; we want to avoid touching the disk redundantly.
+ writeToJournalLocked(packageName);
- if (MORE_DEBUG) {
- int numKeys = mPendingBackups.size();
- Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
- for (BackupRequest b : mPendingBackups.values()) {
- Slog.d(TAG, " + " + b);
- }
+ if (MORE_DEBUG) {
+ int numKeys = mPendingBackups.size();
+ Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
+ for (BackupRequest b : mPendingBackups.values()) {
+ Slog.d(TAG, " + " + b);
}
}
}
@@ -4805,7 +4766,7 @@ class BackupManagerService extends IBackupManager.Stub {
}
// Note: packageName is currently unused, but may be in the future
- private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
+ private HashSet<String> dataChangedTargets(String packageName) {
// If the caller does not hold the BACKUP permission, it can only request a
// backup of its own data.
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
@@ -4817,11 +4778,11 @@ class BackupManagerService extends IBackupManager.Stub {
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow backup of ANY app?
- HashSet<ApplicationInfo> targets = new HashSet<ApplicationInfo>();
+ HashSet<String> targets = new HashSet<String>();
synchronized (mBackupParticipants) {
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
- HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
+ HashSet<String> s = mBackupParticipants.valueAt(i);
if (s != null) {
targets.addAll(s);
}
@@ -4848,7 +4809,7 @@ class BackupManagerService extends IBackupManager.Stub {
// ----- IBackupManager binder interface -----
public void dataChanged(final String packageName) {
- final HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+ final HashSet<String> targets = dataChangedTargets(packageName);
if (targets == null) {
Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+ " uid=" + Binder.getCallingUid());
@@ -4875,7 +4836,7 @@ class BackupManagerService extends IBackupManager.Stub {
// If the caller does not hold the BACKUP permission, it can only request a
// wipe of its own backed-up data.
- HashSet<ApplicationInfo> apps;
+ HashSet<String> apps;
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
apps = mBackupParticipants.get(Binder.getCallingUid());
@@ -4883,30 +4844,27 @@ class BackupManagerService extends IBackupManager.Stub {
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow data-clear of ANY app?
if (DEBUG) Slog.v(TAG, "Privileged caller, allowing clear of other apps");
- apps = new HashSet<ApplicationInfo>();
+ apps = new HashSet<String>();
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
- HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
+ HashSet<String> s = mBackupParticipants.valueAt(i);
if (s != null) {
apps.addAll(s);
}
}
}
- // now find the given package in the set of candidate apps
- for (ApplicationInfo app : apps) {
- if (app.packageName.equals(packageName)) {
- if (DEBUG) Slog.v(TAG, "Found the app - running clear process");
- // found it; fire off the clear request
- synchronized (mQueueLock) {
- long oldId = Binder.clearCallingIdentity();
- mWakelock.acquire();
- Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
- new ClearParams(getTransport(mCurrentTransport), info));
- mBackupHandler.sendMessage(msg);
- Binder.restoreCallingIdentity(oldId);
- }
- break;
+ // Is the given app an available participant?
+ if (apps.contains(packageName)) {
+ if (DEBUG) Slog.v(TAG, "Found the app - running clear process");
+ // found it; fire off the clear request
+ synchronized (mQueueLock) {
+ long oldId = Binder.clearCallingIdentity();
+ mWakelock.acquire();
+ Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
+ new ClearParams(getTransport(mCurrentTransport), info));
+ mBackupHandler.sendMessage(msg);
+ Binder.restoreCallingIdentity(oldId);
}
}
}
@@ -5824,9 +5782,9 @@ class BackupManagerService extends IBackupManager.Stub {
int uid = mBackupParticipants.keyAt(i);
pw.print(" uid: ");
pw.println(uid);
- HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
- for (ApplicationInfo app: participants) {
- pw.println(" " + app.packageName);
+ HashSet<String> participants = mBackupParticipants.valueAt(i);
+ for (String app: participants) {
+ pw.println(" " + app);
}
}
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index da65438..22874e6 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -20,13 +20,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.net.Downloads;
import android.os.Build;
import android.os.DropBoxManager;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.RecoverySystem;
import android.os.SystemProperties;
+import android.provider.Downloads;
import android.util.Slog;
import java.io.File;
@@ -78,9 +78,8 @@ public class BootReceiver extends BroadcastReceiver {
}.start();
}
- private void removeOldUpdatePackages(Context ctx) {
- Downloads.ByUri.removeAllDownloadsByPackage(
- ctx, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS);
+ private void removeOldUpdatePackages(Context context) {
+ Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS);
}
private void logBootEvents(Context ctx) throws IOException {
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index 062ab74..2e2a278 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -34,6 +34,7 @@ import android.os.Parcel;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.UserId;
import android.util.Pair;
import android.util.Slog;
@@ -204,7 +205,7 @@ public class ClipboardService extends IClipboard.Stub {
PackageInfo pi;
try {
pi = mPm.getPackageInfo(pkg, 0);
- if (pi.applicationInfo.uid != uid) {
+ if (!UserId.isSameApp(pi.applicationInfo.uid, uid)) {
throw new SecurityException("Calling uid " + uid
+ " does not own package " + pkg);
}
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b3d7220..f7e841e 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -201,7 +201,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
}
public List<R> queryIntentFromList(Intent intent, String resolvedType,
- boolean defaultOnly, ArrayList<ArrayList<F>> listCut) {
+ boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) {
ArrayList<R> resultList = new ArrayList<R>();
final boolean debug = localLOGV ||
@@ -212,13 +212,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
int N = listCut.size();
for (int i = 0; i < N; ++i) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, listCut.get(i), resultList);
+ resolvedType, scheme, listCut.get(i), resultList, userId);
}
sortResults(resultList);
return resultList;
}
- public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
+ public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
+ int userId) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
@@ -290,19 +291,19 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
if (firstTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, firstTypeCut, finalList);
+ resolvedType, scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, secondTypeCut, finalList);
+ resolvedType, scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, thirdTypeCut, finalList);
+ resolvedType, scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, schemeCut, finalList);
+ resolvedType, scheme, schemeCut, finalList, userId);
}
sortResults(finalList);
@@ -329,7 +330,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
* "stopped," that is whether it should not be included in the result
* if the intent requests to excluded stopped objects.
*/
- protected boolean isFilterStopped(F filter) {
+ protected boolean isFilterStopped(F filter, int userId) {
return false;
}
@@ -341,7 +342,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
protected abstract String packageForFilter(F filter);
@SuppressWarnings("unchecked")
- protected R newResult(F filter, int match) {
+ protected R newResult(F filter, int match, int userId) {
return (R)filter;
}
@@ -504,7 +505,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly,
- String resolvedType, String scheme, List<F> src, List<R> dest) {
+ String resolvedType, String scheme, List<F> src, List<R> dest, int userId) {
final String action = intent.getAction();
final Uri data = intent.getData();
final String packageName = intent.getPackage();
@@ -519,7 +520,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
int match;
if (debug) Slog.v(TAG, "Matching against filter " + filter);
- if (excludingStopped && isFilterStopped(filter)) {
+ if (excludingStopped && isFilterStopped(filter, userId)) {
if (debug) {
Slog.v(TAG, " Filter's target is stopped; skipping");
}
@@ -547,7 +548,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
if (debug) Slog.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
- final R oneResult = newResult(filter, match);
+ final R oneResult = newResult(filter, match, userId);
if (oneResult != null) {
dest.add(oneResult);
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 366160b..510bdb2 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -48,6 +48,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserId;
import android.os.storage.IMountService;
import android.os.storage.IMountServiceListener;
import android.os.storage.IMountShutdownObserver;
@@ -1674,7 +1675,7 @@ class MountService extends IMountService.Stub
return false;
}
- final int packageUid = mPms.getPackageUid(packageName);
+ final int packageUid = mPms.getPackageUid(packageName, UserId.getUserId(callerUid));
if (DEBUG_OBB) {
Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 8ee12bc..6d83f30 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -25,9 +25,11 @@ import android.app.PendingIntent;
import android.app.WallpaperInfo;
import android.app.backup.BackupManager;
import android.app.backup.WallpaperBackupHelper;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -36,6 +38,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.RemoteException;
@@ -401,41 +404,48 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
wallpaper.wallpaperObserver.stopWatching();
}
}
-
+
public void systemReady() {
if (DEBUG) Slog.v(TAG, "systemReady");
WallpaperData wallpaper = mWallpaperMap.get(0);
switchWallpaper(wallpaper);
wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
wallpaper.wallpaperObserver.startWatching();
- ActivityManagerService ams = (ActivityManagerService) ServiceManager
- .getService(Context.ACTIVITY_SERVICE);
- ams.addUserListener(new ActivityManagerService.UserListener() {
-
- @Override
- public void onUserChanged(int userId) {
- switchUser(userId);
- }
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(new BroadcastReceiver() {
@Override
- public void onUserAdded(int userId) {
- }
-
- @Override
- public void onUserRemoved(int userId) {
- }
-
- @Override
- public void onUserLoggedOut(int userId) {
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ switchUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+ }
}
-
- });
+ }, userFilter);
}
String getName() {
return mWallpaperMap.get(0).name;
}
+ void removeUser(int userId) {
+ synchronized (mLock) {
+ WallpaperData wallpaper = mWallpaperMap.get(userId);
+ if (wallpaper != null) {
+ wallpaper.wallpaperObserver.stopWatching();
+ mWallpaperMap.remove(userId);
+ }
+ File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
+ wallpaperFile.delete();
+ File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
+ wallpaperInfoFile.delete();
+ }
+ }
+
void switchUser(int userId) {
synchronized (mLock) {
mCurrentUserId = userId;
@@ -861,7 +871,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
}
private static JournaledFile makeJournaledFile(int userId) {
- final String base = "/data/system/users/" + userId + "/" + WALLPAPER_INFO;
+ final String base = getWallpaperDir(userId) + "/" + WALLPAPER_INFO;
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 326b940..9b4eddc 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -30,8 +30,11 @@ import android.util.Slog;
import android.media.AudioManager;
import android.util.Log;
+import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
/**
* <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
@@ -39,17 +42,6 @@ import java.io.FileNotFoundException;
class WiredAccessoryObserver extends UEventObserver {
private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
private static final boolean LOG = true;
- private static final int MAX_AUDIO_PORTS = 3; /* h2w, USB Audio & hdmi */
- private static final String uEventInfo[][] = { {"DEVPATH=/devices/virtual/switch/h2w",
- "/sys/class/switch/h2w/state",
- "/sys/class/switch/h2w/name"},
- {"DEVPATH=/devices/virtual/switch/usb_audio",
- "/sys/class/switch/usb_audio/state",
- "/sys/class/switch/usb_audio/name"},
- {"DEVPATH=/devices/virtual/switch/hdmi",
- "/sys/class/switch/hdmi/state",
- "/sys/class/switch/hdmi/name"} };
-
private static final int BIT_HEADSET = (1 << 0);
private static final int BIT_HEADSET_NO_MIC = (1 << 1);
private static final int BIT_USB_HEADSET_ANLG = (1 << 2);
@@ -60,10 +52,89 @@ class WiredAccessoryObserver extends UEventObserver {
BIT_HDMI_AUDIO);
private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
+ private static class UEventInfo {
+ private final String mDevName;
+ private final int mState1Bits;
+ private final int mState2Bits;
+
+ public UEventInfo(String devName, int state1Bits, int state2Bits) {
+ mDevName = devName;
+ mState1Bits = state1Bits;
+ mState2Bits = state2Bits;
+ }
+
+ public String getDevName() { return mDevName; }
+
+ public String getDevPath() {
+ return String.format("/devices/virtual/switch/%s", mDevName);
+ }
+
+ public String getSwitchStatePath() {
+ return String.format("/sys/class/switch/%s/state", mDevName);
+ }
+
+ public boolean checkSwitchExists() {
+ File f = new File(getSwitchStatePath());
+ return ((null != f) && f.exists());
+ }
+
+ public int computeNewHeadsetState(int headsetState, int switchState) {
+ int preserveMask = ~(mState1Bits | mState2Bits);
+ int setBits = ((switchState == 1) ? mState1Bits :
+ ((switchState == 2) ? mState2Bits : 0));
+
+ return ((headsetState & preserveMask) | setBits);
+ }
+ }
+
+ private static List<UEventInfo> makeObservedUEventList() {
+ List<UEventInfo> retVal = new ArrayList<UEventInfo>();
+ UEventInfo uei;
+
+ // Monitor h2w
+ uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have wired headset support");
+ }
+
+ // Monitor USB
+ uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have usb audio support");
+ }
+
+ // Monitor HDMI
+ //
+ // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled
+ // only when the HDMI driver has a video mode configured, and the downstream sink indicates
+ // support for audio in its EDID.
+ //
+ // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi"
+ // switch instead.
+ uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0);
+ if (uei.checkSwitchExists()) {
+ retVal.add(uei);
+ } else {
+ Slog.w(TAG, "This kernel does not have HDMI audio support");
+ }
+ }
+
+ return retVal;
+ }
+
+ private static List<UEventInfo> uEventInfo = makeObservedUEventList();
+
private int mHeadsetState;
private int mPrevHeadsetState;
private String mHeadsetName;
- private int switchState;
private final Context mContext;
private final WakeLock mWakeLock; // held while there is a pending route change
@@ -85,71 +156,60 @@ class WiredAccessoryObserver extends UEventObserver {
// one on the board, one on the dock and one on HDMI:
// observe three UEVENTs
init(); // set initial status
- for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
- startObserving(uEventInfo[i][0]);
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
+ startObserving("DEVPATH="+uei.getDevPath());
}
}
- }
+ }
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
try {
+ String devPath = event.get("DEVPATH");
String name = event.get("SWITCH_NAME");
int state = Integer.parseInt(event.get("SWITCH_STATE"));
- updateState(name, state);
+ updateState(devPath, name, state);
} catch (NumberFormatException e) {
Slog.e(TAG, "Could not parse switch state from event " + event);
}
}
- private synchronized final void updateState(String name, int state)
+ private synchronized final void updateState(String devPath, String name, int state)
{
- if (name.equals("usb_audio")) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|BIT_HDMI_AUDIO)) |
- ((state == 1) ? BIT_USB_HEADSET_ANLG :
- ((state == 2) ? BIT_USB_HEADSET_DGTL : 0)));
- } else if (name.equals("hdmi")) {
- switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
- BIT_USB_HEADSET_DGTL|BIT_USB_HEADSET_ANLG)) |
- ((state == 1) ? BIT_HDMI_AUDIO : 0));
- } else {
- switchState = ((mHeadsetState & (BIT_HDMI_AUDIO|BIT_USB_HEADSET_ANLG|
- BIT_USB_HEADSET_DGTL)) |
- ((state == 1) ? BIT_HEADSET :
- ((state == 2) ? BIT_HEADSET_NO_MIC : 0)));
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
+ if (devPath.equals(uei.getDevPath())) {
+ update(name, uei.computeNewHeadsetState(mHeadsetState, state));
+ return;
+ }
}
- update(name, switchState);
}
private synchronized final void init() {
char[] buffer = new char[1024];
-
- String newName = mHeadsetName;
- int newState = mHeadsetState;
mPrevHeadsetState = mHeadsetState;
if (LOG) Slog.v(TAG, "init()");
- for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
+ for (int i = 0; i < uEventInfo.size(); ++i) {
+ UEventInfo uei = uEventInfo.get(i);
try {
- FileReader file = new FileReader(uEventInfo[i][1]);
+ int curState;
+ FileReader file = new FileReader(uei.getSwitchStatePath());
int len = file.read(buffer, 0, 1024);
file.close();
- newState = Integer.valueOf((new String(buffer, 0, len)).trim());
-
- file = new FileReader(uEventInfo[i][2]);
- len = file.read(buffer, 0, 1024);
- file.close();
- newName = new String(buffer, 0, len).trim();
+ curState = Integer.valueOf((new String(buffer, 0, len)).trim());
- if (newState > 0) {
- updateState(newName, newState);
+ if (curState > 0) {
+ updateState(uei.getDevPath(), uei.getDevName(), curState);
}
} catch (FileNotFoundException e) {
- Slog.w(TAG, "This kernel does not have wired headset support");
+ Slog.w(TAG, uei.getSwitchStatePath() +
+ " not found while attempting to determine initial switch state");
} catch (Exception e) {
Slog.e(TAG, "" , e);
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d21212f..78f17bc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -34,6 +34,7 @@ import dalvik.system.Zygote;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.AlertDialog;
import android.app.AppGlobals;
@@ -151,6 +152,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -1079,7 +1081,8 @@ public final class ActivityManagerService extends ActivityManagerNative
int uid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart, false, true, false);
+ forceStopPackageLocked(pkg, uid, restart, false, true, false,
+ UserId.getUserId(uid));
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -1289,7 +1292,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ApplicationInfo info =
mSelf.mContext.getPackageManager().getApplicationInfo(
- "android", STOCK_PM_FLAGS);
+ "android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
synchronized (mSelf) {
@@ -2352,10 +2355,12 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
if (r == null) {
+ ActivityOptions.abort(options);
return false;
}
if (r.app == null || r.app.thread == null) {
// The caller is not running... d'oh!
+ ActivityOptions.abort(options);
return false;
}
intent = new Intent(intent);
@@ -2369,7 +2374,8 @@ public final class ActivityManagerService extends ActivityManagerNative
List<ResolveInfo> resolves =
AppGlobals.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
+ PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
+ UserId.getCallingUserId());
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
@@ -2391,6 +2397,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (aInfo == null) {
// Nobody who is next!
+ ActivityOptions.abort(options);
return false;
}
@@ -2420,8 +2427,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final long origId = Binder.clearCallingIdentity();
- // XXX we are not dealing with propagating grantedUriPermissions...
- // those are not yet exposed to user code, so there is no need.
int res = mMainStack.startActivityLocked(r.app.thread, intent,
r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
resultWho, requestCode, -1, r.launchedFromUid, 0,
@@ -3034,7 +3039,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
- if (IS_USER_BUILD) {
+ if (true || IS_USER_BUILD) {
return;
}
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
@@ -3291,7 +3296,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3312,7 +3317,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
//clear application user data
- pm.clearApplicationUserData(packageName, observer);
+ pm.clearApplicationUserData(packageName, observer, userId);
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
@@ -3339,13 +3344,14 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
+ int userId = UserId.getCallingUserId();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3412,16 +3418,14 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- final int userId = Binder.getOrigCallingUser();
+ final int userId = UserId.getCallingUserId();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName);
- // Convert the uid to the one for the calling user
- pkgUid = UserId.getUid(userId, pkgUid);
+ pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -3430,7 +3434,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
forceStopPackageLocked(packageName, pkgUid);
try {
- pm.setPackageStoppedState(packageName, true);
+ pm.setPackageStoppedState(packageName, true, userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -3545,7 +3549,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private void forceStopPackageLocked(final String packageName, int uid) {
- forceStopPackageLocked(packageName, uid, false, false, true, false);
+ forceStopPackageLocked(packageName, uid, false, false, true, false, UserId.getUserId(uid));
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
@@ -3579,9 +3583,14 @@ public final class ActivityManagerService extends ActivityManagerNative
if (doit) {
procs.add(app);
}
- } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
- || app.processName.equals(packageName)
- || app.processName.startsWith(procNamePrefix)) {
+ // If uid is specified and the uid and process name match
+ // Or, the uid is not specified and the process name matches
+ } else if (((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
+ && (app.processName.equals(packageName)
+ || app.processName.startsWith(procNamePrefix)))
+ || (uid < 0
+ && (app.processName.equals(packageName)
+ || app.processName.startsWith(procNamePrefix)))) {
if (app.setAdj >= minOomAdj) {
if (!doit) {
return true;
@@ -3602,13 +3611,13 @@ public final class ActivityManagerService extends ActivityManagerNative
private final boolean forceStopPackageLocked(String name, int uid,
boolean callerWillRestart, boolean purgeCache, boolean doit,
- boolean evenPersistent) {
+ boolean evenPersistent, int userId) {
int i;
int N;
if (uid < 0) {
try {
- uid = AppGlobals.getPackageManager().getPackageUid(name);
+ uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
} catch (RemoteException e) {
}
}
@@ -3632,7 +3641,8 @@ public final class ActivityManagerService extends ActivityManagerNative
for (i=0; i<mMainStack.mHistory.size(); i++) {
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
final boolean samePackage = r.packageName.equals(name);
- if ((samePackage || r.task == lastTask)
+ if (r.userId == userId
+ && (samePackage || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (!doit) {
if (r.finishing) {
@@ -3652,14 +3662,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
lastTask = r.task;
if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
- null, "force-stop")) {
+ null, "force-stop", true)) {
i--;
}
}
}
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- int userId = UserId.getUserId(uid);
for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
if (service.packageName.equals(name)
&& (service.app == null || evenPersistent || !service.app.persistent)) {
@@ -3683,7 +3692,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
- for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(-1).values()) {
+ for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) {
if (provider.info.packageName.equals(name)
&& (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
if (!doit) {
@@ -4107,16 +4116,25 @@ public final class ActivityManagerService extends ActivityManagerNative
if (pkgs != null) {
for (String pkg : pkgs) {
synchronized (ActivityManagerService.this) {
- if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
- setResultCode(Activity.RESULT_OK);
- return;
- }
- }
+ if (forceStopPackageLocked(pkg, -1, false, false, false, false, 0)) {
+ setResultCode(Activity.RESULT_OK);
+ return;
+ }
+ }
}
}
}
}, pkgFilter);
-
+
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onUserRemoved(intent);
+ }
+ }, userFilter);
+
synchronized (this) {
// Ensure that any processes we had put on hold are now started
// up.
@@ -4290,8 +4308,8 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
int uid = AppGlobals.getPackageManager()
- .getPackageUid(packageName);
- if (UserId.getAppId(callingUid) != uid) {
+ .getPackageUid(packageName, UserId.getUserId(callingUid));
+ if (!UserId.isSameApp(callingUid, uid)) {
String msg = "Permission Denial: getIntentSender() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
@@ -4386,7 +4404,7 @@ public final class ActivityManagerService extends ActivityManagerNative
PendingIntentRecord rec = (PendingIntentRecord)sender;
try {
int uid = AppGlobals.getPackageManager()
- .getPackageUid(rec.key.packageName);
+ .getPackageUid(rec.key.packageName, UserId.getCallingUserId());
if (!UserId.isSameApp(uid, Binder.getCallingUid())) {
String msg = "Permission Denial: cancelIntentSender() from pid="
+ Binder.getCallingPid()
@@ -4796,7 +4814,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
try {
pi = pm.resolveContentProvider(name,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, UserId.getUserId(callingUid));
} catch (RemoteException ex) {
}
}
@@ -4808,7 +4826,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int targetUid = lastTargetUid;
if (targetUid < 0 && targetPkg != null) {
try {
- targetUid = pm.getPackageUid(targetPkg);
+ targetUid = pm.getPackageUid(targetPkg, UserId.getUserId(callingUid));
if (targetUid < 0) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Can't grant URI permission no uid for: " + targetPkg);
@@ -5100,14 +5118,14 @@ public final class ActivityManagerService extends ActivityManagerNative
final String authority = uri.getAuthority();
ProviderInfo pi = null;
- ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
- UserId.getUserId(callingUid));
+ int userId = UserId.getUserId(callingUid);
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
if (cpr != null) {
pi = cpr.info;
} else {
try {
pi = pm.resolveContentProvider(authority,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
} catch (RemoteException ex) {
}
}
@@ -5202,7 +5220,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
try {
pi = pm.resolveContentProvider(authority,
- PackageManager.GET_URI_PERMISSION_PATTERNS);
+ PackageManager.GET_URI_PERMISSION_PATTERNS, r.userId);
} catch (RemoteException ex) {
}
}
@@ -5480,12 +5498,13 @@ public final class ActivityManagerService extends ActivityManagerNative
// Check whether this activity is currently available.
try {
if (rti.origActivity != null) {
- if (pm.getActivityInfo(rti.origActivity, 0) == null) {
+ if (pm.getActivityInfo(rti.origActivity, 0, callingUserId)
+ == null) {
continue;
}
} else if (rti.baseIntent != null) {
if (pm.queryIntentActivities(rti.baseIntent,
- null, 0) == null) {
+ null, 0, callingUserId) == null) {
continue;
}
}
@@ -5685,13 +5704,14 @@ public final class ActivityManagerService extends ActivityManagerNative
/**
* TODO: Add mController hook
*/
- public void moveTaskToFront(int task, int flags) {
+ public void moveTaskToFront(int task, int flags, Bundle options) {
enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
"moveTaskToFront()");
synchronized(this) {
if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
Binder.getCallingUid(), "Task to front")) {
+ ActivityOptions.abort(options);
return;
}
final long origId = Binder.clearCallingIdentity();
@@ -5706,7 +5726,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// we'll just move the home task to the top first.
mMainStack.moveHomeToFrontLocked();
}
- mMainStack.moveTaskToFrontLocked(tr, null);
+ mMainStack.moveTaskToFrontLocked(tr, null, options);
return;
}
for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
@@ -5720,13 +5740,14 @@ public final class ActivityManagerService extends ActivityManagerNative
// we'll just move the home task to the top first.
mMainStack.moveHomeToFrontLocked();
}
- mMainStack.moveTaskToFrontLocked(hr.task, null);
+ mMainStack.moveTaskToFrontLocked(hr.task, null, options);
return;
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
+ ActivityOptions.abort(options);
}
}
@@ -6132,15 +6153,14 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
- STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
+ STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
} catch (RemoteException ex) {
}
if (cpi == null) {
return null;
}
- cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo,
- Binder.getOrigCallingUser());
+ cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
String msg;
if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
@@ -6157,7 +6177,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- cpr = mProviderMap.getProviderByClass(comp, Binder.getOrigCallingUser());
+ cpr = mProviderMap.getProviderByClass(comp, userId);
final boolean firstClass = cpr == null;
if (firstClass) {
try {
@@ -6165,13 +6185,13 @@ public final class ActivityManagerService extends ActivityManagerNative
AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
- STOCK_PM_FLAGS);
+ STOCK_PM_FLAGS, userId);
if (ai == null) {
Slog.w(TAG, "No package info for content provider "
+ cpi.name);
return null;
}
- ai = getAppInfoForUser(ai, Binder.getOrigCallingUser());
+ ai = getAppInfoForUser(ai, userId);
cpr = new ContentProviderRecord(this, cpi, ai, comp);
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
@@ -6212,7 +6232,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Content provider is now in use, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- cpr.appInfo.packageName, false);
+ cpr.appInfo.packageName, false, userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -6546,7 +6566,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// This package really, really can not be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- info.packageName, false);
+ info.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -6778,7 +6798,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false, false, true, true);
+ forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
Binder.restoreCallingIdentity(origId);
}
}
@@ -6993,7 +7013,43 @@ public final class ActivityManagerService extends ActivityManagerNative
}
return killed;
}
-
+
+ @Override
+ public boolean killProcessesBelowForeground(String reason) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("killProcessesBelowForeground() only available to system");
+ }
+
+ return killProcessesBelowAdj(ProcessList.FOREGROUND_APP_ADJ, reason);
+ }
+
+ private boolean killProcessesBelowAdj(int belowAdj, String reason) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("killProcessesBelowAdj() only available to system");
+ }
+
+ boolean killed = false;
+ synchronized (mPidsSelfLocked) {
+ final int size = mPidsSelfLocked.size();
+ for (int i = 0; i < size; i++) {
+ final int pid = mPidsSelfLocked.keyAt(i);
+ final ProcessRecord proc = mPidsSelfLocked.valueAt(i);
+ if (proc == null) continue;
+
+ final int adj = proc.setAdj;
+ if (adj > belowAdj && !proc.killedBackground) {
+ Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
+ EventLog.writeEvent(
+ EventLogTags.AM_KILL, proc.pid, proc.processName, adj, reason);
+ killed = true;
+ proc.killedBackground = true;
+ Process.killProcessQuiet(pid);
+ }
+ }
+ }
+ return killed;
+ }
+
public final void startRunning(String pkg, String cls, String action,
String data) {
synchronized(this) {
@@ -7137,7 +7193,7 @@ public final class ActivityManagerService extends ActivityManagerNative
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0);
+ intent, null, 0, 0);
} catch (RemoteException e) {
}
if (ris != null) {
@@ -7394,6 +7450,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private boolean handleAppCrashLocked(ProcessRecord app) {
+ if (mHeadless) {
+ Log.e(TAG, "handleAppCrashLocked: " + app.processName);
+ return false;
+ }
long now = SystemClock.uptimeMillis();
Long crashTime;
@@ -7441,7 +7501,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mMainStack.resumeTopActivityLocked(null);
} else {
ActivityRecord r = mMainStack.topRunningActivityLocked(null);
- if (r.app == app) {
+ if (r != null && r.app == app) {
// If the top running activity is from this crashing
// process, then terminate it to avoid getting in a loop.
Slog.w(TAG, " Force finishing activity "
@@ -7803,7 +7863,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (String pkg : process.pkgList) {
sb.append("Package: ").append(pkg);
try {
- PackageInfo pi = pm.getPackageInfo(pkg, 0);
+ PackageInfo pi = pm.getPackageInfo(pkg, 0, 0);
if (pi != null) {
sb.append(" v").append(pi.versionCode);
if (pi.versionName != null) {
@@ -8201,7 +8261,7 @@ public final class ActivityManagerService extends ActivityManagerNative
IPackageManager pm = AppGlobals.getPackageManager();
for (String pkg : extList) {
try {
- ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
+ ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserId.getCallingUserId());
if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
retList.add(info);
}
@@ -10682,21 +10742,21 @@ public final class ActivityManagerService extends ActivityManagerNative
};
private ServiceLookupResult findServiceLocked(Intent service,
- String resolvedType) {
+ String resolvedType, int userId) {
ServiceRecord r = null;
if (service.getComponent() != null) {
- r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
+ r = mServiceMap.getServiceByName(service.getComponent(), userId);
}
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
- r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
+ r = mServiceMap.getServiceByIntent(filter, userId);
}
if (r == null) {
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
- service, resolvedType, 0);
+ service, resolvedType, 0, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -10767,7 +10827,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
- service, resolvedType, STOCK_PM_FLAGS);
+ service, resolvedType, STOCK_PM_FLAGS, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -11132,7 +11192,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Service is now being launched, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- r.packageName, false);
+ r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -11437,7 +11497,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = findServiceLocked(service, resolvedType);
+ ServiceLookupResult r = findServiceLocked(service, resolvedType,
+ callerApp == null ? UserId.getCallingUserId() : callerApp.userId);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
@@ -11465,7 +11526,8 @@ public final class ActivityManagerService extends ActivityManagerNative
IBinder ret = null;
synchronized(this) {
- ServiceLookupResult r = findServiceLocked(service, resolvedType);
+ ServiceLookupResult r = findServiceLocked(service, resolvedType,
+ UserId.getCallingUserId());
if (r != null) {
// r.record is null if findServiceLocked() failed the caller permission check
@@ -12094,7 +12156,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Backup agent is now in use, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- app.packageName, false);
+ app.packageName, false, UserId.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -12423,7 +12485,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST_LIGHT) Slog.v(
TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
- + " ordered=" + ordered);
+ + " ordered=" + ordered + " userid=" + userId);
if ((resultTo != null) && !ordered) {
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
@@ -12458,7 +12520,7 @@ public final class ActivityManagerService extends ActivityManagerNative
String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && (list.length > 0)) {
for (String pkg : list) {
- forceStopPackageLocked(pkg, -1, false, true, true, false);
+ forceStopPackageLocked(pkg, -1, false, true, true, false, userId);
}
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
@@ -12469,7 +12531,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp,
- intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
+ intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true,
+ false, userId);
}
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
@@ -12586,7 +12649,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (intent.getComponent() != null) {
// Broadcast is going to one specific receiver class...
ActivityInfo ai = AppGlobals.getPackageManager().
- getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
+ getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS, userId);
if (ai != null) {
receivers = new ArrayList();
ResolveInfo ri = new ResolveInfo();
@@ -12594,15 +12657,15 @@ public final class ActivityManagerService extends ActivityManagerNative
receivers.add(ri);
}
} else {
- // TODO: Apply userId
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers =
AppGlobals.getPackageManager().queryIntentReceivers(
- intent, resolvedType, STOCK_PM_FLAGS);
+ intent, resolvedType, STOCK_PM_FLAGS, userId);
}
- registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
+ registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false,
+ userId);
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
@@ -12893,7 +12956,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ii = mContext.getPackageManager().getInstrumentationInfo(
className, STOCK_PM_FLAGS);
ai = mContext.getPackageManager().getApplicationInfo(
- ii.targetPackage, STOCK_PM_FLAGS);
+ ii.targetPackage, STOCK_PM_FLAGS);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
@@ -12921,9 +12984,10 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
+ int userId = UserId.getCallingUserId();
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
- forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
+ forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
ProcessRecord app = addAppLocked(ai, false);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
@@ -12978,11 +13042,12 @@ public final class ActivityManagerService extends ActivityManagerNative
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
- forceStopPackageLocked(app.processName, -1, false, false, true, true);
+ forceStopPackageLocked(app.processName, -1, false, false, true, true, app.userId);
}
public void finishInstrumentation(IApplicationThread target,
int resultCode, Bundle results) {
+ int userId = UserId.getCallingUserId();
// Refuse possible leaked file descriptors
if (results != null && results.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -14544,25 +14609,6 @@ public final class ActivityManagerService extends ActivityManagerNative
private int mCurrentUserId;
private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
- private ArrayList<UserListener> mUserListeners = new ArrayList<UserListener>(3);
-
- public interface UserListener {
- public void onUserChanged(int userId);
-
- public void onUserAdded(int userId);
-
- public void onUserRemoved(int userId);
-
- public void onUserLoggedOut(int userId);
- }
-
- public void addUserListener(UserListener listener) {
- synchronized (this) {
- if (!mUserListeners.contains(listener)) {
- mUserListeners.add(listener);
- }
- }
- }
public boolean switchUser(int userId) {
final int callingUid = Binder.getCallingUid();
@@ -14573,8 +14619,6 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mCurrentUserId == userId)
return true;
- ArrayList<UserListener> listeners;
-
synchronized (this) {
// Check if user is already logged in, otherwise check if user exists first before
// adding to the list of logged in users.
@@ -14591,23 +14635,44 @@ public final class ActivityManagerService extends ActivityManagerNative
startHomeActivityLocked(userId);
}
- listeners = (ArrayList<UserListener>) mUserListeners.clone();
- }
- // Inform the listeners
- for (UserListener listener : listeners) {
- listener.onUserChanged(userId);
}
+
+ // Inform of user switch
+ Intent addedIntent = new Intent(Intent.ACTION_USER_SWITCHED);
+ addedIntent.putExtra(Intent.EXTRA_USERID, userId);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+
return true;
}
- private boolean userExists(int userId) {
- try {
- List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
- for (UserInfo user : users) {
- if (user.id == userId) {
- return true;
+ private void onUserRemoved(Intent intent) {
+ int extraUserId = intent.getIntExtra(Intent.EXTRA_USERID, -1);
+ if (extraUserId < 1) return;
+
+ // Kill all the processes for the user
+ ArrayList<Pair<String, Integer>> pkgAndUids = new ArrayList<Pair<String,Integer>>();
+ synchronized (this) {
+ HashMap<String,SparseArray<ProcessRecord>> map = mProcessNames.getMap();
+ for (Entry<String, SparseArray<ProcessRecord>> uidMap : map.entrySet()) {
+ SparseArray<ProcessRecord> uids = uidMap.getValue();
+ for (int i = 0; i < uids.size(); i++) {
+ if (UserId.getUserId(uids.keyAt(i)) == extraUserId) {
+ pkgAndUids.add(new Pair<String,Integer>(uidMap.getKey(), uids.keyAt(i)));
+ }
}
}
+
+ for (Pair<String,Integer> pkgAndUid : pkgAndUids) {
+ forceStopPackageLocked(pkgAndUid.first, pkgAndUid.second,
+ false, false, true, true, extraUserId);
+ }
+ }
+ }
+
+ private boolean userExists(int userId) {
+ try {
+ UserInfo user = AppGlobals.getPackageManager().getUser(userId);
+ return user != null;
} catch (RemoteException re) {
// Won't happen, in same process
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 53cb2b0..d60ff2b 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -26,7 +26,6 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Build;
@@ -542,24 +541,38 @@ final class ActivityRecord {
void updateOptionsLocked(Bundle options) {
if (options != null) {
+ if (pendingOptions != null) {
+ pendingOptions.abort();
+ }
pendingOptions = new ActivityOptions(options);
}
}
void applyOptionsLocked() {
if (pendingOptions != null) {
- if (pendingOptions.isCustomAnimation()) {
- service.mWindowManager.overridePendingAppTransition(
- pendingOptions.getPackageName(),
- pendingOptions.getCustomEnterResId(),
- pendingOptions.getCustomExitResId());
+ switch (pendingOptions.getAnimationType()) {
+ case ActivityOptions.ANIM_CUSTOM:
+ service.mWindowManager.overridePendingAppTransition(
+ pendingOptions.getPackageName(),
+ pendingOptions.getCustomEnterResId(),
+ pendingOptions.getCustomExitResId());
+ break;
+ case ActivityOptions.ANIM_THUMBNAIL:
+ service.mWindowManager.overridePendingAppTransitionThumb(
+ pendingOptions.getThumbnail(),
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getOnAnimationStartListener());
+ break;
}
pendingOptions = null;
}
}
void clearOptionsLocked() {
- pendingOptions = null;
+ if (pendingOptions != null) {
+ pendingOptions.abort();
+ pendingOptions = null;
+ }
}
void removeUriPermissionsLocked() {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 7e8df35..a01ed25 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1445,9 +1445,8 @@ final class ActivityStack {
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
- // TODO: Apply to the correct userId
AppGlobals.getPackageManager().setPackageStoppedState(
- next.packageName, false);
+ next.packageName, false, next.userId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -1696,6 +1695,7 @@ final class ActivityStack {
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
+ ActivityOptions.abort(options);
return;
}
break;
@@ -1798,6 +1798,7 @@ final class ActivityStack {
// because there is nothing for it to animate on top of.
mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen);
+ ActivityOptions.abort(options);
}
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
@@ -2345,6 +2346,7 @@ final class ActivityStack {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
if (requestCode >= 0) {
+ ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
@@ -2376,6 +2378,7 @@ final class ActivityStack {
Activity.RESULT_CANCELED, null);
}
mDismissKeyguardOnNextActivity = false;
+ ActivityOptions.abort(options);
return err;
}
@@ -2426,6 +2429,7 @@ final class ActivityStack {
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
mDismissKeyguardOnNextActivity = false;
+ ActivityOptions.abort(options);
return ActivityManager.START_SUCCESS;
}
}
@@ -2448,6 +2452,7 @@ final class ActivityStack {
pal.startFlags = startFlags;
mService.mPendingActivityLaunches.add(pal);
mDismissKeyguardOnNextActivity = false;
+ ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
@@ -2602,8 +2607,7 @@ final class ActivityStack {
// We really do want to push this one into the
// user's face, right now.
moveHomeToFrontFromLaunchLocked(launchFlags);
- r.updateOptionsLocked(options);
- moveTaskToFrontLocked(taskTop.task, r);
+ moveTaskToFrontLocked(taskTop.task, r, options);
}
}
// If the caller has requested that the target task be
@@ -2619,6 +2623,7 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
+ ActivityOptions.abort(options);
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags &
@@ -2706,6 +2711,7 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
+ ActivityOptions.abort(options);
return ActivityManager.START_TASK_TO_FRONT;
}
}
@@ -2735,6 +2741,7 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
+ ActivityOptions.abort(options);
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and
// the client said not to do anything if that
@@ -2754,6 +2761,7 @@ final class ActivityStack {
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
}
+ ActivityOptions.abort(options);
return ActivityManager.START_CLASS_NOT_FOUND;
}
@@ -2795,6 +2803,7 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
+ ActivityOptions.abort(options);
return ActivityManager.START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
@@ -2847,7 +2856,7 @@ final class ActivityStack {
}
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
- String profileFile, ParcelFileDescriptor profileFd) {
+ String profileFile, ParcelFileDescriptor profileFd, int userId) {
// Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
@@ -2855,7 +2864,7 @@ final class ActivityStack {
AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS);
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
@@ -2909,7 +2918,7 @@ final class ActivityStack {
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
- profileFile, profileFd);
+ profileFile, profileFd, userId);
aInfo = mService.getActivityInfoForUser(aInfo, userId);
synchronized (mService) {
@@ -2949,6 +2958,7 @@ final class ActivityStack {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + realCallingPid + ") when starting: "
+ intent.toString());
+ ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
@@ -2989,7 +2999,7 @@ final class ActivityStack {
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS);
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
@@ -3098,7 +3108,7 @@ final class ActivityStack {
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
- 0, null, null);
+ 0, null, null, userId);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -3481,6 +3491,15 @@ final class ActivityStack {
*/
final boolean finishActivityLocked(ActivityRecord r, int index,
int resultCode, Intent resultData, String reason) {
+ return finishActivityLocked(r, index, resultCode, resultData, reason, false);
+ }
+
+ /**
+ * @return Returns true if this activity has been removed from the history
+ * list, or false if it is still in the list and will be removed later.
+ */
+ final boolean finishActivityLocked(ActivityRecord r, int index,
+ int resultCode, Intent resultData, String reason, boolean immediate) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
@@ -3522,7 +3541,10 @@ final class ActivityStack {
mService.mCancelledThumbnails.add(r);
}
- if (mResumedActivity == r) {
+ if (immediate) {
+ return finishCurrentActivityLocked(r, index,
+ FINISH_IMMEDIATELY) == null;
+ } else if (mResumedActivity == r) {
boolean endTask = index <= 0
|| (mHistory.get(index-1)).task != r.task;
if (DEBUG_TRANSITION) Slog.v(TAG,
@@ -3888,12 +3910,12 @@ final class ActivityStack {
}
}
if (homeTask != null) {
- moveTaskToFrontLocked(homeTask, null);
+ moveTaskToFrontLocked(homeTask, null, null);
}
}
- final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason) {
+ final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int task = tr.taskId;
@@ -3901,6 +3923,7 @@ final class ActivityStack {
if (top < 0 || (mHistory.get(top)).task.taskId == task) {
// nothing to do!
+ ActivityOptions.abort(options);
return;
}
@@ -3942,7 +3965,16 @@ final class ActivityStack {
if (r != null) {
mNoAnimActivities.add(r);
}
+ ActivityOptions.abort(options);
} else {
+ if (options != null) {
+ ActivityRecord r = topRunningActivityLocked(null);
+ if (r != null && r.state != ActivityState.RESUMED) {
+ r.updateOptionsLocked(options);
+ } else {
+ ActivityOptions.abort(options);
+ }
+ }
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, false);
}
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 39b63db..1b83e0b 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -732,7 +732,7 @@ public class BroadcastQueue {
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- r.curComponent.getPackageName(), false);
+ r.curComponent.getPackageName(), false, UserId.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index cd72202..3ba3fbb 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -121,7 +121,7 @@ public class CompatModePackages {
public void handlePackageAddedLocked(String packageName, boolean updated) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -220,7 +220,7 @@ public class CompatModePackages {
public int getPackageScreenCompatModeLocked(String packageName) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -232,7 +232,7 @@ public class CompatModePackages {
public void setPackageScreenCompatModeLocked(String packageName, int mode) {
ApplicationInfo ai = null;
try {
- ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+ ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
@@ -365,7 +365,7 @@ public class CompatModePackages {
}
ApplicationInfo ai = null;
try {
- ai = pm.getApplicationInfo(pkg, 0);
+ ai = pm.getApplicationInfo(pkg, 0, 0);
} catch (RemoteException e) {
}
if (ai == null) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 2ad24e2..1f1e720 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -41,7 +41,6 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.dumpPolicy;
import static android.net.NetworkPolicyManager.dumpRules;
-import static android.net.NetworkPolicyManager.isUidValidForPolicy;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
@@ -74,6 +73,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -96,6 +96,7 @@ import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.UserId;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
@@ -157,6 +158,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int VERSION_ADDED_METERED = 4;
private static final int VERSION_SPLIT_SNOOZE = 5;
private static final int VERSION_ADDED_TIMEZONE = 6;
+ private static final int VERSION_ADDED_INFERRED = 7;
+ private static final int VERSION_SWITCH_APP_ID = 8;
// @VisibleForTesting
public static final int TYPE_WARNING = 0x1;
@@ -166,6 +169,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
private static final String TAG_UID_POLICY = "uid-policy";
+ private static final String TAG_APP_POLICY = "app-policy";
private static final String ATTR_VERSION = "version";
private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
@@ -179,7 +183,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
private static final String ATTR_METERED = "metered";
+ private static final String ATTR_INFERRED = "inferred";
private static final String ATTR_UID = "uid";
+ private static final String ATTR_APP_ID = "appId";
private static final String ATTR_POLICY = "policy";
private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
@@ -221,8 +227,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Currently active network rules for ifaces. */
private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
- /** Defined UID policies. */
- private SparseIntArray mUidPolicy = new SparseIntArray();
+ /** Defined app policies. */
+ private SparseIntArray mAppPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
private SparseIntArray mUidRules = new SparseIntArray();
@@ -377,18 +383,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final String action = intent.getAction();
final int uid = intent.getIntExtra(EXTRA_UID, 0);
+ final int appId = UserId.getAppId(uid);
synchronized (mRulesLock) {
if (ACTION_PACKAGE_ADDED.equals(action)) {
+ // NOTE: PACKAGE_ADDED is currently only sent once, and is
+ // not broadcast when users are added.
+
// update rules for UID, since it might be subject to
// global background data policy.
if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
- updateRulesForUidLocked(uid);
+ updateRulesForAppLocked(appId);
} else if (ACTION_UID_REMOVED.equals(action)) {
+ // NOTE: UID_REMOVED is currently only sent once, and is not
+ // broadcast when users are removed.
+
// remove any policy and update rules to clean up.
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
- mUidPolicy.delete(uid);
- updateRulesForUidLocked(uid);
+
+ mAppPolicy.delete(appId);
+ updateRulesForAppLocked(appId);
writePolicyLocked();
}
}
@@ -522,6 +536,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
+ // mobile templates aren't relevant in airplane mode
+ if (isAirplaneModeOn(mContext)) {
+ return false;
+ }
+
// mobile templates are relevant when subscriberid is active
return Objects.equal(getActiveSubscriberId(), template.getSubscriberId());
}
@@ -932,7 +951,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, cycleTimezone,
- warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true));
+ warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true));
writePolicyLocked();
}
}
@@ -942,7 +961,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// clear any existing policy and read from disk
mNetworkPolicy.clear();
- mUidPolicy.clear();
+ mAppPolicy.clear();
FileInputStream fis = null;
try {
@@ -1004,22 +1023,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} else {
lastWarningSnooze = SNOOZE_NEVER;
}
+ final boolean inferred;
+ if (version >= VERSION_ADDED_INFERRED) {
+ inferred = readBooleanAttribute(in, ATTR_INFERRED);
+ } else {
+ inferred = false;
+ }
final NetworkTemplate template = new NetworkTemplate(
networkTemplate, subscriberId);
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
- lastLimitSnooze, metered));
+ lastLimitSnooze, metered, inferred));
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
- if (isUidValidForPolicy(mContext, uid)) {
- setUidPolicyUnchecked(uid, policy, false);
+ final int appId = UserId.getAppId(uid);
+ if (UserId.isApp(appId)) {
+ setAppPolicyUnchecked(appId, policy, false);
} else {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
+ } else if (TAG_APP_POLICY.equals(tag)) {
+ final int appId = readIntAttribute(in, ATTR_APP_ID);
+ final int policy = readIntAttribute(in, ATTR_POLICY);
+
+ if (UserId.isApp(appId)) {
+ setAppPolicyUnchecked(appId, policy, false);
+ } else {
+ Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring");
+ }
}
}
}
@@ -1064,7 +1099,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
out.startDocument(null, true);
out.startTag(null, TAG_POLICY_LIST);
- writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_TIMEZONE);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_SWITCH_APP_ID);
writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
// write all known network policies
@@ -1084,21 +1119,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
writeBooleanAttribute(out, ATTR_METERED, policy.metered);
+ writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
out.endTag(null, TAG_NETWORK_POLICY);
}
// write all known uid policies
- for (int i = 0; i < mUidPolicy.size(); i++) {
- final int uid = mUidPolicy.keyAt(i);
- final int policy = mUidPolicy.valueAt(i);
+ for (int i = 0; i < mAppPolicy.size(); i++) {
+ final int appId = mAppPolicy.keyAt(i);
+ final int policy = mAppPolicy.valueAt(i);
// skip writing empty policies
if (policy == POLICY_NONE) continue;
- out.startTag(null, TAG_UID_POLICY);
- writeIntAttribute(out, ATTR_UID, uid);
+ out.startTag(null, TAG_APP_POLICY);
+ writeIntAttribute(out, ATTR_APP_ID, appId);
writeIntAttribute(out, ATTR_POLICY, policy);
- out.endTag(null, TAG_UID_POLICY);
+ out.endTag(null, TAG_APP_POLICY);
}
out.endTag(null, TAG_POLICY_LIST);
@@ -1113,24 +1149,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- public void setUidPolicy(int uid, int policy) {
+ public void setAppPolicy(int appId, int policy) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- if (!isUidValidForPolicy(mContext, uid)) {
- throw new IllegalArgumentException("cannot apply policy to UID " + uid);
+ if (!UserId.isApp(appId)) {
+ throw new IllegalArgumentException("cannot apply policy to appId " + appId);
}
- setUidPolicyUnchecked(uid, policy, true);
+ setAppPolicyUnchecked(appId, policy, true);
}
- private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
+ private void setAppPolicyUnchecked(int appId, int policy, boolean persist) {
final int oldPolicy;
synchronized (mRulesLock) {
- oldPolicy = getUidPolicy(uid);
- mUidPolicy.put(uid, policy);
+ oldPolicy = getAppPolicy(appId);
+ mAppPolicy.put(appId, policy);
// uid policy changed, recompute rules and persist policy.
- updateRulesForUidLocked(uid);
+ updateRulesForAppLocked(appId);
if (persist) {
writePolicyLocked();
}
@@ -1138,11 +1174,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- public int getUidPolicy(int uid) {
+ public int getAppPolicy(int appId) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
synchronized (mRulesLock) {
- return mUidPolicy.get(uid, POLICY_NONE);
+ return mAppPolicy.get(appId, POLICY_NONE);
}
}
@@ -1333,27 +1369,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.print(" "); fout.println(policy.toString());
}
- fout.println("Policy status for known UIDs:");
+ fout.println("Policy for apps:");
+ int size = mAppPolicy.size();
+ for (int i = 0; i < size; i++) {
+ final int appId = mAppPolicy.keyAt(i);
+ final int policy = mAppPolicy.valueAt(i);
+ fout.print(" appId=");
+ fout.print(appId);
+ fout.print(" policy=");
+ dumpPolicy(fout, policy);
+ fout.println();
+ }
final SparseBooleanArray knownUids = new SparseBooleanArray();
- collectKeys(mUidPolicy, knownUids);
collectKeys(mUidForeground, knownUids);
collectKeys(mUidRules, knownUids);
- final int size = knownUids.size();
+ fout.println("Status for known UIDs:");
+ size = knownUids.size();
for (int i = 0; i < size; i++) {
final int uid = knownUids.keyAt(i);
fout.print(" UID=");
fout.print(uid);
- fout.print(" policy=");
- final int policyIndex = mUidPolicy.indexOfKey(uid);
- if (policyIndex < 0) {
- fout.print("UNKNOWN");
- } else {
- dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
- }
-
fout.print(" foreground=");
final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
if (foregroundIndex < 0) {
@@ -1443,7 +1481,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final PackageManager pm = mContext.getPackageManager();
final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
for (ApplicationInfo app : apps) {
- updateRulesForUidLocked(app.uid);
+ final int appId = UserId.getAppId(app.uid);
+ updateRulesForAppLocked(appId);
}
// and catch system UIDs
@@ -1462,13 +1501,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void updateRulesForAppLocked(int appId) {
+ for (UserInfo user : mContext.getPackageManager().getUsers()) {
+ final int uid = UserId.getUid(user.id, appId);
+ updateRulesForUidLocked(uid);
+ }
+ }
+
private void updateRulesForUidLocked(int uid) {
- final int uidPolicy = getUidPolicy(uid);
+ final int appId = UserId.getAppId(uid);
+ final int appPolicy = getAppPolicy(appId);
final boolean uidForeground = isUidForeground(uid);
// derive active rules based on policy and active state
int uidRules = RULE_ALLOW_ALL;
- if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
+ if (!uidForeground && (appPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
// uid in background, and policy says to block metered data
uidRules = RULE_REJECT_METERED;
}
@@ -1714,6 +1761,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mHandler.getLooper().getQueue().addIdleHandler(handler);
}
+ public static boolean isAirplaneModeOn(Context context) {
+ return Settings.System.getInt(
+ context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
+ }
+
private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
final int size = source.size();
for (int i = 0; i < size; i++) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index bc98f86..1593707 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -134,6 +134,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -395,7 +396,7 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int MCS_GIVE_UP = 11;
static final int UPDATED_MEDIA_STATUS = 12;
static final int WRITE_SETTINGS = 13;
- static final int WRITE_STOPPED_PACKAGES = 14;
+ static final int WRITE_PACKAGE_RESTRICTIONS = 14;
static final int PACKAGE_VERIFIED = 15;
static final int CHECK_PENDING_VERIFICATION = 16;
@@ -404,7 +405,10 @@ public class PackageManagerService extends IPackageManager.Stub {
// Delay time in millisecs
static final int BROADCAST_DELAY = 10 * 1000;
- final UserManager mUserManager;
+ static UserManager sUserManager;
+
+ // Stores a list of users whose package restrictions file needs to be updated
+ private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
@@ -629,7 +633,7 @@ public class PackageManagerService extends IPackageManager.Stub {
packages[i] = ent.getKey();
components[i] = ent.getValue();
PackageSetting ps = mSettings.mPackages.get(ent.getKey());
- uids[i] = (ps != null) ? ps.userId : -1;
+ uids[i] = (ps != null) ? ps.appId : -1;
i++;
}
size = i;
@@ -673,14 +677,15 @@ public class PackageManagerService extends IPackageManager.Stub {
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
res.pkg.applicationInfo.packageName,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
res.pkg.applicationInfo.packageName,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null, null,
- res.pkg.applicationInfo.packageName, null);
+ res.pkg.applicationInfo.packageName, null,
+ UserId.USER_ALL);
}
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
@@ -735,16 +740,20 @@ public class PackageManagerService extends IPackageManager.Stub {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPackages) {
removeMessages(WRITE_SETTINGS);
- removeMessages(WRITE_STOPPED_PACKAGES);
+ removeMessages(WRITE_PACKAGE_RESTRICTIONS);
mSettings.writeLPr();
+ mDirtyUsers.clear();
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
- case WRITE_STOPPED_PACKAGES: {
+ case WRITE_PACKAGE_RESTRICTIONS: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPackages) {
- removeMessages(WRITE_STOPPED_PACKAGES);
- mSettings.writeStoppedLPr();
+ removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+ for (int userId : mDirtyUsers) {
+ mSettings.writePackageRestrictionsLPr(userId);
+ }
+ mDirtyUsers.clear();
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
@@ -811,10 +820,12 @@ public class PackageManagerService extends IPackageManager.Stub {
mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
}
}
-
- void scheduleWriteStoppedPackagesLocked() {
- if (!mHandler.hasMessages(WRITE_STOPPED_PACKAGES)) {
- mHandler.sendEmptyMessageDelayed(WRITE_STOPPED_PACKAGES, WRITE_SETTINGS_DELAY);
+
+ void scheduleWritePackageRestrictionsLocked(int userId) {
+ if (!sUserManager.exists(userId)) return;
+ mDirtyUsers.add(userId);
+ if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+ mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
}
}
@@ -912,11 +923,11 @@ public class PackageManagerService extends IPackageManager.Stub {
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
- mUserManager = new UserManager(mInstaller, mUserAppDataDir);
+ sUserManager = new UserManager(mInstaller, mUserAppDataDir);
readPermissions();
- mRestoredSettings = mSettings.readLPw();
+ mRestoredSettings = mSettings.readLPw(getUsers());
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1078,7 +1089,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " no longer exists; wiping its data";
reportSettingsProblem(Log.WARN, msg);
mInstaller.remove(ps.name, 0);
- mUserManager.removePackageForAllUsers(ps.name);
+ sUserManager.removePackageForAllUsers(ps.name);
}
}
}
@@ -1180,7 +1191,7 @@ public class PackageManagerService extends IPackageManager.Stub {
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);
+ PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
String requiredVerifier = null;
@@ -1234,7 +1245,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Couldn't remove app data directory for package: "
+ ps.name + ", retcode=" + retCode);
} else {
- mUserManager.removePackageForAllUsers(ps.name);
+ sUserManager.removePackageForAllUsers(ps.name);
}
if (ps.codePath != null) {
if (!ps.codePath.delete()) {
@@ -1498,31 +1509,42 @@ public class PackageManagerService extends IPackageManager.Stub {
return cur;
}
- PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
+ PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
+ PackageInfo pi;
if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
// The package has been uninstalled but has retained data and resources.
- return PackageParser.generatePackageInfo(p, null, flags, 0, 0, null);
- }
- final PackageSetting ps = (PackageSetting)p.mExtras;
- if (ps == null) {
- return null;
+ pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
+ } else {
+ final PackageSetting ps = (PackageSetting) p.mExtras;
+ if (ps == null) {
+ return null;
+ }
+ final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+ pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
+ ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
+ ps.getStopped(userId), ps.getEnabled(userId), userId);
+ pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
+ pi.applicationInfo.enabled =
+ pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
+ || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
}
- final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
- return PackageParser.generatePackageInfo(p, gp.gids, flags,
- ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions);
+ return pi;
}
- public PackageInfo getPackageInfo(String packageName, int flags) {
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if (DEBUG_PACKAGE_INFO)
Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
if (p != null) {
- return generatePackageInfo(p, flags);
+ return generatePackageInfo(p, flags, userId);
}
if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- return generatePackageInfoFromSettingsLPw(packageName, flags);
+ return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
}
}
return null;
@@ -1551,20 +1573,22 @@ public class PackageManagerService extends IPackageManager.Stub {
}
return out;
}
-
- public int getPackageUid(String packageName) {
+
+ @Override
+ public int getPackageUid(String packageName, int userId) {
+ if (!sUserManager.exists(userId)) return -1;
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if(p != null) {
- return p.applicationInfo.uid;
+ return UserId.getUid(userId, p.applicationInfo.uid);
}
PackageSetting ps = mSettings.mPackages.get(packageName);
if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
return -1;
}
p = ps.pkg;
- return p != null ? p.applicationInfo.uid : -1;
+ return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
}
}
@@ -1577,7 +1601,16 @@ public class PackageManagerService extends IPackageManager.Stub {
if (p != null) {
final PackageSetting ps = (PackageSetting)p.mExtras;
final SharedUserSetting suid = ps.sharedUser;
- return suid != null ? suid.gids : ps.gids;
+ int[] gids = suid != null ? suid.gids : ps.gids;
+
+ // include GIDs for any unenforced permissions
+ if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
+ final BasePermission basePerm = mSettings.mPermissions.get(
+ READ_EXTERNAL_STORAGE);
+ gids = appendInts(gids, basePerm.gids);
+ }
+
+ return gids;
}
}
// stupid thing to indicate an error.
@@ -1652,24 +1685,30 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags) {
+ private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
if (ps.pkg == null) {
- PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags);
+ PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
if (pInfo != null) {
return pInfo.applicationInfo;
}
return null;
}
- return PackageParser.generateApplicationInfo(ps.pkg, flags);
+ return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
return null;
}
- private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags) {
+ private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
+ PackageParser.Package pkg = new PackageParser.Package(packageName);
if (ps.pkg == null) {
ps.pkg = new PackageParser.Package(packageName);
ps.pkg.applicationInfo.packageName = packageName;
@@ -1679,15 +1718,17 @@ public class PackageManagerService extends IPackageManager.Stub {
ps.pkg.applicationInfo.dataDir =
getDataPathForPackage(ps.pkg.packageName, 0).getPath();
ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
- ps.pkg.mSetEnabled = ps.enabled;
- ps.pkg.mSetStopped = ps.stopped;
}
- return generatePackageInfo(ps.pkg, flags);
+ // ps.pkg.mSetEnabled = ps.getEnabled(userId);
+ // ps.pkg.mSetStopped = ps.getStopped(userId);
+ return generatePackageInfo(ps.pkg, flags, userId);
}
return null;
}
- public ApplicationInfo getApplicationInfo(String packageName, int flags) {
+ @Override
+ public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
// writer
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1695,14 +1736,17 @@ public class PackageManagerService extends IPackageManager.Stub {
TAG, "getApplicationInfo " + packageName
+ ": " + p);
if (p != null) {
+ PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null) return null;
// Note: isEnabledLP() does not apply here - always return info
- return PackageParser.generateApplicationInfo(p, flags);
+ return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
+ ps.getEnabled(userId));
}
if ("android".equals(packageName)||"system".equals(packageName)) {
return mAndroidApplication;
}
if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- return generateApplicationInfoFromSettingsLPw(packageName, flags);
+ return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
}
}
return null;
@@ -1758,17 +1802,18 @@ public class PackageManagerService extends IPackageManager.Stub {
});
}
- public ActivityInfo getActivityInfo(ComponentName component, int flags) {
- return getActivityInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
- return PackageParser.generateActivityInfo(a, flags, userId);
+ if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
+ PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ if (ps == null) return null;
+ return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
if (mResolveComponentName.equals(component)) {
return mResolveActivity;
@@ -1777,49 +1822,52 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
- public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
- return getReceiverInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
synchronized (mPackages) {
PackageParser.Activity a = mReceivers.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getReceiverInfo " + component + ": " + a);
- if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
- return PackageParser.generateActivityInfo(a, flags, userId);
+ if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
+ PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ if (ps == null) return null;
+ return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
}
return null;
}
- public ServiceInfo getServiceInfo(ComponentName component, int flags) {
- return getServiceInfo(component, flags, Binder.getOrigCallingUser());
- }
-
- ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
synchronized (mPackages) {
PackageParser.Service s = mServices.mServices.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getServiceInfo " + component + ": " + s);
- if (s != null && mSettings.isEnabledLPr(s.info, flags)) {
- return PackageParser.generateServiceInfo(s, flags, userId);
+ if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
+ PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ if (ps == null) return null;
+ return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
}
return null;
}
- public ProviderInfo getProviderInfo(ComponentName component, int flags) {
- return getProviderInfo(component, flags, UserId.getUserId(Binder.getCallingUid()));
- }
-
- ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
+ @Override
+ public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
synchronized (mPackages) {
PackageParser.Provider p = mProvidersByComponent.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getProviderInfo " + component + ": " + p);
- if (p != null && mSettings.isEnabledLPr(p.info, flags)) {
- return PackageParser.generateProviderInfo(p, flags, userId);
+ if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
+ PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ if (ps == null) return null;
+ return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
}
return null;
@@ -1863,6 +1911,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ private void checkValidCaller(int uid, int userId) {
+ if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
+ return;
+
+ throw new SecurityException("Caller uid=" + uid
+ + " is not privileged to communicate with user=" + userId);
+ }
+
public int checkPermission(String permName, String pkgName) {
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(pkgName);
@@ -1997,7 +2053,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!async) {
mSettings.writeLPr();
} else {
- scheduleWriteSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
return added;
@@ -2232,14 +2288,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags) {
- List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
- return chooseBestActivity(intent, resolvedType, flags, query);
+ int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
+ List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query) {
+ int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
@@ -2263,7 +2321,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
- flags, query, r0.priority);
+ flags, query, r0.priority, userId);
if (ri != null) {
return ri;
}
@@ -2274,7 +2332,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query, int priority) {
+ int flags, List<ResolveInfo> query, int priority, int userId) {
+ if (!sUserManager.exists(userId)) return null;
// writer
synchronized (mPackages) {
if (intent.getSelector() != null) {
@@ -2283,7 +2342,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
List<PreferredActivity> prefs =
mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
if (prefs != null && prefs.size() > 0) {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
@@ -2317,7 +2376,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pa.mPref.mMatch != match) {
continue;
}
- final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags);
+ final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
if (DEBUG_PREFERRED) {
Log.v(TAG, "Got preferred activity:");
if (ai != null) {
@@ -2367,8 +2426,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
+ @Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
- String resolvedType, int flags) {
+ String resolvedType, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2379,7 +2440,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- final ActivityInfo ai = getActivityInfo(comp, flags);
+ final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
@@ -2392,24 +2453,26 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
final String pkgName = intent.getPackage();
if (pkgName == null) {
- return mActivities.queryIntent(intent, resolvedType, flags);
+ return mActivities.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return mActivities.queryIntentForPackage(intent, resolvedType, flags,
- pkg.activities);
+ pkg.activities, userId);
}
return new ArrayList<ResolveInfo>();
}
}
+ @Override
public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
- String resolvedType, int flags) {
+ String resolvedType, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
final String resultsAction = intent.getAction();
List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
- | PackageManager.GET_RESOLVED_FILTER);
+ | PackageManager.GET_RESOLVED_FILTER, userId);
if (DEBUG_INTENT_MATCHING) {
Log.v(TAG, "Query " + intent + ": " + results);
@@ -2452,7 +2515,7 @@ public class PackageManagerService extends IPackageManager.Stub {
ri = resolveIntent(
sintent,
specificTypes != null ? specificTypes[i] : null,
- flags);
+ flags, userId);
if (ri == null) {
continue;
}
@@ -2463,7 +2526,7 @@ public class PackageManagerService extends IPackageManager.Stub {
comp = new ComponentName(ai.applicationInfo.packageName,
ai.name);
} else {
- ai = getActivityInfo(comp, flags);
+ ai = getActivityInfo(comp, flags, userId);
if (ai == null) {
continue;
}
@@ -2572,7 +2635,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return results;
}
- public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
+ @Override
+ public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2582,7 +2648,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (comp != null) {
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- ActivityInfo ai = getReceiverInfo(comp, flags);
+ ActivityInfo ai = getReceiverInfo(comp, flags, userId);
if (ai != null) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
@@ -2595,18 +2661,21 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mReceivers.queryIntent(intent, resolvedType, flags);
+ return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers);
+ return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
+ userId);
}
return null;
}
}
- public ResolveInfo resolveService(Intent intent, String resolvedType, int flags) {
- List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags);
+ @Override
+ public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
+ if (!sUserManager.exists(userId)) return null;
if (query != null) {
if (query.size() >= 1) {
// If there is more than one service with the same priority,
@@ -2617,7 +2686,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
- public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
+ @Override
+ public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -2627,7 +2699,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
- final ServiceInfo si = getServiceInfo(comp, flags);
+ final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
final ResolveInfo ri = new ResolveInfo();
ri.serviceInfo = si;
@@ -2640,11 +2712,12 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mServices.queryIntent(intent, resolvedType, flags);
+ return mServices.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services);
+ return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+ userId);
}
return null;
}
@@ -2669,6 +2742,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
final String[] keys;
+ int userId = UserId.getCallingUserId();
// writer
synchronized (mPackages) {
@@ -2689,12 +2763,12 @@ public class PackageManagerService extends IPackageManager.Stub {
if (listUninstalled) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- pi = generatePackageInfoFromSettingsLPw(ps.name, flags);
+ pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
}
} else {
final PackageParser.Package p = mPackages.get(packageName);
if (p != null) {
- pi = generatePackageInfo(p, flags);
+ pi = generatePackageInfo(p, flags, userId);
}
}
@@ -2711,8 +2785,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return list;
}
+ @Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
- String lastRead) {
+ String lastRead, int userId) {
+ if (!sUserManager.exists(userId)) return null;
final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
final String[] keys;
@@ -2728,21 +2804,21 @@ public class PackageManagerService extends IPackageManager.Stub {
Arrays.sort(keys);
int i = getContinuationPoint(keys, lastRead);
final int N = keys.length;
- final int userId = UserId.getUserId(Binder.getCallingUid());
while (i < N) {
final String packageName = keys[i++];
ApplicationInfo ai = null;
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
if (listUninstalled) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
+ ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
}
} else {
final PackageParser.Package p = mPackages.get(packageName);
- if (p != null) {
- ai = PackageParser.generateApplicationInfo(p, flags, userId);
+ if (p != null && ps != null) {
+ ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
+ ps.getEnabled(userId), userId);
}
}
@@ -2765,13 +2841,17 @@ public class PackageManagerService extends IPackageManager.Stub {
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Package> i = mPackages.values().iterator();
- final int userId = UserId.getUserId(Binder.getCallingUid());
+ final int userId = UserId.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Package p = i.next();
if (p.applicationInfo != null
&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))) {
- finalList.add(PackageParser.generateApplicationInfo(p, flags, userId));
+ PackageSetting ps = mSettings.mPackages.get(p.packageName);
+ finalList.add(PackageParser.generateApplicationInfo(p, flags,
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId));
}
}
}
@@ -2779,16 +2859,23 @@ public class PackageManagerService extends IPackageManager.Stub {
return finalList;
}
- public ProviderInfo resolveContentProvider(String name, int flags) {
+ @Override
+ public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return null;
// reader
synchronized (mPackages) {
final PackageParser.Provider provider = mProviders.get(name);
+ PackageSetting ps = provider != null
+ ? mSettings.mPackages.get(provider.owner.packageName)
+ : null;
return provider != null
- && mSettings.isEnabledLPr(provider.info, flags)
+ && mSettings.isEnabledLPr(provider.info, flags, userId)
&& (!mSafeMode || (provider.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)
? PackageParser.generateProviderInfo(provider, flags,
- UserId.getUserId(Binder.getCallingUid()))
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId)
: null;
}
}
@@ -2802,16 +2889,20 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
.iterator();
- final int userId = UserId.getUserId(Binder.getCallingUid());
+ final int userId = UserId.getCallingUserId();
while (i.hasNext()) {
Map.Entry<String, PackageParser.Provider> entry = i.next();
PackageParser.Provider p = entry.getValue();
+ PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
if (p.syncable
&& (!mSafeMode || (p.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)) {
outNames.add(entry.getKey());
- outInfo.add(PackageParser.generateProviderInfo(p, 0, userId));
+ outInfo.add(PackageParser.generateProviderInfo(p, 0,
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId));
}
}
}
@@ -2824,21 +2915,25 @@ public class PackageManagerService extends IPackageManager.Stub {
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
- final int userId = UserId.getUserId(Binder.getCallingUid());
+ final int userId = processName != null ?
+ UserId.getUserId(uid) : UserId.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Provider p = i.next();
+ PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
if (p.info.authority != null
&& (processName == null
|| (p.info.processName.equals(processName)
- && UserId.getAppId(p.info.applicationInfo.uid)
- == UserId.getAppId(uid)))
- && mSettings.isEnabledLPr(p.info, flags)
+ && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
+ && mSettings.isEnabledLPr(p.info, flags, userId)
&& (!mSafeMode
|| (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
if (finalList == null) {
finalList = new ArrayList<ProviderInfo>(3);
}
- finalList.add(PackageParser.generateProviderInfo(p, flags, userId));
+ finalList.add(PackageParser.generateProviderInfo(p, flags,
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId));
}
}
}
@@ -3482,7 +3577,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
- pkg.applicationInfo.uid = pkgSetting.userId;
+ pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
if (!verifySignaturesLP(pkgSetting, pkg)) {
@@ -3589,7 +3684,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (ret >= 0) {
// TODO: Kill the processes first
// Remove the data directories for all users
- mUserManager.removePackageForAllUsers(pkgName);
+ sUserManager.removePackageForAllUsers(pkgName);
// Old data gone!
String msg = "System package " + pkg.packageName
+ " has changed from uid: "
@@ -3610,7 +3705,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
// Create data directories for all users
- mUserManager.installPackageForAllUsers(pkgName,
+ sUserManager.installPackageForAllUsers(pkgName,
pkg.applicationInfo.uid);
}
if (!recovered) {
@@ -3652,7 +3747,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
// Create data directories for all users
- mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
+ sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
if (dataPath.exists()) {
pkg.applicationInfo.dataDir = dataPath.getPath();
@@ -4480,19 +4575,23 @@ public class PackageManagerService extends IPackageManager.Stub {
private final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly) {
+ boolean defaultOnly, int userId) {
+ if (!sUserManager.exists(userId)) return null;
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+ public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, ArrayList<PackageParser.Activity> packageActivities) {
+ int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
+ if (!sUserManager.exists(userId)) return null;
if (packageActivities == null) {
return null;
}
@@ -4509,7 +4608,7 @@ public class PackageManagerService extends IPackageManager.Stub {
listCut.add(intentFilters);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
public final void addActivity(PackageParser.Activity a, String type) {
@@ -4574,7 +4673,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter) {
+ protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
+ if (!sUserManager.exists(userId)) return true;
PackageParser.Package p = filter.activity.owner;
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4582,7 +4682,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// 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 ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4595,8 +4695,9 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
- int match) {
- if (!mSettings.isEnabledLPr(info.activity.info, mFlags)) {
+ int match, int userId) {
+ if (!sUserManager.exists(userId)) return null;
+ if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
return null;
}
final PackageParser.Activity activity = info.activity;
@@ -4605,8 +4706,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
final ResolveInfo res = new ResolveInfo();
+ PackageSetting ps = (PackageSetting) activity.owner.mExtras;
res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
- Binder.getOrigCallingUser());
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId);
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = info;
}
@@ -4660,19 +4764,22 @@ public class PackageManagerService extends IPackageManager.Stub {
private final class ServiceIntentResolver
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly) {
+ boolean defaultOnly, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
- public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+ public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+ int userId) {
+ if (!sUserManager.exists(userId)) return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
- int flags, ArrayList<PackageParser.Service> packageServices) {
+ int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
+ if (!sUserManager.exists(userId)) return null;
if (packageServices == null) {
return null;
}
@@ -4689,7 +4796,7 @@ public class PackageManagerService extends IPackageManager.Stub {
listCut.add(intentFilters);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
public final void addService(PackageParser.Service s) {
@@ -4749,7 +4856,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter) {
+ protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
+ if (!sUserManager.exists(userId)) return true;
PackageParser.Package p = filter.service.owner;
if (p != null) {
PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4757,7 +4865,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// 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 ps.getStopped(userId)
+ && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
}
}
return false;
@@ -4770,9 +4879,10 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
- int match) {
+ int match, int userId) {
+ if (!sUserManager.exists(userId)) return null;
final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
- if (!mSettings.isEnabledLPr(info.service.info, mFlags)) {
+ if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
return null;
}
final PackageParser.Service service = info.service;
@@ -4781,8 +4891,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
final ResolveInfo res = new ResolveInfo();
+ PackageSetting ps = (PackageSetting) service.owner.mExtras;
res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
- Binder.getOrigCallingUser());
+ ps != null ? ps.getStopped(userId) : false,
+ ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
+ userId);
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = filter;
}
@@ -4873,23 +4986,32 @@ public class PackageManagerService extends IPackageManager.Stub {
};
static final void sendPackageBroadcast(String action, String pkg,
- Bundle extras, String targetPkg, IIntentReceiver finishedReceiver) {
+ Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- final Intent intent = new Intent(action,
- pkg != null ? Uri.fromParts("package", pkg, null) : null);
- if (extras != null) {
- intent.putExtras(extras);
- }
- if (targetPkg != null) {
- intent.setPackage(targetPkg);
- }
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- // TODO: Fix the userId argument
- am.broadcastIntent(null, intent, null, finishedReceiver,
- 0, null, null, null, finishedReceiver != null, false,
- Binder.getOrigCallingUser());
+ int[] userIds = userId == UserId.USER_ALL
+ ? sUserManager.getUserIds()
+ : new int[] {userId};
+ for (int id : userIds) {
+ final Intent intent = new Intent(action,
+ pkg != null ? Uri.fromParts("package", pkg, null) : null);
+ if (extras != null) {
+ intent.putExtras(extras);
+ }
+ if (targetPkg != null) {
+ intent.setPackage(targetPkg);
+ }
+ // Modify the UID when posting to other users
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ if (uid > 0 && id > 0) {
+ uid = UserId.getUid(id, UserId.getAppId(uid));
+ intent.putExtra(Intent.EXTRA_UID, uid);
+ }
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ am.broadcastIntent(null, intent, null, finishedReceiver,
+ 0, null, null, null, finishedReceiver != null, false, id);
+ }
} catch (RemoteException ex) {
}
}
@@ -5032,13 +5154,13 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putInt(Intent.EXTRA_UID, removedUid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, addedUid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
}
}
@@ -5635,14 +5757,14 @@ public class PackageManagerService extends IPackageManager.Stub {
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage);
+ : getPackageUid(mRequiredVerifierPackage, 0);
if (requiredUid != -1 && isVerificationEnabled()) {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
- PackageManager.GET_DISABLED_COMPONENTS);
+ PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
if (DEBUG_VERIFY) {
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -7062,11 +7184,11 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
- null, packageName, null);
+ null, packageName, null, UserId.USER_ALL);
}
}
// Force a gc here.
@@ -7099,14 +7221,15 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (removedPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
if (fullRemove && !replacing) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
- extras, null, null);
+ extras, null, null, UserId.USER_ALL);
}
}
if (removedUid >= 0) {
- sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null);
+ sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
+ UserId.getUserId(removedUid));
}
}
}
@@ -7138,7 +7261,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// we don't consider this to be a failure of the core package deletion
} else {
// TODO: Kill the processes first
- mUserManager.removePackageForAllUsers(packageName);
+ sUserManager.removePackageForAllUsers(packageName);
}
schedulePackageCleaning(packageName);
}
@@ -7316,17 +7439,19 @@ public class PackageManagerService extends IPackageManager.Stub {
return ret;
}
+ @Override
public void clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) {
+ final IPackageDataObserver observer, final int userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+ checkValidCaller(Binder.getCallingUid(), userId);
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final boolean succeeded;
synchronized (mInstallLock) {
- succeeded = clearApplicationUserDataLI(packageName);
+ succeeded = clearApplicationUserDataLI(packageName, userId);
}
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
@@ -7347,7 +7472,7 @@ public class PackageManagerService extends IPackageManager.Stub {
});
}
- private boolean clearApplicationUserDataLI(String packageName) {
+ private boolean clearApplicationUserDataLI(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
@@ -7379,7 +7504,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
}
- int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
+ int retCode = mInstaller.clearUserData(packageName, userId);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: "
+ packageName);
@@ -7393,12 +7518,13 @@ public class PackageManagerService extends IPackageManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_CACHE_FILES, null);
// Queue up an async operation since the package deletion may take a little while.
+ final int userId = UserId.getCallingUserId();
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final boolean succeded;
synchronized (mInstallLock) {
- succeded = deleteApplicationCacheFilesLI(packageName);
+ succeded = deleteApplicationCacheFilesLI(packageName, userId);
}
if(observer != null) {
try {
@@ -7411,7 +7537,7 @@ public class PackageManagerService extends IPackageManager.Stub {
});
}
- private boolean deleteApplicationCacheFilesLI(String packageName) {
+ private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
@@ -7429,6 +7555,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
+ // TODO: Pass userId to deleteCacheFiles
int retCode = mInstaller.deleteCacheFiles(packageName);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove cache files for package: "
@@ -7695,19 +7822,23 @@ public class PackageManagerService extends IPackageManager.Stub {
return num;
}
+ @Override
public void setApplicationEnabledSetting(String appPackageName,
- int newState, int flags) {
- setEnabledSetting(appPackageName, null, newState, flags);
+ int newState, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return;
+ setEnabledSetting(appPackageName, null, newState, flags, userId);
}
+ @Override
public void setComponentEnabledSetting(ComponentName componentName,
- int newState, int flags) {
+ int newState, int flags, int userId) {
+ if (!sUserManager.exists(userId)) return;
setEnabledSetting(componentName.getPackageName(),
- componentName.getClassName(), newState, flags);
+ componentName.getClassName(), newState, flags, userId);
}
private void setEnabledSetting(
- final String packageName, String className, int newState, final int flags) {
+ final String packageName, String className, int newState, final int flags, int userId) {
if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
|| newState == COMPONENT_ENABLED_STATE_ENABLED
|| newState == COMPONENT_ENABLED_STATE_DISABLED
@@ -7719,6 +7850,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+ checkValidCaller(uid, userId);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
boolean sendNow = false;
boolean isApp = (className == null);
@@ -7738,20 +7870,21 @@ public class PackageManagerService extends IPackageManager.Stub {
"Unknown component: " + packageName
+ "/" + className);
}
- if (!allowedByPermission && (!UserId.isSameApp(uid, pkgSetting.userId))) {
+ // Allow root and verify that userId is not being specified by a different user
+ if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.appId)) {
throw new SecurityException(
"Permission Denial: attempt to change component state from pid="
+ Binder.getCallingPid()
- + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+ + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
}
if (className == null) {
// We're dealing with an application/package level state change
- if (pkgSetting.enabled == newState) {
+ if (pkgSetting.getEnabled(userId) == newState) {
// Nothing to do
return;
}
- pkgSetting.enabled = newState;
- pkgSetting.pkg.mSetEnabled = newState;
+ pkgSetting.setEnabled(newState, userId);
+ // pkgSetting.pkg.mSetEnabled = newState;
} else {
// We're dealing with a component level state change
// First, verify that this is a valid class name.
@@ -7767,17 +7900,17 @@ public class PackageManagerService extends IPackageManager.Stub {
}
switch (newState) {
case COMPONENT_ENABLED_STATE_ENABLED:
- if (!pkgSetting.enableComponentLPw(className)) {
+ if (!pkgSetting.enableComponentLPw(className, userId)) {
return;
}
break;
case COMPONENT_ENABLED_STATE_DISABLED:
- if (!pkgSetting.disableComponentLPw(className)) {
+ if (!pkgSetting.disableComponentLPw(className, userId)) {
return;
}
break;
case COMPONENT_ENABLED_STATE_DEFAULT:
- if (!pkgSetting.restoreComponentLPw(className)) {
+ if (!pkgSetting.restoreComponentLPw(className, userId)) {
return;
}
break;
@@ -7786,8 +7919,8 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
}
- mSettings.writeLPr();
- packageUid = pkgSetting.userId;
+ mSettings.writePackageRestrictionsLPr(userId);
+ packageUid = UserId.getUid(userId, pkgSetting.appId);
components = mPendingBroadcasts.get(packageName);
final boolean newPackage = components == null;
if (newPackage) {
@@ -7835,19 +7968,22 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
+ UserId.getUserId(packageUid));
}
- public void setPackageStoppedState(String packageName, boolean stopped) {
+ public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
+ if (!sUserManager.exists(userId)) return;
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+ checkValidCaller(uid, userId);
// writer
synchronized (mPackages) {
if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
- uid)) {
- scheduleWriteStoppedPackagesLocked();
+ uid, userId)) {
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -7859,17 +7995,25 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- public int getApplicationEnabledSetting(String packageName) {
+ @Override
+ public int getApplicationEnabledSetting(String packageName, int userId) {
+ if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
+ int uid = Binder.getCallingUid();
+ checkValidCaller(uid, userId);
// reader
synchronized (mPackages) {
- return mSettings.getApplicationEnabledSettingLPr(packageName);
+ return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
}
}
- public int getComponentEnabledSetting(ComponentName componentName) {
+ @Override
+ public int getComponentEnabledSetting(ComponentName componentName, int userId) {
+ if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
+ int uid = Binder.getCallingUid();
+ checkValidCaller(uid, userId);
// reader
synchronized (mPackages) {
- return mSettings.getComponentEnabledSettingLPr(componentName);
+ return mSettings.getComponentEnabledSettingLPr(componentName, userId);
}
}
@@ -8073,7 +8217,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.print(" Required: ");
pw.print(mRequiredVerifierPackage);
pw.print(" (uid=");
- pw.print(getPackageUid(mRequiredVerifierPackage));
+ pw.print(getPackageUid(mRequiredVerifierPackage, 0));
pw.println(")");
}
@@ -8338,7 +8482,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " at code path: " + ps.codePathString);
// We do have a valid package installed on sdcard
processCids.put(args, ps.codePathString);
- int uid = ps.userId;
+ int uid = ps.appId;
if (uid != -1) {
uidList[num++] = uid;
}
@@ -8391,7 +8535,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, null, finishedReceiver);
+ sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserId.USER_ALL);
}
}
@@ -8815,8 +8959,12 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO(kroot): Add a real permission for creating users
enforceSystemOrRoot("Only the system can create users");
- // TODO(kroot): fix this API
- UserInfo userInfo = mUserManager.createUser(name, flags, new ArrayList<ApplicationInfo>());
+ UserInfo userInfo = sUserManager.createUser(name, flags);
+ if (userInfo != null) {
+ Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
+ addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+ }
return userInfo;
}
@@ -8824,13 +8972,34 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO(kroot): Add a real permission for removing users
enforceSystemOrRoot("Only the system can remove users");
- if (userId == 0) {
+ if (userId == 0 || !sUserManager.exists(userId)) {
return false;
}
- mUserManager.removeUser(userId);
+
+ cleanUpUser(userId);
+
+ if (sUserManager.removeUser(userId)) {
+ // Let other services shutdown any activity
+ Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+ addedIntent.putExtra(Intent.EXTRA_USERID, userId);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+ }
+ sUserManager.removePackageFolders(userId);
return true;
}
+ private void cleanUpUser(int userId) {
+ // Disable all the packages for the user first
+ synchronized (mPackages) {
+ Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
+ for (Entry<String, PackageSetting> entry : entries) {
+ entry.getValue().removeUser(userId);
+ }
+ if (mDirtyUsers.remove(userId));
+ mSettings.removeUserLPr(userId);
+ }
+ }
+
@Override
public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
mContext.enforceCallingOrSelfPermission(
@@ -8842,8 +9011,22 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ @Override
public List<UserInfo> getUsers() {
- return mUserManager.getUsers();
+ enforceSystemOrRoot("Only the system can query users");
+ return sUserManager.getUsers();
+ }
+
+ @Override
+ public UserInfo getUser(int userId) {
+ enforceSystemOrRoot("Only the system can remove users");
+ return sUserManager.getUser(userId);
+ }
+
+ @Override
+ public void updateUserName(int userId, String name) {
+ enforceSystemOrRoot("Only the system can rename users");
+ sUserManager.updateUserName(userId, name);
}
@Override
@@ -8854,6 +9037,19 @@ public class PackageManagerService extends IPackageManager.Stub {
if (mSettings.mReadExternalStorageEnforcement != enforcement) {
mSettings.mReadExternalStorageEnforcement = enforcement;
mSettings.writeLPr();
+
+ // kill any non-foreground processes so we restart them and
+ // grant/revoke the GID.
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ if (am != null) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ am.killProcessesBelowForeground("setPermissionEnforcement");
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
}
}
} else {
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java
index efdc2b3..f7f0870 100644
--- a/services/java/com/android/server/pm/PackageSetting.java
+++ b/services/java/com/android/server/pm/PackageSetting.java
@@ -24,7 +24,7 @@ import java.io.File;
* Settings data for a particular package we know about.
*/
final class PackageSetting extends PackageSettingBase {
- int userId;
+ int appId;
PackageParser.Package pkg;
SharedUserSetting sharedUser;
@@ -41,7 +41,7 @@ final class PackageSetting extends PackageSettingBase {
PackageSetting(PackageSetting orig) {
super(orig);
- userId = orig.userId;
+ appId = orig.appId;
pkg = orig.pkg;
sharedUser = orig.sharedUser;
}
@@ -50,6 +50,6 @@ final class PackageSetting extends PackageSettingBase {
public String toString() {
return "PackageSetting{"
+ Integer.toHexString(System.identityHashCode(this))
- + " " + name + "/" + userId + "}";
+ + " " + name + "/" + appId + "}";
}
} \ No newline at end of file
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index e2f83ad..56f2166 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,6 +20,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import java.io.File;
import java.util.HashSet;
@@ -62,20 +64,22 @@ class PackageSettingBase extends GrantedPermissions {
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
- public boolean stopped;
+ private SparseArray<Boolean> stopped = new SparseArray<Boolean>();
// Set to true if we have never launched this app.
- public boolean notLaunched;
+ private SparseArray<Boolean> notLaunched = new SparseArray<Boolean>();
/* Explicitly disabled components */
- HashSet<String> disabledComponents = new HashSet<String>(0);
+ private SparseArray<HashSet<String>> disabledComponents = new SparseArray<HashSet<String>>();
/* Explicitly enabled components */
- HashSet<String> enabledComponents = new HashSet<String>(0);
- int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ private SparseArray<HashSet<String>> enabledComponents = new SparseArray<HashSet<String>>();
+ /* Enabled state */
+ private SparseIntArray enabled = new SparseIntArray();
+
int installStatus = PKG_INSTALL_COMPLETE;
PackageSettingBase origPackage;
-
+
/* package name of the app that installed this package */
String installerPackageName;
PackageSettingBase(String name, String realName, File codePath, File resourcePath,
@@ -111,14 +115,12 @@ class PackageSettingBase extends GrantedPermissions {
permissionsFixed = base.permissionsFixed;
haveGids = base.haveGids;
- stopped = base.stopped;
notLaunched = base.notLaunched;
- disabledComponents = (HashSet<String>) base.disabledComponents.clone();
-
- enabledComponents = (HashSet<String>) base.enabledComponents.clone();
-
- enabled = base.enabled;
+ disabledComponents = (SparseArray<HashSet<String>>) base.disabledComponents.clone();
+ enabledComponents = (SparseArray<HashSet<String>>) base.enabledComponents.clone();
+ enabled = (SparseIntArray) base.enabled.clone();
+ stopped = (SparseArray<Boolean>) base.stopped.clone();
installStatus = base.installStatus;
origPackage = base.origPackage;
@@ -177,31 +179,107 @@ class PackageSettingBase extends GrantedPermissions {
installStatus = base.installStatus;
}
- boolean enableComponentLPw(String componentClassName) {
- boolean changed = disabledComponents.remove(componentClassName);
- changed |= enabledComponents.add(componentClassName);
+ void setEnabled(int state, int userId) {
+ enabled.put(userId, state);
+ }
+
+ int getEnabled(int userId) {
+ return enabled.get(userId, COMPONENT_ENABLED_STATE_DEFAULT);
+ }
+
+ boolean getStopped(int userId) {
+ return stopped.get(userId, false);
+ }
+
+ void setStopped(boolean stop, int userId) {
+ stopped.put(userId, stop);
+ }
+
+ boolean getNotLaunched(int userId) {
+ return notLaunched.get(userId, false);
+ }
+
+ void setNotLaunched(boolean stop, int userId) {
+ notLaunched.put(userId, stop);
+ }
+
+ HashSet<String> getEnabledComponents(int userId) {
+ return getComponentHashSet(enabledComponents, userId);
+ }
+
+ HashSet<String> getDisabledComponents(int userId) {
+ return getComponentHashSet(disabledComponents, userId);
+ }
+
+ void setEnabledComponents(HashSet<String> components, int userId) {
+ enabledComponents.put(userId, components);
+ }
+
+ void setDisabledComponents(HashSet<String> components, int userId) {
+ disabledComponents.put(userId, components);
+ }
+
+ private HashSet<String> getComponentHashSet(SparseArray<HashSet<String>> setArray, int userId) {
+ HashSet<String> set = setArray.get(userId);
+ if (set == null) {
+ set = new HashSet<String>(1);
+ setArray.put(userId, set);
+ }
+ return set;
+ }
+
+ void addDisabledComponent(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ disabled.add(componentClassName);
+ }
+
+ void addEnabledComponent(String componentClassName, int userId) {
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ enabled.add(componentClassName);
+ }
+
+ boolean enableComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = disabled.remove(componentClassName);
+ changed |= enabled.add(componentClassName);
return changed;
}
- boolean disableComponentLPw(String componentClassName) {
- boolean changed = enabledComponents.remove(componentClassName);
- changed |= disabledComponents.add(componentClassName);
+ boolean disableComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = enabled.remove(componentClassName);
+ changed |= disabled.add(componentClassName);
return changed;
}
- boolean restoreComponentLPw(String componentClassName) {
- boolean changed = enabledComponents.remove(componentClassName);
- changed |= disabledComponents.remove(componentClassName);
+ boolean restoreComponentLPw(String componentClassName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ boolean changed = enabled.remove(componentClassName);
+ changed |= disabled.remove(componentClassName);
return changed;
}
- int getCurrentEnabledStateLPr(String componentName) {
- if (enabledComponents.contains(componentName)) {
+ int getCurrentEnabledStateLPr(String componentName, int userId) {
+ HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+ HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+ if (enabled.contains(componentName)) {
return COMPONENT_ENABLED_STATE_ENABLED;
- } else if (disabledComponents.contains(componentName)) {
+ } else if (disabled.contains(componentName)) {
return COMPONENT_ENABLED_STATE_DISABLED;
} else {
return COMPONENT_ENABLED_STATE_DEFAULT;
}
}
-} \ No newline at end of file
+
+ void removeUser(int userId) {
+ enabled.delete(userId);
+ stopped.delete(userId);
+ enabledComponents.delete(userId);
+ disabledComponents.delete(userId);
+ notLaunched.delete(userId);
+ }
+
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 363d020..bb7f4fc 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,6 +32,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -40,11 +41,14 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserId;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -63,6 +67,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import libcore.io.IoUtils;
@@ -78,6 +83,17 @@ final class Settings {
private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
private static final String ATTR_ENFORCEMENT = "enforcement";
+ private static final String TAG_ITEM = "item";
+ private static final String TAG_DISABLED_COMPONENTS = "disabled-components";
+ private static final String TAG_ENABLED_COMPONENTS = "enabled-components";
+ private static final String TAG_PACKAGE_RESTRICTIONS = "package-restrictions";
+ private static final String TAG_PACKAGE = "pkg";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_NOT_LAUNCHED = "nl";
+ private static final String ATTR_ENABLED = "enabled";
+ private static final String ATTR_STOPPED = "stopped";
+
private final File mSettingsFilename;
private final File mBackupSettingsFilename;
private final File mPackageListFilename;
@@ -153,19 +169,24 @@ final class Settings {
*/
private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
+ private final File mSystemDir;
Settings() {
- File dataDir = Environment.getDataDirectory();
- File systemDir = new File(dataDir, "system");
- systemDir.mkdirs();
- FileUtils.setPermissions(systemDir.toString(),
+ this(Environment.getDataDirectory());
+ }
+
+ Settings(File dataDir) {
+ mSystemDir = new File(dataDir, "system");
+ mSystemDir.mkdirs();
+ FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
- mSettingsFilename = new File(systemDir, "packages.xml");
- mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
- mPackageListFilename = new File(systemDir, "packages.list");
- mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml");
- mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml");
+ mSettingsFilename = new File(mSystemDir, "packages.xml");
+ mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
+ mPackageListFilename = new File(mSystemDir, "packages.list");
+ // Deprecated: Needed for migration
+ mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
+ mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
@@ -254,7 +275,7 @@ final class Settings {
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
- p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags);
+ p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags);
mDisabledSysPackages.remove(name);
return ret;
}
@@ -263,7 +284,7 @@ final class Settings {
String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
PackageSetting p = mPackages.get(name);
if (p != null) {
- if (p.userId == uid) {
+ if (p.appId == uid) {
return p;
}
PackageManagerService.reportSettingsProblem(Log.ERROR,
@@ -272,7 +293,7 @@ final class Settings {
}
p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
vc, pkgFlags);
- p.userId = uid;
+ p.appId = uid;
if (addUserIdLPw(uid, p, name)) {
mPackages.put(name, p);
return p;
@@ -323,7 +344,7 @@ final class Settings {
}
}
}
-
+
private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
@@ -335,13 +356,13 @@ final class Settings {
// This is an updated system app with versions in both system
// and data partition. Just let the most recent version
// take precedence.
- Slog.w(PackageManagerService.TAG, "Trying to update system app code path from " +
- p.codePathString + " to " + codePath.toString());
+ Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
+ + p.codePathString + " to " + codePath.toString());
} else {
// Just a change in the code path is not an issue, but
// let's log a message about it.
- Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from " + p.codePath
- + " to " + codePath + "; Retaining data and using new");
+ Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
+ + p.codePath + " to " + codePath + "; Retaining data and using new");
/*
* Since we've changed paths, we need to prefer the new
* native library path over the one stored in the
@@ -378,15 +399,15 @@ final class Settings {
// We are consuming the data from an existing package.
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
nativeLibraryPathString, vc, pkgFlags);
- if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name
- + " is adopting original package " + origPackage.name);
+ if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ + name + " is adopting original package " + origPackage.name);
// Note that we will retain the new package's signature so
// that we can keep its data.
PackageSignatures s = p.signatures;
p.copyFrom(origPackage);
p.signatures = s;
p.sharedUser = origPackage.sharedUser;
- p.userId = origPackage.userId;
+ p.appId = origPackage.appId;
p.origPackage = origPackage;
mRenamedPackages.put(name, origPackage.name);
name = origPackage.name;
@@ -404,11 +425,17 @@ final class Settings {
e.fillInStackTrace();
Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
}
- p.stopped = true;
- p.notLaunched = true;
+ List<UserInfo> users = getAllUsers();
+ if (users != null) {
+ for (UserInfo user : users) {
+ p.setStopped(true, user.id);
+ p.setNotLaunched(true, user.id);
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
}
if (sharedUser != null) {
- p.userId = sharedUser.userId;
+ p.appId = sharedUser.userId;
} else {
// Clone the setting here for disabled system packages
PackageSetting dis = mDisabledSysPackages.get(name);
@@ -420,21 +447,31 @@ final class Settings {
if (dis.signatures.mSignatures != null) {
p.signatures.mSignatures = dis.signatures.mSignatures.clone();
}
- p.userId = dis.userId;
+ p.appId = dis.appId;
// Clone permissions
p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
// Clone component info
- p.disabledComponents = new HashSet<String>(dis.disabledComponents);
- p.enabledComponents = new HashSet<String>(dis.enabledComponents);
+ List<UserInfo> users = getAllUsers();
+ if (users != null) {
+ for (UserInfo user : users) {
+ int userId = user.id;
+ p.setDisabledComponents(
+ new HashSet<String>(dis.getDisabledComponents(userId)),
+ userId);
+ p.setEnabledComponents(
+ new HashSet<String>(dis.getEnabledComponents(userId)),
+ userId);
+ }
+ }
// Add new setting to list of user ids
- addUserIdLPw(p.userId, p, name);
+ addUserIdLPw(p.appId, p, name);
} else {
// Assign new user id
- p.userId = newUserIdLPw(p);
+ p.appId = newUserIdLPw(p);
}
}
}
- if (p.userId < 0) {
+ if (p.appId < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Package " + name + " could not be assigned a valid uid");
return null;
@@ -450,8 +487,8 @@ final class Settings {
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
- pkg.mSetEnabled = p.enabled;
- pkg.mSetStopped = p.stopped;
+ // pkg.mSetEnabled = p.getEnabled(userId);
+ // pkg.mSetStopped = p.getStopped(userId);
final String codePath = pkg.applicationInfo.sourceDir;
final String resourcePath = pkg.applicationInfo.publicSourceDir;
// Update code path if needed
@@ -475,18 +512,18 @@ final class Settings {
p.nativeLibraryPathString = nativeLibraryPath;
}
// Update version code if needed
- if (pkg.mVersionCode != p.versionCode) {
+ if (pkg.mVersionCode != p.versionCode) {
p.versionCode = pkg.mVersionCode;
}
- // Update signatures if needed.
- if (p.signatures.mSignatures == null) {
- p.signatures.assignSignatures(pkg.mSignatures);
- }
- // If this app defines a shared user id initialize
- // the shared user signatures as well.
- if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
- p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
- }
+ // Update signatures if needed.
+ if (p.signatures.mSignatures == null) {
+ p.signatures.assignSignatures(pkg.mSignatures);
+ }
+ // If this app defines a shared user id initialize
+ // the shared user signatures as well.
+ if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
+ p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
+ }
addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
}
@@ -502,9 +539,9 @@ final class Settings {
+ p.sharedUser + " but is now " + sharedUser
+ "; I am not changing its files so it will probably fail!");
p.sharedUser.packages.remove(p);
- } else if (p.userId != sharedUser.userId) {
+ } else if (p.appId != sharedUser.userId) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Package " + p.name + " was user id " + p.userId
+ "Package " + p.name + " was user id " + p.appId
+ " but is now user " + sharedUser
+ " with id " + sharedUser.userId
+ "; I am not changing its files so it will probably fail!");
@@ -512,7 +549,7 @@ final class Settings {
sharedUser.packages.add(p);
p.sharedUser = sharedUser;
- p.userId = sharedUser.userId;
+ p.appId = sharedUser.userId;
}
}
@@ -577,8 +614,8 @@ final class Settings {
return p.sharedUser.userId;
}
} else {
- removeUserIdLPw(p.userId);
- return p.userId;
+ removeUserIdLPw(p.appId);
+ return p.appId;
}
}
return -1;
@@ -591,7 +628,7 @@ final class Settings {
p.sharedUser.packages.remove(p);
p.sharedUser.packages.add(newp);
} else {
- replaceUserIdLPw(p.userId, newp);
+ replaceUserIdLPw(p.appId, newp);
}
}
mPackages.put(name, newp);
@@ -658,50 +695,269 @@ final class Settings {
}
}
- void writeStoppedLPr() {
+ private File getUserPackagesStateFile(int userId) {
+ return new File(mSystemDir,
+ "users/" + userId + "/package-restrictions.xml");
+ }
+
+ private File getUserPackagesStateBackupFile(int userId) {
+ return new File(mSystemDir,
+ "users/" + userId + "/package-restrictions-backup.xml");
+ }
+
+ void writeAllUsersPackageRestrictionsLPr() {
+ List<UserInfo> users = getAllUsers();
+ if (users == null) return;
+
+ for (UserInfo user : users) {
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
+
+ void readAllUsersPackageRestrictionsLPr() {
+ List<UserInfo> users = getAllUsers();
+ if (users == null) {
+ readPackageRestrictionsLPr(0);
+ return;
+ }
+
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
+ }
+ }
+
+ void readPackageRestrictionsLPr(int userId) {
+ FileInputStream str = null;
+ File userPackagesStateFile = getUserPackagesStateFile(userId);
+ File backupFile = getUserPackagesStateBackupFile(userId);
+ if (backupFile.exists()) {
+ try {
+ str = new FileInputStream(backupFile);
+ mReadMessages.append("Reading from backup stopped packages file\n");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "Need to read from backup stopped packages file");
+ if (userPackagesStateFile.exists()) {
+ // If both the backup and normal file exist, we
+ // ignore the normal one since it might have been
+ // corrupted.
+ Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
+ + userPackagesStateFile);
+ userPackagesStateFile.delete();
+ }
+ } catch (java.io.IOException e) {
+ // We'll try for the normal settings file.
+ }
+ }
+
+ try {
+ if (str == null) {
+ if (!userPackagesStateFile.exists()) {
+ mReadMessages.append("No stopped packages file found\n");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "No stopped packages file; "
+ + "assuming all started");
+ // At first boot, make sure no packages are stopped.
+ // We usually want to have third party apps initialize
+ // in the stopped state, but not at first boot.
+ for (PackageSetting pkg : mPackages.values()) {
+ pkg.setStopped(false, userId);
+ pkg.setNotLaunched(false, userId);
+ }
+ return;
+ }
+ str = new FileInputStream(userPackagesStateFile);
+ }
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(str, null);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ ;
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in package restrictions file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager stopped packages");
+ return;
+ }
+
+ int outerDepth = parser.getDepth();
+ PackageSetting ps = null;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ ps = mPackages.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG, "No package known for stopped package: "
+ + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
+ int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT
+ : Integer.parseInt(enabledStr);
+ ps.setEnabled(enabled, userId);
+ String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
+ boolean stopped = stoppedStr == null ? false : Boolean.parseBoolean(stoppedStr);
+ ps.setStopped(stopped, userId);
+ String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
+ boolean notLaunched = stoppedStr == null ? false
+ : Boolean.parseBoolean(notLaunchedStr);
+ ps.setNotLaunched(notLaunched, userId);
+
+ int packageDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > packageDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tagName = parser.getName();
+ if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+ HashSet<String> components = readComponentsLPr(parser);
+ ps.setEnabledComponents(components, userId);
+ } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+ HashSet<String> components = readComponentsLPr(parser);
+ ps.setDisabledComponents(components, userId);
+ }
+ }
+ } else {
+ Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ str.close();
+
+ } catch (XmlPullParserException e) {
+ mReadMessages.append("Error reading: " + e.toString());
+ PackageManagerService.reportSettingsProblem(Log.ERROR,
+ "Error reading stopped packages: " + e);
+ Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+
+ } catch (java.io.IOException e) {
+ mReadMessages.append("Error reading: " + e.toString());
+ PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
+ Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+ }
+ }
+
+ private HashSet<String> readComponentsLPr(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ HashSet<String> components = new HashSet<String>();
+ int type;
+ int outerDepth = parser.getDepth();
+ String tagName;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tagName = parser.getName();
+ if (tagName.equals(TAG_ITEM)) {
+ String componentName = parser.getAttributeValue(null, ATTR_NAME);
+ if (componentName != null) {
+ components.add(componentName);
+ }
+ }
+ }
+ return components;
+ }
+
+ void writePackageRestrictionsLPr(int userId) {
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
- if (mStoppedPackagesFilename.exists()) {
+ File userPackagesStateFile = getUserPackagesStateFile(userId);
+ File backupFile = getUserPackagesStateBackupFile(userId);
+ new File(userPackagesStateFile.getParent()).mkdirs();
+ if (userPackagesStateFile.exists()) {
// Presence of backup settings file indicates that we failed
// to persist packages earlier. So preserve the older
// backup for future reference since the current packages
// might have been corrupted.
- if (!mBackupStoppedPackagesFilename.exists()) {
- if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) {
- Log.wtf(PackageManagerService.TAG, "Unable to backup package manager stopped packages, "
+ if (!backupFile.exists()) {
+ if (!userPackagesStateFile.renameTo(backupFile)) {
+ Log.wtf(PackageManagerService.TAG, "Unable to backup user packages state file, "
+ "current changes will be lost at reboot");
return;
}
} else {
- mStoppedPackagesFilename.delete();
+ userPackagesStateFile.delete();
Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
}
}
try {
- final FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename);
+ final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
final BufferedOutputStream str = new BufferedOutputStream(fstr);
- //XmlSerializer serializer = XmlUtils.serializerInstance();
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(str, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- serializer.startTag(null, "stopped-packages");
+ serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
for (final PackageSetting pkg : mPackages.values()) {
- if (pkg.stopped) {
- serializer.startTag(null, "pkg");
- serializer.attribute(null, "name", pkg.name);
- if (pkg.notLaunched) {
- serializer.attribute(null, "nl", "1");
+ if (pkg.getStopped(userId)
+ || pkg.getNotLaunched(userId)
+ || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
+ || pkg.getEnabledComponents(userId).size() > 0
+ || pkg.getDisabledComponents(userId).size() > 0) {
+ serializer.startTag(null, TAG_PACKAGE);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
+ boolean stopped = pkg.getStopped(userId);
+ boolean notLaunched = pkg.getNotLaunched(userId);
+ int enabled = pkg.getEnabled(userId);
+ HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
+ HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
+
+ if (stopped) {
+ serializer.attribute(null, ATTR_STOPPED, "true");
+ }
+ if (notLaunched) {
+ serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
+ }
+ if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
}
- serializer.endTag(null, "pkg");
+ if (enabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+ for (final String name : enabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+ }
+ if (disabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+ for (final String name : disabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+ }
+ serializer.endTag(null, TAG_PACKAGE);
}
}
- serializer.endTag(null, "stopped-packages");
+ serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.endDocument();
@@ -711,8 +967,8 @@ final class Settings {
// New settings successfully written, old ones are no longer
// needed.
- mBackupStoppedPackagesFilename.delete();
- FileUtils.setPermissions(mStoppedPackagesFilename.toString(),
+ backupFile.delete();
+ FileUtils.setPermissions(userPackagesStateFile.toString(),
FileUtils.S_IRUSR|FileUtils.S_IWUSR
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
@@ -720,26 +976,30 @@ final class Settings {
// Done, all is good!
return;
} catch(java.io.IOException e) {
- Log.wtf(PackageManagerService.TAG, "Unable to write package manager stopped packages, "
+ Log.wtf(PackageManagerService.TAG,
+ "Unable to write package manager user packages state, "
+ " current changes will be lost at reboot", e);
}
// Clean up partially written files
- if (mStoppedPackagesFilename.exists()) {
- if (!mStoppedPackagesFilename.delete()) {
- Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename);
+ if (userPackagesStateFile.exists()) {
+ if (!userPackagesStateFile.delete()) {
+ Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
+ + mStoppedPackagesFilename);
}
}
}
// Note: assumed "stopped" field is already cleared in all packages.
+ // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
void readStoppedLPw() {
FileInputStream str = null;
if (mBackupStoppedPackagesFilename.exists()) {
try {
str = new FileInputStream(mBackupStoppedPackagesFilename);
mReadMessages.append("Reading from backup stopped packages file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "Need to read from backup stopped packages file");
if (mSettingsFilename.exists()) {
// If both the backup and normal file exist, we
// ignore the normal one since it might have been
@@ -757,14 +1017,14 @@ final class Settings {
if (str == null) {
if (!mStoppedPackagesFilename.exists()) {
mReadMessages.append("No stopped packages file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO, "No stopped packages file file; "
- + "assuming all started");
+ PackageManagerService.reportSettingsProblem(Log.INFO,
+ "No stopped packages file file; assuming all started");
// At first boot, make sure no packages are stopped.
// We usually want to have third party apps initialize
// in the stopped state, but not at first boot.
for (PackageSetting pkg : mPackages.values()) {
- pkg.stopped = false;
- pkg.notLaunched = false;
+ pkg.setStopped(false, 0);
+ pkg.setNotLaunched(false, 0);
}
return;
}
@@ -796,16 +1056,17 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("pkg")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
PackageSetting ps = mPackages.get(name);
if (ps != null) {
- ps.stopped = true;
- if ("1".equals(parser.getAttributeValue(null, "nl"))) {
- ps.notLaunched = true;
+ ps.setStopped(true, 0);
+ if ("1".equals(parser.getAttributeValue(null, ATTR_NOT_LAUNCHED))) {
+ ps.setNotLaunched(true, 0);
}
} else {
- Slog.w(PackageManagerService.TAG, "No package known for stopped package: " + name);
+ Slog.w(PackageManagerService.TAG,
+ "No package known for stopped package: " + name);
}
XmlUtils.skipCurrentTag(parser);
} else {
@@ -817,12 +1078,13 @@ final class Settings {
str.close();
- } catch(XmlPullParserException e) {
+ } catch (XmlPullParserException e) {
mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e);
+ PackageManagerService.reportSettingsProblem(Log.ERROR,
+ "Error reading stopped packages: " + e);
Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
- } catch(java.io.IOException e) {
+ } catch (java.io.IOException e) {
mReadMessages.append("Error reading: " + e.toString());
PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
@@ -906,23 +1168,23 @@ final class Settings {
serializer.startTag(null, "preferred-activities");
for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
- serializer.startTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
pa.writeToXml(serializer);
- serializer.endTag(null, "item");
+ serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "preferred-activities");
for (final SharedUserSetting usr : mSharedUsers.values()) {
serializer.startTag(null, "shared-user");
- serializer.attribute(null, "name", usr.name);
+ serializer.attribute(null, ATTR_NAME, usr.name);
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
serializer.startTag(null, "perms");
for (String name : usr.grantedPermissions) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "perms");
serializer.endTag(null, "shared-user");
@@ -931,7 +1193,7 @@ final class Settings {
if (mPackagesToBeCleaned.size() > 0) {
for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
serializer.startTag(null, "cleaning-package");
- serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
+ serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
serializer.endTag(null, "cleaning-package");
}
}
@@ -1016,8 +1278,7 @@ final class Settings {
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
- writeStoppedLPr();
-
+ writeAllUsersPackageRestrictionsLPr();
return;
} catch(XmlPullParserException e) {
@@ -1030,7 +1291,8 @@ final class Settings {
// Clean up partially written files
if (mSettingsFilename.exists()) {
if (!mSettingsFilename.delete()) {
- Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: " + mSettingsFilename);
+ Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
+ + mSettingsFilename);
}
}
//Debug.stopMethodTracing();
@@ -1039,7 +1301,7 @@ final class Settings {
void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "updated-package");
- serializer.attribute(null, "name", pkg.name);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
@@ -1055,9 +1317,9 @@ final class Settings {
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
}
if (pkg.sharedUser == null) {
- serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "userId", Integer.toString(pkg.appId));
} else {
- serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
}
serializer.startTag(null, "perms");
if (pkg.sharedUser == null) {
@@ -1072,9 +1334,9 @@ final class Settings {
// this wont
// match the semantics of grantedPermissions. So write all
// permissions.
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
}
}
@@ -1085,7 +1347,7 @@ final class Settings {
void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "package");
- serializer.attribute(null, "name", pkg.name);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
@@ -1102,16 +1364,13 @@ final class Settings {
serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
if (pkg.sharedUser == null) {
- serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "userId", Integer.toString(pkg.appId));
} else {
- serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+ serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
}
if (pkg.uidError) {
serializer.attribute(null, "uidError", "true");
}
- if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
- }
if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
serializer.attribute(null, "installStatus", "false");
}
@@ -1127,31 +1386,13 @@ final class Settings {
// empty permissions list so permissionsFixed will
// be set.
for (final String name : pkg.grantedPermissions) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
}
}
serializer.endTag(null, "perms");
}
- if (pkg.disabledComponents.size() > 0) {
- serializer.startTag(null, "disabled-components");
- for (final String name : pkg.disabledComponents) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
- }
- serializer.endTag(null, "disabled-components");
- }
- if (pkg.enabledComponents.size() > 0) {
- serializer.startTag(null, "enabled-components");
- for (final String name : pkg.enabledComponents) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", name);
- serializer.endTag(null, "item");
- }
- serializer.endTag(null, "enabled-components");
- }
serializer.endTag(null, "package");
}
@@ -1159,8 +1400,8 @@ final class Settings {
void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
throws XmlPullParserException, java.io.IOException {
if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
- serializer.startTag(null, "item");
- serializer.attribute(null, "name", bp.name);
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, bp.name);
serializer.attribute(null, "package", bp.sourcePackage);
if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
@@ -1180,7 +1421,7 @@ final class Settings {
}
}
}
- serializer.endTag(null, "item");
+ serializer.endTag(null, TAG_ITEM);
}
}
@@ -1198,7 +1439,7 @@ final class Settings {
return ret;
}
- boolean readLPw() {
+ boolean readLPw(List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -1273,7 +1514,7 @@ final class Settings {
} else if (tagName.equals("updated-package")) {
readDisabledSysPackageLPw(parser);
} else if (tagName.equals("cleaning-package")) {
- String name = parser.getAttributeValue(null, "name");
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
mPackagesToBeCleaned.add(name);
}
@@ -1366,14 +1607,29 @@ final class Settings {
final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
while (disabledIt.hasNext()) {
final PackageSetting disabledPs = disabledIt.next();
- final Object id = getUserIdLPr(disabledPs.userId);
+ final Object id = getUserIdLPr(disabledPs.appId);
if (id != null && id instanceof SharedUserSetting) {
disabledPs.sharedUser = (SharedUserSetting) id;
}
}
- readStoppedLPw();
-
+ if (mBackupStoppedPackagesFilename.exists()
+ || mStoppedPackagesFilename.exists()) {
+ // Read old file
+ readStoppedLPw();
+ mBackupStoppedPackagesFilename.delete();
+ mStoppedPackagesFilename.delete();
+ // Migrate to new file format
+ writePackageRestrictionsLPr(0);
+ } else {
+ if (users == null) {
+ readPackageRestrictionsLPr(0);
+ } else {
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
+ }
+ }
+ }
mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
+ mSharedUsers.size() + " shared uids\n");
@@ -1407,8 +1663,8 @@ final class Settings {
}
final String tagName = parser.getName();
- if (tagName.equals("item")) {
- final String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ final String name = parser.getAttributeValue(null, ATTR_NAME);
final String sourcePackage = parser.getAttributeValue(null, "package");
final String ptype = parser.getAttributeValue(null, "type");
if (name != null && sourcePackage != null) {
@@ -1444,7 +1700,7 @@ final class Settings {
private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException,
IOException {
- String name = parser.getAttributeValue(null, "name");
+ String name = parser.getAttributeValue(null, ATTR_NAME);
String realName = parser.getAttributeValue(null, "realName");
String codePathStr = parser.getAttributeValue(null, "codePath");
String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
@@ -1497,10 +1753,10 @@ final class Settings {
}
}
String idStr = parser.getAttributeValue(null, "userId");
- ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
- if (ps.userId <= 0) {
+ ps.appId = idStr != null ? Integer.parseInt(idStr) : 0;
+ if (ps.appId <= 0) {
String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
- ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
+ ps.appId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
}
int outerDepth = parser.getDepth();
int type;
@@ -1541,7 +1797,7 @@ final class Settings {
String version = null;
int versionCode = 0;
try {
- name = parser.getAttributeValue(null, "name");
+ name = parser.getAttributeValue(null, ATTR_NAME);
realName = parser.getAttributeValue(null, "realName");
idStr = parser.getAttributeValue(null, "userId");
uidError = parser.getAttributeValue(null, "uidError");
@@ -1672,17 +1928,18 @@ final class Settings {
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
- final String enabledStr = parser.getAttributeValue(null, "enabled");
+ // Handle legacy string here for single-user mode
+ final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
if (enabledStr != null) {
try {
- packageSetting.enabled = Integer.parseInt(enabledStr);
+ packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */);
} catch (NumberFormatException e) {
if (enabledStr.equalsIgnoreCase("true")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0);
} else if (enabledStr.equalsIgnoreCase("false")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
} else if (enabledStr.equalsIgnoreCase("default")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name
@@ -1691,8 +1948,9 @@ final class Settings {
}
}
} else {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
}
+
final String installStatusStr = parser.getAttributeValue(null, "installStatus");
if (installStatusStr != null) {
if (installStatusStr.equalsIgnoreCase("false")) {
@@ -1711,10 +1969,11 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("disabled-components")) {
- readDisabledComponentsLPw(packageSetting, parser);
- } else if (tagName.equals("enabled-components")) {
- readEnabledComponentsLPw(packageSetting, parser);
+ // Legacy
+ if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+ readDisabledComponentsLPw(packageSetting, parser, 0);
+ } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+ readEnabledComponentsLPw(packageSetting, parser, 0);
} else if (tagName.equals("sigs")) {
packageSetting.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals("perms")) {
@@ -1731,8 +1990,8 @@ final class Settings {
}
}
- private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
- throws IOException, XmlPullParserException {
+ private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1742,10 +2001,10 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
- packageSetting.disabledComponents.add(name.intern());
+ packageSetting.addDisabledComponent(name.intern(), userId);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <disabled-components> has"
@@ -1759,8 +2018,8 @@ final class Settings {
}
}
- private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
- throws IOException, XmlPullParserException {
+ private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1770,10 +2029,10 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
- packageSetting.enabledComponents.add(name.intern());
+ packageSetting.addEnabledComponent(name.intern(), userId);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <enabled-components> has"
@@ -1787,13 +2046,13 @@ final class Settings {
}
}
- private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
+ private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
String name = null;
String idStr = null;
int pkgFlags = 0;
SharedUserSetting su = null;
try {
- name = parser.getAttributeValue(null, "name");
+ name = parser.getAttributeValue(null, ATTR_NAME);
idStr = parser.getAttributeValue(null, "userId");
int userId = idStr != null ? Integer.parseInt(idStr) : 0;
if ("true".equals(parser.getAttributeValue(null, "system"))) {
@@ -1859,8 +2118,8 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_ITEM)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name != null) {
outPerms.add(name.intern());
} else {
@@ -1887,7 +2146,7 @@ final class Settings {
}
String tagName = parser.getName();
- if (tagName.equals("item")) {
+ if (tagName.equals(TAG_ITEM)) {
PreferredActivity pa = new PreferredActivity(parser);
if (pa.mPref.getParseError() == null) {
mPreferredActivities.addFilter(pa);
@@ -1905,6 +2164,13 @@ final class Settings {
}
}
+ void removeUserLPr(int userId) {
+ File file = getUserPackagesStateFile(userId);
+ file.delete();
+ file = getUserPackagesStateBackupFile(userId);
+ file.delete();
+ }
+
// Returns -1 if we could not find an available UserId to assign
private int newUserIdLPw(Object obj) {
// Let's be stupidly inefficient for now...
@@ -1940,32 +2206,34 @@ final class Settings {
return ps;
}
- boolean isEnabledLPr(ComponentInfo componentInfo, int flags) {
+ boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
return true;
}
- final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
+ final String pkgName = componentInfo.packageName;
+ final PackageSetting packageSettings = mPackages.get(pkgName);
if (PackageManagerService.DEBUG_SETTINGS) {
- Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = " + componentInfo.packageName
- + " componentName = " + componentInfo.name);
+ Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
+ + componentInfo.packageName + " componentName = " + componentInfo.name);
Log.v(PackageManagerService.TAG, "enabledComponents: "
- + Arrays.toString(packageSettings.enabledComponents.toArray()));
+ + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
Log.v(PackageManagerService.TAG, "disabledComponents: "
- + Arrays.toString(packageSettings.disabledComponents.toArray()));
+ + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
}
if (packageSettings == null) {
return false;
}
- if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
- || packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+ final int enabled = packageSettings.getEnabled(userId);
+ if (enabled == COMPONENT_ENABLED_STATE_DISABLED
+ || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
|| (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
- && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
+ && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
return false;
}
- if (packageSettings.enabledComponents.contains(componentInfo.name)) {
+ if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
return true;
}
- if (packageSettings.disabledComponents.contains(componentInfo.name)) {
+ if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
return false;
}
return componentInfo.enabled;
@@ -1979,35 +2247,36 @@ final class Settings {
return pkg.installerPackageName;
}
- int getApplicationEnabledSettingLPr(String packageName) {
+ int getApplicationEnabledSettingLPr(String packageName, int userId) {
final PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- return pkg.enabled;
+ return pkg.getEnabled(userId);
}
- int getComponentEnabledSettingLPr(ComponentName componentName) {
+ int getComponentEnabledSettingLPr(ComponentName componentName, int userId) {
final String packageName = componentName.getPackageName();
final PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown component: " + componentName);
}
final String classNameStr = componentName.getClassName();
- return pkg.getCurrentEnabledStateLPr(classNameStr);
+ return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
}
-
+
boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
- boolean allowedByPermission, int uid) {
+ boolean allowedByPermission, int uid, int userId) {
+ int appId = UserId.getAppId(uid);
final PackageSetting pkgSetting = mPackages.get(packageName);
if (pkgSetting == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- if (!allowedByPermission && (uid != pkgSetting.userId)) {
+ if (!allowedByPermission && (appId != pkgSetting.appId)) {
throw new SecurityException(
"Permission Denial: attempt to change stopped state from pid="
+ Binder.getCallingPid()
- + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+ + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
}
if (DEBUG_STOPPED) {
if (stopped) {
@@ -2016,22 +2285,33 @@ final class Settings {
Slog.i(TAG, "Stopping package " + packageName, e);
}
}
- if (pkgSetting.stopped != stopped) {
- pkgSetting.stopped = stopped;
- pkgSetting.pkg.mSetStopped = stopped;
- if (pkgSetting.notLaunched) {
+ if (pkgSetting.getStopped(userId) != stopped) {
+ pkgSetting.setStopped(stopped, userId);
+ // pkgSetting.pkg.mSetStopped = stopped;
+ if (pkgSetting.getNotLaunched(userId)) {
if (pkgSetting.installerPackageName != null) {
PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
pkgSetting.name, null,
- pkgSetting.installerPackageName, null);
+ pkgSetting.installerPackageName, null, userId);
}
- pkgSetting.notLaunched = false;
+ pkgSetting.setNotLaunched(false, userId);
}
return true;
}
return false;
}
+ private List<UserInfo> getAllUsers() {
+ try {
+ return AppGlobals.getPackageManager().getUsers();
+ } catch (RemoteException re) {
+ // Local to system process, shouldn't happen
+ } catch (NullPointerException npe) {
+ // packagemanager not yet initialized
+ }
+ return null;
+ }
+
static final void printFlags(PrintWriter pw, int val, Object[] spec) {
pw.print("[ ");
for (int i=0; i<spec.length; i+=2) {
@@ -2096,7 +2376,7 @@ final class Settings {
pw.println(ps.name);
}
- pw.print(" userId="); pw.print(ps.userId);
+ pw.print(" userId="); pw.print(ps.appId);
pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
pw.print(" sharedUser="); pw.println(ps.sharedUser);
pw.print(" pkg="); pw.println(ps.pkg);
@@ -2169,18 +2449,24 @@ final class Settings {
pw.print(" haveGids="); pw.println(ps.haveGids);
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
pw.print(" installStatus="); pw.print(ps.installStatus);
- pw.print(" stopped="); pw.print(ps.stopped);
- pw.print(" enabled="); pw.println(ps.enabled);
- if (ps.disabledComponents.size() > 0) {
- pw.println(" disabledComponents:");
- for (String s : ps.disabledComponents) {
- pw.print(" "); pw.println(s);
+ List<UserInfo> users = getAllUsers();
+ for (UserInfo user : users) {
+ pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print(" stopped=");
+ pw.print(ps.getStopped(user.id));
+ pw.print(" enabled=");
+ pw.println(ps.getEnabled(user.id));
+ if (ps.getDisabledComponents(user.id).size() > 0) {
+ pw.println(" disabledComponents:");
+ for (String s : ps.getDisabledComponents(user.id)) {
+ pw.print(" "); pw.println(s);
+ }
}
- }
- if (ps.enabledComponents.size() > 0) {
- pw.println(" enabledComponents:");
- for (String s : ps.enabledComponents) {
- pw.print(" "); pw.println(s);
+ if (ps.getEnabledComponents(user.id).size() > 0) {
+ pw.println(" enabledComponents:");
+ for (String s : ps.getEnabledComponents(user.id)) {
+ pw.print(" "); pw.println(s);
+ }
}
}
if (ps.grantedPermissions.size() > 0) {
@@ -2234,7 +2520,7 @@ final class Settings {
pw.println(ps.name);
}
pw.print(" userId=");
- pw.println(ps.userId);
+ pw.println(ps.appId);
pw.print(" sharedUser=");
pw.println(ps.sharedUser);
pw.print(" codePath=");
@@ -2244,7 +2530,7 @@ final class Settings {
}
}
}
-
+
void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
boolean printedSomething = false;
for (BasePermission p : mPermissions.values()) {
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManager.java
index 5eacf4a..4e9e666 100644
--- a/services/java/com/android/server/pm/UserManager.java
+++ b/services/java/com/android/server/pm/UserManager.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import android.content.pm.ApplicationInfo;
@@ -58,7 +59,7 @@ public class UserManager {
private static final String USER_INFO_DIR = "system" + File.separator + "users";
private static final String USER_LIST_FILENAME = "userlist.xml";
- private SparseArray<UserInfo> mUsers;
+ private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
private final File mUsersDir;
private final File mUserListFile;
@@ -73,6 +74,9 @@ public class UserManager {
UserManager(File dataDir, File baseUserPath) {
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
+ // Make zeroth user directory, for services to migrate their files to that location
+ File userZeroDir = new File(mUsersDir, "0");
+ userZeroDir.mkdirs();
mBaseUserPath = baseUserPath;
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
@@ -88,11 +92,36 @@ public class UserManager {
}
public List<UserInfo> getUsers() {
- ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
- for (int i = 0; i < mUsers.size(); i++) {
- users.add(mUsers.valueAt(i));
+ synchronized (mUsers) {
+ ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+ for (int i = 0; i < mUsers.size(); i++) {
+ users.add(mUsers.valueAt(i));
+ }
+ return users;
+ }
+ }
+
+ public UserInfo getUser(int userId) {
+ synchronized (mUsers) {
+ UserInfo info = mUsers.get(userId);
+ return info;
+ }
+ }
+
+ public boolean exists(int userId) {
+ synchronized (mUsers) {
+ return ArrayUtils.contains(mUserIds, userId);
+ }
+ }
+
+ public void updateUserName(int userId, String name) {
+ synchronized (mUsers) {
+ UserInfo info = mUsers.get(userId);
+ if (name != null && !name.equals(info.name)) {
+ info.name = name;
+ writeUserLocked(info);
+ }
}
- return users;
}
/**
@@ -105,9 +134,14 @@ public class UserManager {
}
private void readUserList() {
- mUsers = new SparseArray<UserInfo>();
+ synchronized (mUsers) {
+ readUserListLocked();
+ }
+ }
+
+ private void readUserListLocked() {
if (!mUserListFile.exists()) {
- fallbackToSingleUser();
+ fallbackToSingleUserLocked();
return;
}
FileInputStream fis = null;
@@ -123,7 +157,7 @@ public class UserManager {
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
- fallbackToSingleUser();
+ fallbackToSingleUserLocked();
return;
}
@@ -136,11 +170,11 @@ public class UserManager {
}
}
}
- updateUserIds();
+ updateUserIdsLocked();
} catch (IOException ioe) {
- fallbackToSingleUser();
+ fallbackToSingleUserLocked();
} catch (XmlPullParserException pe) {
- fallbackToSingleUser();
+ fallbackToSingleUserLocked();
} finally {
if (fis != null) {
try {
@@ -151,15 +185,15 @@ public class UserManager {
}
}
- private void fallbackToSingleUser() {
+ private void fallbackToSingleUserLocked() {
// Create the primary user
UserInfo primary = new UserInfo(0, "Primary",
UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
mUsers.put(0, primary);
- updateUserIds();
+ updateUserIdsLocked();
- writeUserList();
- writeUser(primary);
+ writeUserListLocked();
+ writeUserLocked(primary);
}
/*
@@ -169,7 +203,7 @@ public class UserManager {
* <name>Primary</name>
* </user>
*/
- private void writeUser(UserInfo userInfo) {
+ private void writeUserLocked(UserInfo userInfo) {
FileOutputStream fos = null;
try {
final File mUserFile = new File(mUsersDir, userInfo.id + ".xml");
@@ -213,7 +247,7 @@ public class UserManager {
* <user id="2"></user>
* </users>
*/
- private void writeUserList() {
+ private void writeUserListLocked() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mUserListFile);
@@ -306,17 +340,19 @@ public class UserManager {
return null;
}
- public UserInfo createUser(String name, int flags, List<ApplicationInfo> apps) {
+ public UserInfo createUser(String name, int flags) {
int userId = getNextAvailableId();
UserInfo userInfo = new UserInfo(userId, name, flags);
File userPath = new File(mBaseUserPath, Integer.toString(userId));
- if (!createPackageFolders(userId, userPath, apps)) {
+ if (!createPackageFolders(userId, userPath)) {
return null;
}
- mUsers.put(userId, userInfo);
- writeUserList();
- writeUser(userInfo);
- updateUserIds();
+ synchronized (mUsers) {
+ mUsers.put(userId, userInfo);
+ writeUserListLocked();
+ writeUserLocked(userInfo);
+ updateUserIdsLocked();
+ }
return userInfo;
}
@@ -325,7 +361,13 @@ public class UserManager {
* after the user's processes have been terminated.
* @param id the user's id
*/
- public void removeUser(int id) {
+ public boolean removeUser(int id) {
+ synchronized (mUsers) {
+ return removeUserLocked(id);
+ }
+ }
+
+ private boolean removeUserLocked(int id) {
// Remove from the list
UserInfo userInfo = mUsers.get(id);
if (userInfo != null) {
@@ -335,11 +377,11 @@ public class UserManager {
File userFile = new File(mUsersDir, id + ".xml");
userFile.delete();
// Update the user list
- writeUserList();
- // Remove the data directories for all packages for this user
- removePackageFolders(id);
- updateUserIds();
+ writeUserListLocked();
+ updateUserIdsLocked();
+ return true;
}
+ return false;
}
public void installPackageForAllUsers(String packageName, int uid) {
@@ -373,7 +415,7 @@ public class UserManager {
/**
* Caches the list of user ids in an array, adjusting the array size when necessary.
*/
- private void updateUserIds() {
+ private void updateUserIdsLocked() {
if (mUserIds == null || mUserIds.length != mUsers.size()) {
mUserIds = new int[mUsers.size()];
}
@@ -399,11 +441,10 @@ public class UserManager {
return i;
}
- private boolean createPackageFolders(int id, File userPath, final List<ApplicationInfo> apps) {
+ private boolean createPackageFolders(int id, File userPath) {
// mInstaller may not be available for unit-tests.
- if (mInstaller == null || apps == null) return true;
+ if (mInstaller == null) return true;
- final long startTime = SystemClock.elapsedRealtime();
// Create the user path
userPath.mkdir();
FileUtils.setPermissions(userPath.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
@@ -411,13 +452,10 @@ public class UserManager {
mInstaller.cloneUserData(0, id, false);
- final long stopTime = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG,
- "Time to create " + apps.size() + " packages = " + (stopTime - startTime) + "ms");
return true;
}
- private boolean removePackageFolders(int id) {
+ boolean removePackageFolders(int id) {
// mInstaller may not be available for unit-tests.
if (mInstaller == null) return true;
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index ed83fbe..c2ded8a 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -43,6 +43,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.provider.Settings;
@@ -206,6 +207,9 @@ public class UsbDeviceManager {
}
private static String addFunction(String functions, String function) {
+ if ("none".equals(functions)) {
+ return function;
+ }
if (!containsFunction(functions, function)) {
if (functions.length() > 0) {
functions += ",";
@@ -222,6 +226,9 @@ public class UsbDeviceManager {
split[i] = null;
}
}
+ if (split.length == 1 && split[0] == null) {
+ return "none";
+ }
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
String s = split[i];
@@ -365,11 +372,7 @@ public class UsbDeviceManager {
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
- try {
- // try again in 50ms
- Thread.sleep(50);
- } catch (InterruptedException e) {
- }
+ SystemClock.sleep(50);
}
Slog.e(TAG, "waitForState(" + state + ") FAILED");
return false;
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 67b667a..6269420 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -21,10 +21,12 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import com.android.server.wm.WindowManagerService.H;
import android.content.pm.ActivityInfo;
+import android.graphics.Matrix;
import android.os.Message;
import android.os.RemoteException;
import android.util.Slog;
import android.view.IApplicationToken;
+import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
@@ -49,14 +51,15 @@ class AppWindowToken extends WindowToken {
int groupId = -1;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-
+
// The input dispatching timeout for this application token in nanoseconds.
long inputDispatchingTimeoutNanos;
// These are used for determining when all windows associated with
// an activity have been drawn, so they can be made visible together
// at the same time.
- int lastTransactionSequence;
+ // initialize so that it doesn't match mTransactionSequence which is an int.
+ long lastTransactionSequence = Long.MIN_VALUE;
int numInterestingWindows;
int numDrawnWindows;
boolean inPendingTransaction;
@@ -89,6 +92,7 @@ class AppWindowToken extends WindowToken {
boolean animating;
Animation animation;
+ boolean animInitialized;
boolean hasTransformation;
final Transformation transformation = new Transformation();
@@ -104,6 +108,15 @@ class AppWindowToken extends WindowToken {
boolean startingMoved;
boolean firstWindowDrawn;
+ // Special surface for thumbnail animation.
+ Surface thumbnail;
+ int thumbnailTransactionSeq;
+ int thumbnailX;
+ int thumbnailY;
+ int thumbnailLayer;
+ Animation thumbnailAnimation;
+ final Transformation thumbnailTransformation = new Transformation();
+
// Input application handle used by the input dispatcher.
final InputApplicationHandle mInputApplicationHandle;
@@ -113,14 +126,14 @@ class AppWindowToken extends WindowToken {
appWindowToken = this;
appToken = _token;
mInputApplicationHandle = new InputApplicationHandle(this);
- lastTransactionSequence = service.mTransactionSequence-1;
}
- public void setAnimation(Animation anim) {
+ public void setAnimation(Animation anim, boolean initialized) {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
animation = anim;
animating = false;
+ animInitialized = initialized;
anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(service.mTransitionAnimationScale);
int zorder = anim.getZAdjustment();
@@ -135,6 +148,10 @@ class AppWindowToken extends WindowToken {
animLayerAdjustment = adj;
updateLayers();
}
+ // Start out animation gone if window is gone, or visible if window is visible.
+ transformation.clear();
+ transformation.setAlpha(reportedVisible ? 1 : 0);
+ hasTransformation = true;
}
public void setDummyAnimation() {
@@ -142,6 +159,7 @@ class AppWindowToken extends WindowToken {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "Setting dummy animation in " + this);
animation = WindowManagerService.sDummyAnimation;
+ animInitialized = false;
}
}
@@ -149,15 +167,28 @@ class AppWindowToken extends WindowToken {
if (animation != null) {
animation = null;
animating = true;
+ animInitialized = false;
+ }
+ clearThumbnail();
+ }
+
+ public void clearThumbnail() {
+ if (thumbnail != null) {
+ thumbnail.destroy();
+ thumbnail = null;
}
}
void updateLayers() {
final int N = allAppWindows.size();
final int adj = animLayerAdjustment;
+ thumbnailLayer = -1;
for (int i=0; i<N; i++) {
WindowState w = allAppWindows.get(i);
w.mAnimLayer = w.mLayer + adj;
+ if (w.mAnimLayer > thumbnailLayer) {
+ thumbnailLayer = w.mAnimLayer;
+ }
if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
+ w.mAnimLayer);
if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
@@ -186,16 +217,51 @@ class AppWindowToken extends WindowToken {
}
}
- void showAllWindowsLocked() {
+ boolean showAllWindowsLocked() {
+ boolean isAnimating = false;
final int NW = allAppWindows.size();
for (int i=0; i<NW; i++) {
WindowState w = allAppWindows.get(i);
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
"performing show on: " + w);
w.performShowLocked();
+ isAnimating |= w.mWinAnimator.isAnimating();
}
+ return isAnimating;
}
+ private void stepThumbnailAnimation(long currentTime) {
+ thumbnailTransformation.clear();
+ thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
+ thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
+ final boolean screenAnimation = service.mAnimator.mScreenRotationAnimation != null
+ && service.mAnimator.mScreenRotationAnimation.isAnimating();
+ if (screenAnimation) {
+ thumbnailTransformation.postCompose(
+ service.mAnimator.mScreenRotationAnimation.getEnterTransformation());
+ }
+ // cache often used attributes locally
+ final float tmpFloats[] = service.mTmpFloats;
+ thumbnailTransformation.getMatrix().getValues(tmpFloats);
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+ "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
+ + ", " + tmpFloats[Matrix.MTRANS_Y], null);
+ thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+ "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
+ + " layer=" + thumbnailLayer
+ + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
+ + "," + tmpFloats[Matrix.MSKEW_Y]
+ + "][" + tmpFloats[Matrix.MSKEW_X]
+ + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
+ thumbnail.setAlpha(thumbnailTransformation.getAlpha());
+ // The thumbnail is layered below the window immediately above this
+ // token's anim layer.
+ thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+ - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+ thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
+ tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
+ }
private boolean stepAnimation(long currentTime) {
if (animation == null) {
@@ -208,6 +274,7 @@ class AppWindowToken extends WindowToken {
": more=" + more + ", xform=" + transformation);
if (!more) {
animation = null;
+ clearThumbnail();
if (WindowManagerService.DEBUG_ANIM) Slog.v(
WindowManagerService.TAG, "Finished animation in " + this +
" @ " + currentTime);
@@ -218,7 +285,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.isScreenOnFully()) {
+ if (service.okToDisplay()) {
// We will run animations as long as the display isn't frozen.
if (animation == WindowManagerService.sDummyAnimation) {
@@ -236,12 +303,22 @@ class AppWindowToken extends WindowToken {
" @ " + currentTime + ": dw=" + dw + " dh=" + dh
+ " scale=" + service.mTransitionAnimationScale
+ " allDrawn=" + allDrawn + " animating=" + animating);
- animation.initialize(dw, dh, dw, dh);
+ if (!animInitialized) {
+ animation.initialize(dw, dh, dw, dh);
+ }
animation.setStartTime(currentTime);
animating = true;
+ if (thumbnail != null) {
+ thumbnail.show();
+ thumbnailAnimation.setStartTime(currentTime);
+ }
}
if (stepAnimation(currentTime)) {
- // we're done!
+ // animation isn't over, step any thumbnail and that's
+ // it for now.
+ if (thumbnail != null) {
+ stepThumbnailAnimation(currentTime);
+ }
return true;
}
}
@@ -259,6 +336,10 @@ class AppWindowToken extends WindowToken {
}
service.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ service.debugLayoutRepeats("AppWindowToken");
+ }
+
clearAnimation();
animating = false;
if (animLayerAdjustment != 0) {
@@ -277,7 +358,7 @@ class AppWindowToken extends WindowToken {
final int N = windows.size();
for (int i=0; i<N; i++) {
- windows.get(i).finishExit();
+ windows.get(i).mWinAnimator.finishExit();
}
updateReportedVisibilityLocked();
@@ -307,7 +388,7 @@ class AppWindowToken extends WindowToken {
if (WindowManagerService.DEBUG_VISIBILITY) {
Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
+ win.isDrawnLw()
- + ", isAnimating=" + win.isAnimating());
+ + ", isAnimating=" + win.mWinAnimator.isAnimating());
if (!win.isDrawnLw()) {
Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
+ " pv=" + win.mPolicyVisibility
@@ -317,17 +398,17 @@ class AppWindowToken extends WindowToken {
+ " th="
+ (win.mAppToken != null
? win.mAppToken.hiddenRequested : false)
- + " a=" + win.mAnimating);
+ + " a=" + win.mWinAnimator.mAnimating);
}
}
numInteresting++;
if (win.isDrawnLw()) {
numDrawn++;
- if (!win.isAnimating()) {
+ if (!win.mWinAnimator.isAnimating()) {
numVisible++;
}
nowGone = false;
- } else if (win.isAnimating()) {
+ } else if (win.mWinAnimator.isAnimating()) {
nowGone = false;
}
}
@@ -433,6 +514,15 @@ class AppWindowToken extends WindowToken {
pw.print(" startingDisplayed="); pw.print(startingDisplayed);
pw.print(" startingMoved"); pw.println(startingMoved);
}
+ if (thumbnail != null) {
+ pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
+ pw.print(" x="); pw.print(thumbnailX);
+ pw.print(" y="); pw.print(thumbnailY);
+ pw.print(" layer="); pw.println(thumbnailLayer);
+ pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
+ pw.print(prefix); pw.print("thumbnailTransformation=");
+ pw.println(thumbnailTransformation.toShortString());
+ }
}
@Override
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 40e452a..c915932 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -32,12 +32,14 @@ public class BlackFrame {
class BlackSurface {
final int left;
final int top;
+ final int layer;
final Surface surface;
BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b)
throws Surface.OutOfResourcesException {
left = l;
top = t;
+ this.layer = layer;
int w = r-l;
int h = b-t;
surface = new Surface(session, 0, "BlackSurface",
@@ -45,8 +47,6 @@ public class BlackFrame {
if (WindowManagerService.SHOW_TRANSACTIONS ||
WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
" BLACK " + surface + ": CREATE layer=" + layer);
- surface.setAlpha(1.0f);
- surface.setLayer(layer);
}
void setMatrix(Matrix matrix) {
@@ -58,6 +58,8 @@ public class BlackFrame {
surface.setMatrix(
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
+ surface.setAlpha(1.0f);
+ surface.setLayer(layer);
if (false) {
Slog.i(WindowManagerService.TAG, "Black Surface @ (" + left + "," + top + "): ("
+ mTmpFloats[Matrix.MTRANS_X] + ","
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index a9d4e01..d8f2254 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -82,7 +82,7 @@ class DimAnimator {
/**
* Set's the dim surface's layer and update dim parameters that will be used in
- * {@link updateSurface} after all windows are examined.
+ * {@link #updateSurface} after all windows are examined.
*/
void updateParameters(Resources res, WindowState w, long currentTime) {
mDimSurface.setLayer(w.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
@@ -94,15 +94,15 @@ class DimAnimator {
// If the desired dim level has changed, then
// start an animation to it.
mLastDimAnimTime = currentTime;
- long duration = (w.mAnimating && w.mAnimation != null)
- ? w.mAnimation.computeDurationHint()
+ long duration = (w.mWinAnimator.mAnimating && w.mWinAnimator.mAnimation != null)
+ ? w.mWinAnimator.mAnimation.computeDurationHint()
: WindowManagerService.DEFAULT_DIM_DURATION;
if (target > mDimTargetAlpha) {
TypedValue tv = new TypedValue();
res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
tv, true);
if (tv.type == TypedValue.TYPE_FRACTION) {
- duration = (long)tv.getFraction((float)duration, (float)duration);
+ duration = (long)tv.getFraction(duration, duration);
} else if (tv.type >= TypedValue.TYPE_FIRST_INT
&& tv.type <= TypedValue.TYPE_LAST_INT) {
duration = tv.data;
@@ -130,33 +130,31 @@ class DimAnimator {
}
}
- boolean animating = false;
- if (mLastDimAnimTime != 0) {
+ boolean animating = mLastDimAnimTime != 0;
+ if (animating) {
mDimCurrentAlpha += mDimDeltaPerMs
* (currentTime-mLastDimAnimTime);
- boolean more = true;
if (displayFrozen) {
// If the display is frozen, there is no reason to animate.
- more = false;
+ animating = false;
} else if (mDimDeltaPerMs > 0) {
if (mDimCurrentAlpha > mDimTargetAlpha) {
- more = false;
+ animating = false;
}
} else if (mDimDeltaPerMs < 0) {
if (mDimCurrentAlpha < mDimTargetAlpha) {
- more = false;
+ animating = false;
}
} else {
- more = false;
+ animating = false;
}
// Do we need to continue animating?
- if (more) {
+ if (animating) {
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ mDimSurface + ": alpha=" + mDimCurrentAlpha);
mLastDimAnimTime = currentTime;
mDimSurface.setAlpha(mDimCurrentAlpha);
- animating = true;
} else {
mDimCurrentAlpha = mDimTargetAlpha;
mLastDimAnimTime = 0;
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
new file mode 100644
index 0000000..81e0a17
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -0,0 +1,629 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+import com.android.internal.policy.impl.PhoneWindowManager;
+
+/**
+ * @author cmautner@google.com (Craig Mautner)
+ * Singleton class that carries out the animations and Surface operations in a separate task
+ * on behalf of WindowManagerService.
+ */
+public class WindowAnimator {
+ private static final String TAG = "WindowAnimator";
+
+ final WindowManagerService mService;
+ final Context mContext;
+ final WindowManagerPolicy mPolicy;
+
+ boolean mAnimating;
+ boolean mUpdateRotation;
+ boolean mTokenMayBeDrawn;
+ boolean mForceHiding;
+ WindowState mWindowAnimationBackground;
+ int mWindowAnimationBackgroundColor;
+ int mAdjResult;
+
+ int mPendingLayoutChanges;
+
+ /** Overall window dimensions */
+ int mDw, mDh;
+
+ /** Interior window dimensions */
+ int mInnerDw, mInnerDh;
+
+ /** Time of current animation step. Reset on each iteration */
+ long mCurrentTime;
+
+ /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
+ * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
+ private int mTransactionSequence;
+
+ /** The one and only screen rotation if one is happening */
+ ScreenRotationAnimation mScreenRotationAnimation = null;
+
+ WindowAnimator(final WindowManagerService service, final Context context,
+ final WindowManagerPolicy policy) {
+ mService = service;
+ mContext = context;
+ mPolicy = policy;
+ }
+
+ private void updateWindowsAppsAndRotationAnimationsLocked() {
+ int i;
+ final int NAT = mService.mAppTokens.size();
+ for (i=0; i<NAT; i++) {
+ final AppWindowToken appToken = mService.mAppTokens.get(i);
+ final boolean wasAnimating = appToken.animation != null
+ && appToken.animation != WindowManagerService.sDummyAnimation;
+ if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+ mAnimating = true;
+ } else if (wasAnimating) {
+ // stopped animating, do one more pass through the layout
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("appToken " + appToken + " done");
+ }
+ }
+ }
+
+ final int NEAT = mService.mExitingAppTokens.size();
+ for (i=0; i<NEAT; i++) {
+ final AppWindowToken appToken = mService.mExitingAppTokens.get(i);
+ final boolean wasAnimating = appToken.animation != null
+ && appToken.animation != WindowManagerService.sDummyAnimation;
+ if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+ mAnimating = true;
+ } else if (wasAnimating) {
+ // stopped animating, do one more pass through the layout
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("exiting appToken " + appToken + " done");
+ }
+ }
+ }
+
+ if (mScreenRotationAnimation != null &&
+ (mScreenRotationAnimation.isAnimating() ||
+ mScreenRotationAnimation.mFinishAnimReady)) {
+ if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+ mUpdateRotation = false;
+ mAnimating = true;
+ } else {
+ mUpdateRotation = true;
+ mScreenRotationAnimation.kill();
+ mScreenRotationAnimation = null;
+ }
+ }
+ }
+
+ private void updateWindowsAndWallpaperLocked() {
+ ++mTransactionSequence;
+
+ for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
+ WindowState w = mService.mWindows.get(i);
+ WindowStateAnimator winAnimator = w.mWinAnimator;
+
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+
+ if (w.mSurface != null) {
+ // Take care of the window being ready to display.
+ if (w.commitFinishDrawingLocked(mCurrentTime)) {
+ if ((w.mAttrs.flags
+ & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+ if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+ "First draw done in potential wallpaper target " + w);
+ mService.mInnerFields.mWallpaperMayChange = true;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 1");
+ }
+ }
+ }
+
+ // If the window has moved due to its containing
+ // content frame changing, then we'd like to animate
+ // it. The checks here are ordered by what is least
+ // likely to be true first.
+ if (w.shouldAnimateMove()) {
+ // Frame has moved, containing content frame
+ // has also moved, and we're not currently animating...
+ // let's do something.
+ Animation a = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.window_move_from_decor);
+ winAnimator.setAnimation(a);
+ w.mAnimDw = w.mLastFrame.left - w.mFrame.left;
+ w.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+ } else {
+ w.mAnimDw = mInnerDw;
+ w.mAnimDh = mInnerDh;
+ }
+
+ final boolean wasAnimating = winAnimator.mWasAnimating;
+ final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
+
+ if (WindowManagerService.DEBUG_WALLPAPER) {
+ Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
+ ", nowAnimating=" + nowAnimating);
+ }
+
+ // If this window is animating, make a note that we have
+ // an animating window and take care of a request to run
+ // a detached wallpaper animation.
+ if (nowAnimating) {
+ if (winAnimator.mAnimation != null) {
+ if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+ && winAnimator.mAnimation.getDetachWallpaper()) {
+ mService.mInnerFields.mDetachedWallpaper = w;
+ }
+ if (winAnimator.mAnimation.getBackgroundColor() != 0) {
+ if (mWindowAnimationBackground == null
+ || (w.mAnimLayer < mWindowAnimationBackground.mAnimLayer)) {
+ mWindowAnimationBackground = w;
+ mWindowAnimationBackgroundColor =
+ winAnimator.mAnimation.getBackgroundColor();
+ }
+ }
+ }
+ mAnimating = true;
+ }
+
+ // If this window's app token is running a detached wallpaper
+ // animation, make a note so we can ensure the wallpaper is
+ // displayed behind it.
+ if (w.mAppToken != null && w.mAppToken.animation != null
+ && w.mAppToken.animating) {
+ if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+ && w.mAppToken.animation.getDetachWallpaper()) {
+ mService.mInnerFields.mDetachedWallpaper = w;
+ }
+ if (w.mAppToken.animation.getBackgroundColor() != 0) {
+ if (mWindowAnimationBackground == null
+ || (w.mAnimLayer <
+ mWindowAnimationBackground.mAnimLayer)) {
+ mWindowAnimationBackground = w;
+ mWindowAnimationBackgroundColor =
+ w.mAppToken.animation.getBackgroundColor();
+ }
+ }
+ }
+
+ if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == w) {
+ mService.mInnerFields.mWallpaperMayChange = true;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2");
+ }
+ }
+
+ if (mPolicy.doesForceHide(w, attrs)) {
+ if (!wasAnimating && nowAnimating) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "Animation started that could impact force hide: "
+ + w);
+ mService.mInnerFields.mWallpaperForceHidingChanged = true;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3");
+ }
+ mService.mFocusMayChange = true;
+ } else if (w.isReadyForDisplay() && winAnimator.mAnimation == null) {
+ mForceHiding = true;
+ }
+ } else if (mPolicy.canBeForceHidden(w, attrs)) {
+ boolean changed;
+ if (mForceHiding) {
+ changed = w.hideLw(false, false);
+ if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+ "Now policy hidden: " + w);
+ } else {
+ changed = w.showLw(false, false);
+ if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+ "Now policy shown: " + w);
+ if (changed) {
+ if (mService.mInnerFields.mWallpaperForceHidingChanged
+ && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
+ // Assume we will need to animate. If
+ // we don't (because the wallpaper will
+ // stay with the lock screen), then we will
+ // clean up later.
+ Animation a = mPolicy.createForceHideEnterAnimation();
+ if (a != null) {
+ winAnimator.setAnimation(a);
+ }
+ }
+ if (mCurrentFocus == null || mCurrentFocus.mLayer < w.mLayer) {
+ // We are showing on to of the current
+ // focus, so re-evaluate focus to make
+ // sure it is correct.
+ mService.mFocusMayChange = true;
+ }
+ }
+ }
+ if (changed && (attrs.flags
+ & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+ mService.mInnerFields.mWallpaperMayChange = true;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4");
+ }
+ }
+ }
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
+ if (atoken.lastTransactionSequence != mTransactionSequence) {
+ atoken.lastTransactionSequence = mTransactionSequence;
+ atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+ atoken.startingDisplayed = false;
+ }
+ if ((w.isOnScreen() || w.mAttrs.type
+ == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
+ && !w.mExiting && !w.mDestroying) {
+ if (WindowManagerService.DEBUG_VISIBILITY ||
+ WindowManagerService.DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Eval win " + w + ": isDrawn="
+ + w.isDrawnLw()
+ + ", isAnimating=" + winAnimator.isAnimating());
+ if (!w.isDrawnLw()) {
+ Slog.v(TAG, "Not displayed: s=" + w.mSurface
+ + " pv=" + w.mPolicyVisibility
+ + " dp=" + w.mDrawPending
+ + " cdp=" + w.mCommitDrawPending
+ + " ah=" + w.mAttachedHidden
+ + " th=" + atoken.hiddenRequested
+ + " a=" + winAnimator.mAnimating);
+ }
+ }
+ if (w != atoken.startingWindow) {
+ if (!atoken.freezingScreen || !w.mAppFreezing) {
+ atoken.numInterestingWindows++;
+ if (w.isDrawnLw()) {
+ atoken.numDrawnWindows++;
+ if (WindowManagerService.DEBUG_VISIBILITY ||
+ WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+ "tokenMayBeDrawn: " + atoken
+ + " freezingScreen=" + atoken.freezingScreen
+ + " mAppFreezing=" + w.mAppFreezing);
+ mTokenMayBeDrawn = true;
+ }
+ }
+ } else if (w.isDrawnLw()) {
+ atoken.startingDisplayed = true;
+ }
+ }
+ } else if (w.mReadyToShow) {
+ if (w.performShowLocked()) {
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5");
+ }
+ }
+ }
+ if (atoken != null && atoken.thumbnail != null) {
+ if (atoken.thumbnailTransactionSeq != mTransactionSequence) {
+ atoken.thumbnailTransactionSeq = mTransactionSequence;
+ atoken.thumbnailLayer = 0;
+ }
+ if (atoken.thumbnailLayer < w.mAnimLayer) {
+ atoken.thumbnailLayer = w.mAnimLayer;
+ }
+ }
+ } // end forall windows
+ }
+
+ private void testTokenMayBeDrawnLocked() {
+ // See if any windows have been drawn, so they (and others
+ // associated with them) can now be shown.
+ final int NT = mService.mAppTokens.size();
+ for (int i=0; i<NT; i++) {
+ AppWindowToken wtoken = mService.mAppTokens.get(i);
+ if (wtoken.freezingScreen) {
+ int numInteresting = wtoken.numInterestingWindows;
+ if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "allDrawn: " + wtoken
+ + " interesting=" + numInteresting
+ + " drawn=" + wtoken.numDrawnWindows);
+ wtoken.showAllWindowsLocked();
+ mService.unsetAppFreezingScreenLocked(wtoken, false, true);
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
+ "Setting mOrientationChangeComplete=true because wtoken "
+ + wtoken + " numInteresting=" + numInteresting
+ + " numDrawn=" + wtoken.numDrawnWindows);
+ mService.mInnerFields.mOrientationChangeComplete = true;
+ }
+ } else if (!wtoken.allDrawn) {
+ int numInteresting = wtoken.numInterestingWindows;
+ if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "allDrawn: " + wtoken
+ + " interesting=" + numInteresting
+ + " drawn=" + wtoken.numDrawnWindows);
+ wtoken.allDrawn = true;
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("testTokenMayBeDrawnLocked");
+ }
+
+ // We can now show all of the drawn windows!
+ if (!mService.mOpeningApps.contains(wtoken)) {
+ mAnimating |= wtoken.showAllWindowsLocked();
+ }
+ }
+ }
+ }
+ }
+
+ private void performAnimationsLocked() {
+ if (WindowManagerService.DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
+ + mTransactionSequence + " mAnimating="
+ + mAnimating);
+
+ mTokenMayBeDrawn = false;
+ mService.mInnerFields.mWallpaperMayChange = false;
+ mForceHiding = false;
+ mService.mInnerFields.mDetachedWallpaper = null;
+ mWindowAnimationBackground = null;
+ mWindowAnimationBackgroundColor = 0;
+
+ updateWindowsAndWallpaperLocked();
+
+ if (mTokenMayBeDrawn) {
+ testTokenMayBeDrawnLocked();
+ }
+
+ if (WindowManagerService.DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
+ + Integer.toHexString(mPendingLayoutChanges));
+ }
+
+ public void prepareSurfaceLocked(final WindowState w, final boolean recoveringMemory) {
+ if (w.mSurface == null) {
+ if (w.mOrientationChanging) {
+ if (WindowManagerService.DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Orientation change skips hidden " + w);
+ }
+ w.mOrientationChanging = false;
+ }
+ return;
+ }
+
+ boolean displayed = false;
+
+ w.computeShownFrameLocked();
+
+ int width, height;
+ if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+ // for a scaled surface, we just want to use
+ // the requested size.
+ width = w.mRequestedWidth;
+ height = w.mRequestedHeight;
+ } else {
+ width = w.mCompatFrame.width();
+ height = w.mCompatFrame.height();
+ }
+
+ if (width < 1) {
+ width = 1;
+ }
+ if (height < 1) {
+ height = 1;
+ }
+ final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
+ if (surfaceResized) {
+ w.mSurfaceW = width;
+ w.mSurfaceH = height;
+ }
+
+ if (w.mSurfaceX != w.mShownFrame.left
+ || w.mSurfaceY != w.mShownFrame.top) {
+ try {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "POS " + w.mShownFrame.left
+ + ", " + w.mShownFrame.top, null);
+ w.mSurfaceX = w.mShownFrame.left;
+ w.mSurfaceY = w.mShownFrame.top;
+ w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error positioning surface of " + w
+ + " pos=(" + w.mShownFrame.left
+ + "," + w.mShownFrame.top + ")", e);
+ if (!recoveringMemory) {
+ mService.reclaimSomeSurfaceMemoryLocked(w, "position", true);
+ }
+ }
+ }
+
+ if (surfaceResized) {
+ try {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "SIZE " + width + "x" + height, null);
+ w.mSurfaceResized = true;
+ w.mSurface.setSize(width, height);
+ } catch (RuntimeException e) {
+ // If something goes wrong with the surface (such
+ // as running out of memory), don't take down the
+ // entire system.
+ Slog.e(TAG, "Error resizing surface of " + w
+ + " size=(" + width + "x" + height + ")", e);
+ if (!recoveringMemory) {
+ mService.reclaimSomeSurfaceMemoryLocked(w, "size", true);
+ }
+ }
+ }
+
+ if (w.mAttachedHidden || !w.isReadyForDisplay()) {
+ if (!w.mLastHidden) {
+ //dump();
+ w.mLastHidden = true;
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "HIDE (performLayout)", null);
+ if (w.mSurface != null) {
+ w.mSurfaceShown = false;
+ try {
+ w.mSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Exception hiding surface in " + w);
+ }
+ }
+ }
+ // If we are waiting for this window to handle an
+ // orientation change, well, it is hidden, so
+ // doesn't really matter. Note that this does
+ // introduce a potential glitch if the window
+ // becomes unhidden before it has drawn for the
+ // new orientation.
+ if (w.mOrientationChanging) {
+ w.mOrientationChanging = false;
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+ "Orientation change skips hidden " + w);
+ }
+ } else if (w.mLastLayer != w.mAnimLayer
+ || w.mLastAlpha != w.mShownAlpha
+ || w.mLastDsDx != w.mDsDx
+ || w.mLastDtDx != w.mDtDx
+ || w.mLastDsDy != w.mDsDy
+ || w.mLastDtDy != w.mDtDy
+ || w.mLastHScale != w.mHScale
+ || w.mLastVScale != w.mVScale
+ || w.mLastHidden) {
+ displayed = true;
+ w.mLastAlpha = w.mShownAlpha;
+ w.mLastLayer = w.mAnimLayer;
+ w.mLastDsDx = w.mDsDx;
+ w.mLastDtDx = w.mDtDx;
+ w.mLastDsDy = w.mDsDy;
+ w.mLastDtDy = w.mDtDy;
+ w.mLastHScale = w.mHScale;
+ w.mLastVScale = w.mVScale;
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
+ + " matrix=[" + (w.mDsDx*w.mHScale)
+ + "," + (w.mDtDx*w.mVScale)
+ + "][" + (w.mDsDy*w.mHScale)
+ + "," + (w.mDtDy*w.mVScale) + "]", null);
+ if (w.mSurface != null) {
+ try {
+ w.mSurfaceAlpha = w.mShownAlpha;
+ w.mSurface.setAlpha(w.mShownAlpha);
+ w.mSurfaceLayer = w.mAnimLayer;
+ w.mSurface.setLayer(w.mAnimLayer);
+ w.mSurface.setMatrix(
+ w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
+ w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error updating surface in " + w, e);
+ if (!recoveringMemory) {
+ mService.reclaimSomeSurfaceMemoryLocked(w, "update", true);
+ }
+ }
+ }
+
+ if (w.mLastHidden && w.isDrawnLw()
+ && !w.mReadyToShow) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "SHOW (performLayout)", null);
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
+ + " during relayout");
+ if (mService.showSurfaceRobustlyLocked(w)) {
+ w.mHasDrawn = true;
+ w.mLastHidden = false;
+ } else {
+ w.mOrientationChanging = false;
+ }
+ }
+ if (w.mSurface != null) {
+ w.mToken.hasVisible = true;
+ }
+ } else {
+ displayed = true;
+ }
+
+ if (displayed) {
+ if (w.mOrientationChanging) {
+ if (!w.isDrawnLw()) {
+ mService.mInnerFields.mOrientationChangeComplete = false;
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+ "Orientation continue waiting for draw in " + w);
+ } else {
+ w.mOrientationChanging = false;
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+ "Orientation change complete in " + w);
+ }
+ }
+ w.mToken.hasVisible = true;
+ }
+ }
+
+ void animate() {
+ mPendingLayoutChanges = 0;
+ mCurrentTime = SystemClock.uptimeMillis();
+
+ // Update animations of all applications, including those
+ // associated with exiting/removed apps
+ Surface.openTransaction();
+
+ try {
+ updateWindowsAppsAndRotationAnimationsLocked();
+ performAnimationsLocked();
+
+ // THIRD LOOP: Update the surfaces of all windows.
+
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.updateSurfaces();
+ }
+
+ final int N = mService.mWindows.size();
+ for (int i=N-1; i>=0; i--) {
+ WindowState w = mService.mWindows.get(i);
+ prepareSurfaceLocked(w, true);
+ }
+
+ if (mService.mDimAnimator != null && mService.mDimAnimator.mDimShown) {
+ mAnimating |= mService.mDimAnimator.updateSurface(mService.mInnerFields.mDimming,
+ mCurrentTime, !mService.okToDisplay());
+ }
+
+ if (mService.mBlackFrame != null) {
+ if (mScreenRotationAnimation != null) {
+ mService.mBlackFrame.setMatrix(
+ mScreenRotationAnimation.getEnterTransformation().getMatrix());
+ } else {
+ mService.mBlackFrame.clearMatrix();
+ }
+ }
+ } catch (RuntimeException e) {
+ Log.wtf(TAG, "Unhandled exception in Window Manager", e);
+ } finally {
+ Surface.closeTransaction();
+ }
+ }
+
+ WindowState mCurrentFocus;
+ void setCurrentFocus(WindowState currentFocus) {
+ mCurrentFocus = currentFocus;
+ }
+
+ void setDisplayDimensions(final int curWidth, final int curHeight,
+ final int appWidth, final int appHeight) {
+ mDw = curWidth;
+ mDh = curHeight;
+ mInnerDw = appWidth;
+ mInnerDh = appHeight;
+ }
+
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 6993657..9635b33 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -18,7 +18,6 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
@@ -90,6 +89,7 @@ import android.os.TokenWatcher;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
+import android.util.FloatMath;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -118,8 +118,12 @@ import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerPolicy.FakeWindow;
+import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation;
import java.io.BufferedWriter;
@@ -167,13 +171,14 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_SCREEN_ON = false;
static final boolean DEBUG_SCREENSHOT = false;
static final boolean DEBUG_BOOT = false;
+ static final boolean DEBUG_LAYOUT_REPEATS = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
static final boolean HIDE_STACK_CRAWLS = true;
+ static final int LAYOUT_REPEAT_THRESHOLD = 4;
static final boolean PROFILE_ORIENTATION = false;
- static final boolean BLUR = true;
static final boolean localLOGV = DEBUG;
/** How much to multiply the policy's type layer, to reserve room
@@ -201,6 +206,13 @@ public class WindowManagerService extends IWindowManager.Stub
static final int LAYER_OFFSET_BLUR = 2;
/**
+ * Animation thumbnail is as far as possible below the window above
+ * the thumbnail (or in other words as far as possible above the window
+ * below it).
+ */
+ static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
+
+ /**
* Layer at which to put the rotation freeze snapshot.
*/
static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
@@ -415,17 +427,12 @@ public class WindowManagerService extends IWindowManager.Stub
IInputMethodManager mInputMethodManager;
SurfaceSession mFxSession;
- private DimAnimator mDimAnimator = null;
- Surface mBlurSurface;
- boolean mBlurShown;
+ DimAnimator mDimAnimator = null;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
- ScreenRotationAnimation mScreenRotationAnimation;
BlackFrame mBlackFrame;
- int mTransactionSequence = 0;
-
final float[] mTmpFloats = new float[9];
boolean mSafeMode;
@@ -491,8 +498,12 @@ public class WindowManagerService extends IWindowManager.Stub
// made visible or hidden at the next transition.
int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
String mNextAppTransitionPackage;
+ Bitmap mNextAppTransitionThumbnail;
+ IRemoteCallback mNextAppTransitionCallback;
int mNextAppTransitionEnter;
int mNextAppTransitionExit;
+ int mNextAppTransitionStartX;
+ int mNextAppTransitionStartY;
boolean mAppTransitionReady = false;
boolean mAppTransitionRunning = false;
boolean mAppTransitionTimeout = false;
@@ -584,27 +595,24 @@ public class WindowManagerService extends IWindowManager.Stub
/** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
* methods. */
- private class LayoutAndSurfaceFields {
- private boolean mAnimating = false;
- private boolean mWallpaperForceHidingChanged = false;
- private boolean mTokenMayBeDrawn = false;
- private boolean mWallpaperMayChange = false;
- private boolean mForceHiding = false;
- private WindowState mDetachedWallpaper = null;
- private WindowState mWindowAnimationBackground = null;
- private int mWindowAnimationBackgroundColor = 0;
- private boolean mOrientationChangeComplete = true;
+ class LayoutAndSurfaceFields {
+ boolean mWallpaperForceHidingChanged = false;
+ boolean mWallpaperMayChange = false;
+ WindowState mDetachedWallpaper = null;
+ boolean mOrientationChangeComplete = true;
private int mAdjResult = 0;
private Session mHoldScreen = null;
private boolean mObscured = false;
- private boolean mBlurring = false;
- private boolean mDimming = false;
+ boolean mDimming = false;
private boolean mSyswin = false;
private float mScreenBrightness = -1;
private float mButtonBrightness = -1;
private boolean mUpdateRotation = false;
}
- private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
+ LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
+
+ /** Only do a maximum of 6 repeated layouts. After that quit */
+ private int mLayoutRepeatCount;
private final class AnimationRunnable implements Runnable {
@Override
@@ -617,6 +625,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
boolean mAnimationScheduled;
+
+ final WindowAnimator mAnimator;
final class DragInputEventReceiver extends InputEventReceiver {
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
@@ -735,6 +745,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAllowBootMessages = allowBootMsgs;
}
+ @Override
public void run() {
Looper.prepare();
WindowManagerService s = new WindowManagerService(mContext, mPM,
@@ -774,6 +785,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPM = pm;
}
+ @Override
public void run() {
Looper.prepare();
WindowManagerPolicyThread.set(this, Looper.myLooper());
@@ -836,6 +848,7 @@ public class WindowManagerService extends IWindowManager.Stub
mHoldingScreenWakeLock.setReferenceCounted(false);
mInputManager = new InputManager(context, this);
+ mAnimator = new WindowAnimator(this, context, mPolicy);
PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
thr.start();
@@ -1225,7 +1238,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (highestTarget != null) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
+ mNextAppTransition + " " + highestTarget
- + " animating=" + highestTarget.isAnimating()
+ + " animating=" + highestTarget.mWinAnimator.isAnimating()
+ " layer=" + highestTarget.mAnimLayer
+ " new layer=" + w.mAnimLayer);
@@ -1235,7 +1248,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInputMethodTargetWaitingAnim = true;
mInputMethodTarget = highestTarget;
return highestPos + 1;
- } else if (highestTarget.isAnimating() &&
+ } else if (highestTarget.mWinAnimator.isAnimating() &&
highestTarget.mAnimLayer > w.mAnimLayer) {
// If the window we are currently targeting is involved
// with an animation, and it is on top of the next target
@@ -1588,7 +1601,7 @@ public class WindowManagerService extends IWindowManager.Stub
foundI = i;
if (w == mWallpaperTarget && ((w.mAppToken != null
&& w.mAppToken.animation != null)
- || w.mAnimation != null)) {
+ || w.mWinAnimator.mAnimation != null)) {
// The current wallpaper target is animating, so we'll
// look behind it for another possible target and figure
// out what is going on below.
@@ -1645,9 +1658,9 @@ public class WindowManagerService extends IWindowManager.Stub
// Now what is happening... if the current and new targets are
// animating, then we are in our super special mode!
if (foundW != null && oldW != null) {
- boolean oldAnim = oldW.mAnimation != null
+ boolean oldAnim = oldW.mWinAnimator.mAnimation != null
|| (oldW.mAppToken != null && oldW.mAppToken.animation != null);
- boolean foundAnim = foundW.mAnimation != null
+ boolean foundAnim = foundW.mWinAnimator.mAnimation != null
|| (foundW.mAppToken != null && foundW.mAppToken.animation != null);
if (DEBUG_WALLPAPER) {
Slog.v(TAG, "New animation: " + foundAnim
@@ -1699,10 +1712,10 @@ public class WindowManagerService extends IWindowManager.Stub
} else if (mLowerWallpaperTarget != null) {
// Is it time to stop animating?
- boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
+ boolean lowerAnimating = mLowerWallpaperTarget.mWinAnimator.mAnimation != null
|| (mLowerWallpaperTarget.mAppToken != null
&& mLowerWallpaperTarget.mAppToken.animation != null);
- boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
+ boolean upperAnimating = mUpperWallpaperTarget.mWinAnimator.mAnimation != null
|| (mUpperWallpaperTarget.mAppToken != null
&& mUpperWallpaperTarget.mAppToken.animation != null);
if (!lowerAnimating || !upperAnimating) {
@@ -1910,7 +1923,7 @@ public class WindowManagerService extends IWindowManager.Stub
rawChanged = true;
}
- if (rawChanged && (wallpaperWin.getAttrs().privateFlags &
+ if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
try {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
@@ -2217,7 +2230,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mInTouchMode) {
res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
}
- if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
+ if (win.mAppToken == null || !win.mAppToken.clientHidden) {
res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
}
@@ -2284,13 +2297,13 @@ public class WindowManagerService extends IWindowManager.Stub
+ ", surface=" + win.mSurface);
final long origId = Binder.clearCallingIdentity();
-
+
win.disposeInputChannel();
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Remove " + win + ": mSurface=" + win.mSurface
+ " mExiting=" + win.mExiting
- + " isAnimating=" + win.isAnimating()
+ + " isAnimating=" + win.mWinAnimator.isAnimating()
+ " app-animation="
+ (win.mAppToken != null ? win.mAppToken.animation : null)
+ " inPendingTransaction="
@@ -2302,14 +2315,14 @@ 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.isScreenOnFully()) {
+ if (win.mSurface != null && okToDisplay()) {
// If we are not currently running the exit animation, we
// need to see about starting one.
- if (wasVisible=win.isWinVisibleLw()) {
+ wasVisible = win.isWinVisibleLw();
+ if (wasVisible) {
int transit = WindowManagerPolicy.TRANSIT_EXIT;
- if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
+ if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
}
// Try starting an animation.
@@ -2317,7 +2330,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mExiting = true;
}
}
- if (win.mExiting || win.isAnimating()) {
+ if (win.mExiting || win.mWinAnimator.isAnimating()) {
// The exit animation is running... wait for it!
//Slog.i(TAG, "*** Running exit animation...");
win.mExiting = true;
@@ -2454,6 +2467,15 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.i(TAG, str);
}
}
+
+ static void logSurface(Surface s, String title, String msg, RuntimeException where) {
+ String str = " SURFACE " + s + ": " + msg + " / " + title;
+ if (where != null) {
+ Slog.i(TAG, str, where);
+ } else {
+ Slog.i(TAG, str);
+ }
+ }
void setTransparentRegionWindow(Session session, IWindow client, Region region) {
long origId = Binder.clearCallingIdentity();
@@ -2677,7 +2699,7 @@ public class WindowManagerService extends IWindowManager.Stub
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
displayed = !win.isVisibleLw();
if (win.mExiting) {
- win.cancelExitAnimationForNextAnimationLocked();
+ win.mWinAnimator.cancelExitAnimationForNextAnimationLocked();
}
if (win.mDestroying) {
win.mDestroying = false;
@@ -2687,8 +2709,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mEnterAnimationPending = true;
}
if (displayed) {
- if (win.isDrawnLw() && !mDisplayFrozen
- && mDisplayEnabled && mPolicy.isScreenOnFully()) {
+ if (win.isDrawnLw() && okToDisplay()) {
applyEnterAnimationLocked(win);
}
if ((win.mAttrs.flags
@@ -2775,14 +2796,14 @@ public class WindowManagerService extends IWindowManager.Stub
// Try starting an animation; if there isn't one, we
// can destroy the surface right away.
int transit = WindowManagerPolicy.TRANSIT_EXIT;
- if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
+ if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
}
if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
applyAnimationLocked(win, transit, false)) {
focusMayChange = true;
win.mExiting = true;
- } else if (win.isAnimating()) {
+ } else if (win.mWinAnimator.isAnimating()) {
// Currently in a hide animation... turn this into
// an exit.
win.mExiting = true;
@@ -2791,7 +2812,7 @@ public class WindowManagerService extends IWindowManager.Stub
// window, we need to change both of them inside
// of a transaction to avoid artifacts.
win.mExiting = true;
- win.mAnimating = true;
+ win.mWinAnimator.mAnimating = true;
} else {
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
@@ -3005,7 +3026,8 @@ public class WindowManagerService extends IWindowManager.Stub
*/
boolean applyAnimationLocked(WindowState win,
int transit, boolean isEntrance) {
- if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
+ if (win.mWinAnimator.mLocalAnimating &&
+ win.mWinAnimator.mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
return true;
@@ -3015,7 +3037,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.isScreenOnFully()) {
+ if (okToDisplay()) {
int anim = mPolicy.selectAnimationLw(win, transit);
int attr = -1;
Animation a = null;
@@ -3042,7 +3064,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
- + " mAnimation=" + win.mAnimation
+ + " mAnimation=" + win.mWinAnimator.mAnimation
+ " isEntrance=" + isEntrance);
if (a != null) {
if (DEBUG_ANIM) {
@@ -3053,14 +3075,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
}
- win.setAnimation(a);
- win.mAnimationIsEntrance = isEntrance;
+ win.mWinAnimator.setAnimation(a);
+ win.mWinAnimator.mAnimationIsEntrance = isEntrance;
}
} else {
- win.clearAnimation();
+ win.mWinAnimator.clearAnimation();
}
- return win.mAnimation != null;
+ return win.mWinAnimator.mAnimation != null;
}
private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
@@ -3095,15 +3117,76 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
+ private Animation createThumbnailAnimationLocked(int transit,
+ boolean enter, boolean thumb) {
+ Animation a;
+ final float thumbWidth = mNextAppTransitionThumbnail.getWidth();
+ final float thumbHeight = mNextAppTransitionThumbnail.getHeight();
+ // Pick the desired duration. If this is an inter-activity transition,
+ // it is the standard duration for that. Otherwise we use the longer
+ // task transition duration.
+ int duration;
+ switch (transit) {
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
+ duration = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_shortAnimTime);
+ break;
+ default:
+ duration = 500;
+ break;
+
+ }
+ if (thumb) {
+ // Animation for zooming thumbnail from its initial size to
+ // filling the screen.
+ Animation scale = new ScaleAnimation(
+ 1, mAppDisplayWidth/thumbWidth,
+ 1, mAppDisplayHeight/thumbHeight,
+ mNextAppTransitionStartX + thumbWidth/2,
+ mNextAppTransitionStartY + thumbHeight/2);
+ AnimationSet set = new AnimationSet(true);
+ Animation alpha = new AlphaAnimation(1, 0);
+ scale.setDuration(duration);
+ set.addAnimation(scale);
+ alpha.setDuration(duration);
+ set.addAnimation(alpha);
+ a = set;
+ } else if (enter) {
+ // Entering app zooms out from the center of the thumbnail.
+ a = new ScaleAnimation(
+ thumbWidth/mAppDisplayWidth, 1,
+ thumbHeight/mAppDisplayHeight, 1,
+ mNextAppTransitionStartX + thumbWidth/2,
+ mNextAppTransitionStartY + thumbHeight/2);
+ a.setDuration(duration);
+ } else {
+ // Exiting app just holds in place.
+ a = new AlphaAnimation(1, 1);
+ a.setDuration(duration);
+ }
+ a.setFillAfter(true);
+ final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
+ com.android.internal.R.interpolator.decelerate_quint);
+ a.setInterpolator(interpolator);
+ a.initialize(mAppDisplayWidth, mAppDisplayHeight,
+ mAppDisplayWidth, mAppDisplayHeight);
+ return a;
+ }
+
private boolean applyAnimationLocked(AppWindowToken wtoken,
WindowManager.LayoutParams lp, int transit, boolean enter) {
// Only apply an animation if the display isn't frozen. If it is
// 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.isScreenOnFully()) {
+ if (okToDisplay()) {
Animation a;
- if (mNextAppTransitionPackage != null) {
+ boolean initialized = false;
+ if (mNextAppTransitionThumbnail != null) {
+ a = createThumbnailAnimationLocked(transit, enter, false);
+ initialized = true;
+ } else if (mNextAppTransitionPackage != null) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
mNextAppTransitionEnter : mNextAppTransitionExit);
} else {
@@ -3175,7 +3258,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
}
- wtoken.setAnimation(a);
+ wtoken.setAnimation(a, initialized);
}
} else {
wtoken.clearAnimation();
@@ -3234,6 +3317,10 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG, msg);
return false;
}
+
+ boolean okToDisplay() {
+ return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
+ }
AppWindowToken findAppWindowToken(IBinder token) {
WindowToken wtoken = mTokenMap.get(token);
@@ -3243,6 +3330,7 @@ public class WindowManagerService extends IWindowManager.Stub
return wtoken.appWindowToken;
}
+ @Override
public void addWindowToken(IBinder token, int type) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"addWindowToken()")) {
@@ -3283,7 +3371,7 @@ public class WindowManagerService extends IWindowManager.Stub
for (int i=0; i<N; i++) {
WindowState win = wtoken.windows.get(i);
- if (win.isAnimating()) {
+ if (win.mWinAnimator.isAnimating()) {
delayed = true;
}
@@ -3665,7 +3753,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.isScreenOnFully()) {
+ if (okToDisplay()) {
if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
|| mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
mNextAppTransition = transit;
@@ -3699,11 +3787,23 @@ public class WindowManagerService extends IWindowManager.Stub
int enterAnim, int exitAnim) {
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
mNextAppTransitionPackage = packageName;
+ mNextAppTransitionThumbnail = null;
mNextAppTransitionEnter = enterAnim;
mNextAppTransitionExit = exitAnim;
}
}
+ public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback) {
+ if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ mNextAppTransitionCallback = startedCallback;
+ }
+ }
+
public void executeAppTransition() {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"executeAppTransition()")) {
@@ -3749,7 +3849,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.isScreenOnFully()) {
+ if (!okToDisplay()) {
return;
}
@@ -3847,6 +3947,19 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendMessageAtFrontOfQueue(m);
return;
}
+ if (ttoken.thumbnail != null) {
+ // The old token is animating with a thumbnail, transfer
+ // that to the new token.
+ if (wtoken.thumbnail != null) {
+ wtoken.thumbnail.destroy();
+ }
+ wtoken.thumbnail = ttoken.thumbnail;
+ wtoken.thumbnailX = ttoken.thumbnailX;
+ wtoken.thumbnailY = ttoken.thumbnailY;
+ wtoken.thumbnailLayer = ttoken.thumbnailLayer;
+ wtoken.thumbnailAnimation = ttoken.thumbnailAnimation;
+ ttoken.thumbnail = null;
+ }
}
}
@@ -3951,7 +4064,7 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
- if (win.isAnimating()) {
+ if (win.mWinAnimator.isAnimating()) {
delayed = true;
}
@@ -4039,8 +4152,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.isScreenOnFully()
- && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ if (okToDisplay() && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
// Already in requested state, don't do anything more.
if (wtoken.hiddenRequested != visible) {
return;
@@ -4168,7 +4280,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
synchronized(mWindowMap) {
- if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOnFully()) {
+ if (configChanges == 0 && okToDisplay()) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
return;
}
@@ -4243,6 +4355,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Make sure there is no animation running on this token,
// so any windows associated with it will be removed as
// soon as their animations are complete
+ wtoken.clearAnimation();
wtoken.animation = null;
wtoken.animating = false;
}
@@ -5150,8 +5263,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
long ident = Binder.clearCallingIdentity();
- dw = mAppDisplayWidth;
- dh = mAppDisplayHeight;
+ dw = mCurDisplayWidth;
+ dh = mCurDisplayHeight;
int aboveAppLayer = mPolicy.windowTypeToLayerLw(
WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5271,7 +5384,7 @@ public class WindowManagerService extends IWindowManager.Stub
Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig());
Matrix matrix = new Matrix();
ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
- matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale));
+ matrix.postTranslate(-FloatMath.ceil(frame.left*scale), -FloatMath.ceil(frame.top*scale));
Canvas canvas = new Canvas(bm);
canvas.drawBitmap(rawss, matrix, null);
canvas.setBitmap(null);
@@ -5389,7 +5502,8 @@ public class WindowManagerService extends IWindowManager.Stub
return false;
}
- if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
+ if (mAnimator.mScreenRotationAnimation != null &&
+ mAnimator.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.
@@ -5459,9 +5573,9 @@ public class WindowManagerService extends IWindowManager.Stub
try {
// 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()) {
- if (mScreenRotationAnimation.setRotation(rotation, mFxSession,
+ if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
+ && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
+ if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
MAX_ANIMATION_DURATION, mTransitionAnimationScale,
mCurDisplayWidth, mCurDisplayHeight)) {
scheduleAnimationLocked();
@@ -5476,7 +5590,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- rebuildBlackFrame(inTransaction);
+ rebuildBlackFrame();
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
@@ -6163,6 +6277,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mDisplaySizeLock) {
mAppDisplayWidth = appWidth;
mAppDisplayHeight = appHeight;
+ mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
+ mAppDisplayWidth, mAppDisplayHeight);
}
if (false) {
Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
@@ -6549,6 +6665,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
+ mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
+ mAppDisplayWidth, mAppDisplayHeight);
}
mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
mDisplay.getRawWidth(), mDisplay.getRawHeight(),
@@ -7151,45 +7269,32 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- private void rebuildBlackFrame(boolean inTransaction) {
- if (!inTransaction) {
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION rebuildBlackFrame");
- Surface.openTransaction();
+ private void rebuildBlackFrame() {
+ if (mBlackFrame != null) {
+ mBlackFrame.kill();
+ mBlackFrame = null;
}
- try {
- if (mBlackFrame != null) {
- mBlackFrame.kill();
- mBlackFrame = null;
- }
- if (mBaseDisplayWidth < mInitialDisplayWidth
- || mBaseDisplayHeight < mInitialDisplayHeight) {
- int initW, initH, baseW, baseH;
- final boolean rotated = (mRotation == Surface.ROTATION_90
- || mRotation == Surface.ROTATION_270);
- if (rotated) {
- initW = mInitialDisplayHeight;
- initH = mInitialDisplayWidth;
- baseW = mBaseDisplayHeight;
- baseH = mBaseDisplayWidth;
- } else {
- initW = mInitialDisplayWidth;
- initH = mInitialDisplayHeight;
- baseW = mBaseDisplayWidth;
- baseH = mBaseDisplayHeight;
- }
- Rect outer = new Rect(0, 0, initW, initH);
- Rect inner = new Rect(0, 0, baseW, baseH);
- try {
- mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER);
- } catch (Surface.OutOfResourcesException e) {
- }
+ if (mBaseDisplayWidth < mInitialDisplayWidth
+ || mBaseDisplayHeight < mInitialDisplayHeight) {
+ int initW, initH, baseW, baseH;
+ final boolean rotated = (mRotation == Surface.ROTATION_90
+ || mRotation == Surface.ROTATION_270);
+ if (rotated) {
+ initW = mInitialDisplayHeight;
+ initH = mInitialDisplayWidth;
+ baseW = mBaseDisplayHeight;
+ baseH = mBaseDisplayWidth;
+ } else {
+ initW = mInitialDisplayWidth;
+ initH = mInitialDisplayHeight;
+ baseW = mBaseDisplayWidth;
+ baseH = mBaseDisplayHeight;
}
- } finally {
- if (!inTransaction) {
- Surface.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION rebuildBlackFrame");
+ Rect outer = new Rect(0, 0, initW, initH);
+ Rect inner = new Rect(0, 0, baseW, baseH);
+ try {
+ mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER);
+ } catch (Surface.OutOfResourcesException e) {
}
}
}
@@ -7240,7 +7345,7 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
- rebuildBlackFrame(false);
+ rebuildBlackFrame();
performLayoutAndPlaceSurfacesLocked();
}
@@ -7478,10 +7583,25 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
mInLayout = false;
- if (mLayoutNeeded) {
+ }
+
+ if (mLayoutNeeded) {
+ if (++mLayoutRepeatCount < 6) {
requestTraversalLocked();
+ } else {
+ Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
+ mLayoutRepeatCount = 0;
}
+ } else {
+ mLayoutRepeatCount = 0;
}
+
+ if (mAnimator.mAnimating) {
+ // Do this even if requestTraversalLocked was called above so we get a frame drawn
+ // at the proper time as well as the one drawn early.
+ scheduleAnimationLocked();
+ }
+
if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE));
@@ -7625,7 +7745,7 @@ public class WindowManagerService extends IWindowManager.Stub
// If the screen is currently frozen or off, then keep
// it frozen/off until this window draws at its new
// orientation.
- if (mDisplayFrozen || !mPolicy.isScreenOnFully()) {
+ if (!okToDisplay()) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Changing surface while display frozen: " + w);
w.mOrientationChanging = true;
@@ -7642,351 +7762,6 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- * Update animations of all applications, including those associated with exiting/removed apps.
- *
- * @param currentTime The time which animations use for calculating transitions.
- * @param innerDw Width of app window.
- * @param innerDh Height of app window.
- */
- private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
- int innerDw, int innerDh) {
- int i;
- final int NAT = mAppTokens.size();
- for (i=0; i<NAT; i++) {
- final AppWindowToken appToken = mAppTokens.get(i);
- if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
- mInnerFields.mAnimating = true;
- }
- }
- final int NEAT = mExitingAppTokens.size();
- for (i=0; i<NEAT; i++) {
- final AppWindowToken appToken = mExitingAppTokens.get(i);
- if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
- mInnerFields.mAnimating = true;
- }
- }
-
- if (mScreenRotationAnimation != null &&
- (mScreenRotationAnimation.isAnimating() ||
- mScreenRotationAnimation.mFinishAnimReady)) {
- if (mScreenRotationAnimation.stepAnimationLocked(currentTime)) {
- mInnerFields.mUpdateRotation = false;
- mInnerFields.mAnimating = true;
- } else {
- mInnerFields.mUpdateRotation = true;
- mScreenRotationAnimation.kill();
- mScreenRotationAnimation = null;
- }
- }
- }
-
- private void animateAndUpdateSurfaces(final long currentTime, final int dw, final int dh,
- final int innerDw, final int innerDh,
- final boolean recoveringMemory) {
- // Update animations of all applications, including those
- // associated with exiting/removed apps
- Surface.openTransaction();
-
- try {
- updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
- mPendingLayoutChanges = performAnimationsLocked(currentTime, dw, dh,
- innerDw, innerDh);
-
- // THIRD LOOP: Update the surfaces of all windows.
-
- if (mScreenRotationAnimation != null) {
- mScreenRotationAnimation.updateSurfaces();
- }
-
- final int N = mWindows.size();
- for (int i=N-1; i>=0; i--) {
- WindowState w = mWindows.get(i);
- prepareSurfaceLocked(w, recoveringMemory);
- }
-
- if (mDimAnimator != null && mDimAnimator.mDimShown) {
- mInnerFields.mAnimating |=
- mDimAnimator.updateSurface(mInnerFields.mDimming, currentTime,
- mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully());
- }
-
- if (!mInnerFields.mBlurring && mBlurShown) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
- + ": HIDE");
- try {
- mBlurSurface.hide();
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Illegal argument exception hiding blur surface");
- }
- mBlurShown = false;
- }
-
- if (mBlackFrame != null) {
- if (mScreenRotationAnimation != null) {
- mBlackFrame.setMatrix(
- mScreenRotationAnimation.getEnterTransformation().getMatrix());
- } else {
- mBlackFrame.clearMatrix();
- }
- }
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Unhandled exception in Window Manager", e);
- } finally {
- Surface.closeTransaction();
- }
- }
-
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
- * @param currentTime The time which animations use for calculating transitions.
- * @param dw Width of app window.
- * @param dh Height of app window.
- * @param innerDw Width of app window.
- * @param innerDh Height of app window.
- */
- private int updateWindowsAndWallpaperLocked(final long currentTime, final int dw, final int dh,
- final int innerDw, final int innerDh) {
- int changes = 0;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState w = mWindows.get(i);
-
- final WindowManager.LayoutParams attrs = w.mAttrs;
-
- if (w.mSurface != null) {
- // Take care of the window being ready to display.
- if (w.commitFinishDrawingLocked(currentTime)) {
- if ((w.mAttrs.flags
- & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "First draw done in potential wallpaper target " + w);
- mInnerFields.mWallpaperMayChange = true;
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
-
- // If the window has moved due to its containing
- // content frame changing, then we'd like to animate
- // it. The checks here are ordered by what is least
- // likely to be true first.
- if (w.shouldAnimateMove()) {
- // Frame has moved, containing content frame
- // has also moved, and we're not currently animating...
- // let's do something.
- Animation a = AnimationUtils.loadAnimation(mContext,
- com.android.internal.R.anim.window_move_from_decor);
- w.setAnimation(a);
- w.mAnimDw = w.mLastFrame.left - w.mFrame.left;
- w.mAnimDh = w.mLastFrame.top - w.mFrame.top;
- } else {
- w.mAnimDw = innerDw;
- w.mAnimDh = innerDh;
- }
-
- final boolean wasAnimating = w.mWasAnimating;
- final boolean nowAnimating = w.stepAnimationLocked(currentTime);
-
- if (DEBUG_WALLPAPER) {
- Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
- ", nowAnimating=" + nowAnimating);
- }
-
- // If this window is animating, make a note that we have
- // an animating window and take care of a request to run
- // a detached wallpaper animation.
- if (nowAnimating) {
- if (w.mAnimation != null) {
- if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
- && w.mAnimation.getDetachWallpaper()) {
- mInnerFields.mDetachedWallpaper = w;
- }
- if (w.mAnimation.getBackgroundColor() != 0) {
- if (mInnerFields.mWindowAnimationBackground == null
- || (w.mAnimLayer <
- mInnerFields.mWindowAnimationBackground.mAnimLayer)) {
- mInnerFields.mWindowAnimationBackground = w;
- mInnerFields.mWindowAnimationBackgroundColor =
- w.mAnimation.getBackgroundColor();
- }
- }
- }
- mInnerFields.mAnimating = true;
- }
-
- // If this window's app token is running a detached wallpaper
- // animation, make a note so we can ensure the wallpaper is
- // displayed behind it.
- if (w.mAppToken != null && w.mAppToken.animation != null
- && w.mAppToken.animating) {
- if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
- && w.mAppToken.animation.getDetachWallpaper()) {
- mInnerFields.mDetachedWallpaper = w;
- }
- if (w.mAppToken.animation.getBackgroundColor() != 0) {
- if (mInnerFields.mWindowAnimationBackground == null
- || (w.mAnimLayer <
- mInnerFields.mWindowAnimationBackground.mAnimLayer)) {
- mInnerFields.mWindowAnimationBackground = w;
- mInnerFields.mWindowAnimationBackgroundColor =
- w.mAppToken.animation.getBackgroundColor();
- }
- }
- }
-
- if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
- mInnerFields.mWallpaperMayChange = true;
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- }
-
- if (mPolicy.doesForceHide(w, attrs)) {
- if (!wasAnimating && nowAnimating) {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "Animation started that could impact force hide: "
- + w);
- mInnerFields.mWallpaperForceHidingChanged = true;
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- mFocusMayChange = true;
- } else if (w.isReadyForDisplay() && w.mAnimation == null) {
- mInnerFields.mForceHiding = true;
- }
- } else if (mPolicy.canBeForceHidden(w, attrs)) {
- boolean changed;
- if (mInnerFields.mForceHiding) {
- changed = w.hideLw(false, false);
- if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy hidden: " + w);
- } else {
- changed = w.showLw(false, false);
- if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy shown: " + w);
- if (changed) {
- if (mInnerFields.mWallpaperForceHidingChanged
- && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
- // Assume we will need to animate. If
- // we don't (because the wallpaper will
- // stay with the lock screen), then we will
- // clean up later.
- Animation a = mPolicy.createForceHideEnterAnimation();
- if (a != null) {
- w.setAnimation(a);
- }
- }
- if (mCurrentFocus == null ||
- mCurrentFocus.mLayer < w.mLayer) {
- // We are showing on to of the current
- // focus, so re-evaluate focus to make
- // sure it is correct.
- mFocusMayChange = true;
- }
- }
- }
- if (changed && (attrs.flags
- & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
- mInnerFields.mWallpaperMayChange = true;
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
- }
-
- final AppWindowToken atoken = w.mAppToken;
- if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
- if (atoken.lastTransactionSequence != mTransactionSequence) {
- atoken.lastTransactionSequence = mTransactionSequence;
- atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
- atoken.startingDisplayed = false;
- }
- if ((w.isOnScreen() || w.mAttrs.type
- == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
- && !w.mExiting && !w.mDestroying) {
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Eval win " + w + ": isDrawn="
- + w.isDrawnLw()
- + ", isAnimating=" + w.isAnimating());
- if (!w.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s=" + w.mSurface
- + " pv=" + w.mPolicyVisibility
- + " dp=" + w.mDrawPending
- + " cdp=" + w.mCommitDrawPending
- + " ah=" + w.mAttachedHidden
- + " th=" + atoken.hiddenRequested
- + " a=" + w.mAnimating);
- }
- }
- if (w != atoken.startingWindow) {
- if (!atoken.freezingScreen || !w.mAppFreezing) {
- atoken.numInterestingWindows++;
- if (w.isDrawnLw()) {
- atoken.numDrawnWindows++;
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
- "tokenMayBeDrawn: " + atoken
- + " freezingScreen=" + atoken.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
- mInnerFields.mTokenMayBeDrawn = true;
- }
- }
- } else if (w.isDrawnLw()) {
- atoken.startingDisplayed = true;
- }
- }
- } else if (w.mReadyToShow) {
- w.performShowLocked();
- changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
- }
- } // end forall windows
-
- return changes;
- }
-
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
- * @return bitmap indicating if another pass through layout must be made.
- */
- private int testTokenMayBeDrawnLocked() {
- int changes = 0;
- // See if any windows have been drawn, so they (and others
- // associated with them) can now be shown.
- final int NT = mAppTokens.size();
- for (int i=0; i<NT; i++) {
- AppWindowToken wtoken = mAppTokens.get(i);
- if (wtoken.freezingScreen) {
- int numInteresting = wtoken.numInterestingWindows;
- if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "allDrawn: " + wtoken
- + " interesting=" + numInteresting
- + " drawn=" + wtoken.numDrawnWindows);
- wtoken.showAllWindowsLocked();
- unsetAppFreezingScreenLocked(wtoken, false, true);
- if (DEBUG_ORIENTATION) Slog.i(TAG,
- "Setting mOrientationChangeComplete=true because wtoken "
- + wtoken + " numInteresting=" + numInteresting
- + " numDrawn=" + wtoken.numDrawnWindows);
- mInnerFields.mOrientationChangeComplete = true;
- }
- } else if (!wtoken.allDrawn) {
- int numInteresting = wtoken.numInterestingWindows;
- if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "allDrawn: " + wtoken
- + " interesting=" + numInteresting
- + " drawn=" + wtoken.numDrawnWindows);
- wtoken.allDrawn = true;
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
-
- // We can now show all of the drawn windows!
- if (!mOpeningApps.contains(wtoken)) {
- wtoken.showAllWindowsLocked();
- }
- }
- }
- }
-
- return changes;
- }
-
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
*
* @return bitmap indicating if another pass through layout must be made.
*/
@@ -8148,11 +7923,15 @@ public class WindowManagerService extends IWindowManager.Stub
animLp = null;
}
+ AppWindowToken topOpeningApp = null;
+ int topOpeningLayer = 0;
+
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.get(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Now opening app" + wtoken);
+ wtoken.clearThumbnail();
wtoken.reportedVisible = false;
wtoken.inPendingTransaction = false;
wtoken.animation = null;
@@ -8160,13 +7939,27 @@ public class WindowManagerService extends IWindowManager.Stub
transit, false);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
- wtoken.showAllWindowsLocked();
+ mAnimator.mAnimating |= wtoken.showAllWindowsLocked();
+ if (animLp != null) {
+ int layer = -1;
+ for (int j=0; j<wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mAnimLayer > layer) {
+ layer = win.mAnimLayer;
+ }
+ }
+ if (topOpeningApp == null || layer > topOpeningLayer) {
+ topOpeningApp = wtoken;
+ topOpeningLayer = layer;
+ }
+ }
}
NN = mClosingApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mClosingApps.get(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Now closing app" + wtoken);
+ wtoken.clearThumbnail();
wtoken.inPendingTransaction = false;
wtoken.animation = null;
setTokenVisibilityLocked(wtoken, animLp, false,
@@ -8179,7 +7972,47 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.allDrawn = true;
}
+ if (mNextAppTransitionThumbnail != null && topOpeningApp != null
+ && topOpeningApp.animation != null) {
+ // This thumbnail animation is very special, we need to have
+ // an extra surface with the thumbnail included with the animation.
+ Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(),
+ mNextAppTransitionThumbnail.getHeight());
+ try {
+ Surface surface = new Surface(mFxSession, Process.myPid(),
+ "thumbnail anim", 0, dirty.width(), dirty.height(),
+ PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+ topOpeningApp.thumbnail = surface;
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL "
+ + surface + ": CREATE");
+ Surface drawSurface = new Surface();
+ drawSurface.copyFrom(surface);
+ Canvas c = drawSurface.lockCanvas(dirty);
+ c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null);
+ drawSurface.unlockCanvasAndPost(c);
+ drawSurface.release();
+ topOpeningApp.thumbnailLayer = topOpeningLayer;
+ Animation anim = createThumbnailAnimationLocked(transit, true, true);
+ topOpeningApp.thumbnailAnimation = anim;
+ anim.restrictDuration(MAX_ANIMATION_DURATION);
+ anim.scaleCurrentDuration(mTransitionAnimationScale);
+ topOpeningApp.thumbnailX = mNextAppTransitionStartX;
+ topOpeningApp.thumbnailY = mNextAppTransitionStartY;
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
+ + " h=" + dirty.height(), e);
+ topOpeningApp.clearThumbnail();
+ }
+ }
+
mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = null;
+ if (mNextAppTransitionCallback != null) {
+ try {
+ mNextAppTransitionCallback.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
mOpeningApps.clear();
mClosingApps.clear();
@@ -8258,20 +8091,20 @@ public class WindowManagerService extends IWindowManager.Stub
if (mLowerWallpaperTarget == null) {
// Whoops, we don't need a special wallpaper animation.
// Clear them out.
- mInnerFields.mForceHiding = false;
+ mAnimator.mForceHiding = false;
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
if (w.mSurface != null) {
final WindowManager.LayoutParams attrs = w.mAttrs;
if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
- mInnerFields.mForceHiding = true;
+ mAnimator.mForceHiding = true;
} else if (mPolicy.canBeForceHidden(w, attrs)) {
- if (!w.mAnimating) {
+ if (!w.mWinAnimator.mAnimating) {
// We set the animation above so it
// is not yet running.
// TODO(cmautner): We lose the enter animation when this occurs.
- w.clearAnimation();
+ w.mWinAnimator.clearAnimation();
}
}
}
@@ -8296,14 +8129,14 @@ public class WindowManagerService extends IWindowManager.Stub
mInnerFields.mWallpaperMayChange = true;
}
- if (mInnerFields.mWindowAnimationBackgroundColor != 0) {
+ if (mAnimator.mWindowAnimationBackgroundColor != 0) {
// If the window that wants black is the current wallpaper
// target, then the black goes *below* the wallpaper so we
// don't cause the wallpaper to suddenly disappear.
- WindowState target = mInnerFields.mWindowAnimationBackground;
- if (mWallpaperTarget == mInnerFields.mWindowAnimationBackground
- || mLowerWallpaperTarget == mInnerFields.mWindowAnimationBackground
- || mUpperWallpaperTarget == mInnerFields.mWindowAnimationBackground) {
+ WindowState target = mAnimator.mWindowAnimationBackground;
+ if (mWallpaperTarget == target
+ || mLowerWallpaperTarget == target
+ || mUpperWallpaperTarget == target) {
for (int i=0; i<mWindows.size(); i++) {
WindowState w = mWindows.get(i);
if (w.mIsWallpaper) {
@@ -8319,7 +8152,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int dh = mCurDisplayHeight;
mWindowAnimationBackgroundSurface.show(dw, dh,
target.mAnimLayer - LAYER_OFFSET_DIM,
- mInnerFields.mWindowAnimationBackgroundColor);
+ mAnimator.mWindowAnimationBackgroundColor);
} else if (mWindowAnimationBackgroundSurface != null) {
mWindowAnimationBackgroundSurface.hide();
}
@@ -8422,206 +8255,6 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
*
- * @param w WindowState whos Surface is being prepared.
- * @param recoveringMemory true if the caller will reclaim surface memory on error.
- */
- public void prepareSurfaceLocked(final WindowState w, final boolean recoveringMemory) {
- // XXX NOTE: The logic here could be improved. We have
- // the decision about whether to resize a window separated
- // from whether to hide the surface. This can cause us to
- // resize a surface even if we are going to hide it. You
- // can see this by (1) holding device in landscape mode on
- // home screen; (2) tapping browser icon (device will rotate
- // to landscape; (3) tap home. The wallpaper will be resized
- // in step 2 but then immediately hidden, causing us to
- // have to resize and then redraw it again in step 3. It
- // would be nice to figure out how to avoid this, but it is
- // difficult because we do need to resize surfaces in some
- // cases while they are hidden such as when first showing a
- // window.
-
- if (w.mSurface == null) {
- if (w.mOrientationChanging) {
- if (DEBUG_ORIENTATION) {
- Slog.v(TAG, "Orientation change skips hidden " + w);
- }
- w.mOrientationChanging = false;
- }
- return;
- }
-
- boolean displayed = false;
-
- w.computeShownFrameLocked();
-
- int width, height;
- if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
- // for a scaled surface, we just want to use
- // the requested size.
- width = w.mRequestedWidth;
- height = w.mRequestedHeight;
- } else {
- width = w.mCompatFrame.width();
- height = w.mCompatFrame.height();
- }
-
- if (width < 1) {
- width = 1;
- }
- if (height < 1) {
- height = 1;
- }
- final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
- if (surfaceResized) {
- w.mSurfaceW = width;
- w.mSurfaceH = height;
- }
-
- if (w.mSurfaceX != w.mShownFrame.left
- || w.mSurfaceY != w.mShownFrame.top) {
- try {
- if (SHOW_TRANSACTIONS) logSurface(w,
- "POS " + w.mShownFrame.left
- + ", " + w.mShownFrame.top, null);
- w.mSurfaceX = w.mShownFrame.left;
- w.mSurfaceY = w.mShownFrame.top;
- w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error positioning surface of " + w
- + " pos=(" + w.mShownFrame.left
- + "," + w.mShownFrame.top + ")", e);
- if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "position", true);
- }
- }
- }
-
- if (surfaceResized) {
- try {
- if (SHOW_TRANSACTIONS) logSurface(w,
- "SIZE " + width + "x" + height, null);
- w.mSurfaceResized = true;
- w.mSurface.setSize(width, height);
- } catch (RuntimeException e) {
- // If something goes wrong with the surface (such
- // as running out of memory), don't take down the
- // entire system.
- Slog.e(TAG, "Error resizing surface of " + w
- + " size=(" + width + "x" + height + ")", e);
- if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "size", true);
- }
- }
- }
-
- updateResizingWindows(w);
-
- if (w.mAttachedHidden || !w.isReadyForDisplay()) {
- if (!w.mLastHidden) {
- //dump();
- w.mLastHidden = true;
- if (SHOW_TRANSACTIONS) logSurface(w,
- "HIDE (performLayout)", null);
- if (w.mSurface != null) {
- w.mSurfaceShown = false;
- try {
- w.mSurface.hide();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Exception hiding surface in " + w);
- }
- }
- }
- // If we are waiting for this window to handle an
- // orientation change, well, it is hidden, so
- // doesn't really matter. Note that this does
- // introduce a potential glitch if the window
- // becomes unhidden before it has drawn for the
- // new orientation.
- if (w.mOrientationChanging) {
- w.mOrientationChanging = false;
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation change skips hidden " + w);
- }
- } else if (w.mLastLayer != w.mAnimLayer
- || w.mLastAlpha != w.mShownAlpha
- || w.mLastDsDx != w.mDsDx
- || w.mLastDtDx != w.mDtDx
- || w.mLastDsDy != w.mDsDy
- || w.mLastDtDy != w.mDtDy
- || w.mLastHScale != w.mHScale
- || w.mLastVScale != w.mVScale
- || w.mLastHidden) {
- displayed = true;
- w.mLastAlpha = w.mShownAlpha;
- w.mLastLayer = w.mAnimLayer;
- w.mLastDsDx = w.mDsDx;
- w.mLastDtDx = w.mDtDx;
- w.mLastDsDy = w.mDsDy;
- w.mLastDtDy = w.mDtDy;
- w.mLastHScale = w.mHScale;
- w.mLastVScale = w.mVScale;
- if (SHOW_TRANSACTIONS) logSurface(w,
- "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
- + " matrix=[" + (w.mDsDx*w.mHScale)
- + "," + (w.mDtDx*w.mVScale)
- + "][" + (w.mDsDy*w.mHScale)
- + "," + (w.mDtDy*w.mVScale) + "]", null);
- if (w.mSurface != null) {
- try {
- w.mSurfaceAlpha = w.mShownAlpha;
- w.mSurface.setAlpha(w.mShownAlpha);
- w.mSurfaceLayer = w.mAnimLayer;
- w.mSurface.setLayer(w.mAnimLayer);
- w.mSurface.setMatrix(
- w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
- w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error updating surface in " + w, e);
- if (!recoveringMemory) {
- reclaimSomeSurfaceMemoryLocked(w, "update", true);
- }
- }
- }
-
- if (w.mLastHidden && w.isDrawnLw()
- && !w.mReadyToShow) {
- if (SHOW_TRANSACTIONS) logSurface(w,
- "SHOW (performLayout)", null);
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
- + " during relayout");
- if (showSurfaceRobustlyLocked(w)) {
- w.mHasDrawn = true;
- w.mLastHidden = false;
- } else {
- w.mOrientationChanging = false;
- }
- }
- if (w.mSurface != null) {
- w.mToken.hasVisible = true;
- }
- } else {
- displayed = true;
- }
-
- if (displayed) {
- if (w.mOrientationChanging) {
- if (!w.isDrawnLw()) {
- mInnerFields.mOrientationChangeComplete = false;
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation continue waiting for draw in " + w);
- } else {
- w.mOrientationChanging = false;
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation change complete in " + w);
- }
- }
- w.mToken.hasVisible = true;
- }
- }
-
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
* @param w WindowState this method is applied to.
* @param currentTime The time which animations use for calculating transitions.
* @param innerDw Width of app window.
@@ -8656,131 +8289,26 @@ public class WindowManagerService extends IWindowManager.Stub
boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
// This window completely covers everything behind it,
- // so we want to leave all of them as unblurred (for
+ // so we want to leave all of them as undimmed (for
// performance reasons).
mInnerFields.mObscured = true;
- } else if (canBeSeen && (attrFlags & (FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND)) != 0) {
- if (localLOGV) Slog.v(TAG, "Win " + w
- + ": blurring=" + mInnerFields.mBlurring
- + " obscured=" + mInnerFields.mObscured);
- if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
- if (!mInnerFields.mDimming) {
- //Slog.i(TAG, "DIM BEHIND: " + w);
- mInnerFields.mDimming = true;
- if (mDimAnimator == null) {
- mDimAnimator = new DimAnimator(mFxSession);
- }
- if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
- mDimAnimator.show(mCurDisplayWidth, mCurDisplayHeight);
- } else {
- mDimAnimator.show(innerDw, innerDh);
- }
+ } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0) {
+ if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured);
+ if (!mInnerFields.mDimming) {
+ //Slog.i(TAG, "DIM BEHIND: " + w);
+ mInnerFields.mDimming = true;
+ if (mDimAnimator == null) {
+ mDimAnimator = new DimAnimator(mFxSession);
+ }
+ if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
+ mDimAnimator.show(mCurDisplayWidth, mCurDisplayHeight);
+ } else {
mDimAnimator.show(innerDw, innerDh);
- mDimAnimator.updateParameters(mContext.getResources(),
- w, currentTime);
}
+ mDimAnimator.updateParameters(mContext.getResources(),
+ w, currentTime);
}
- if ((attrFlags & FLAG_BLUR_BEHIND) != 0) {
- if (!mInnerFields.mBlurring) {
- //Slog.i(TAG, "BLUR BEHIND: " + w);
- mInnerFields.mBlurring = true;
- if (mBlurSurface == null) {
- try {
- mBlurSurface = new Surface(mFxSession, 0,
- "BlurSurface",
- -1, 16, 16,
- PixelFormat.OPAQUE,
- Surface.FX_SURFACE_BLUR);
- } catch (Exception e) {
- Slog.e(TAG, "Exception creating Blur surface", e);
- }
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
- + mBlurSurface + ": CREATE");
- }
- final int dw = mCurDisplayWidth;
- final int dh = mCurDisplayHeight;
- if (mBlurSurface != null) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
- + mBlurSurface + ": pos=(0,0) (" +
- dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
- mBlurSurface.setPosition(0, 0);
- mBlurSurface.setSize(dw, dh);
- mBlurSurface.setLayer(w.mAnimLayer-LAYER_OFFSET_BLUR);
- if (!mBlurShown) {
- try {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
- + mBlurSurface + ": SHOW");
- mBlurSurface.show();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure showing blur surface", e);
- }
- mBlurShown = true;
- }
- }
- }
- }
- }
- }
-
- private final int performAnimationsLocked(long currentTime, int dw, int dh,
- int innerDw, int innerDh) {
- ++mTransactionSequence;
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
- + mTransactionSequence + " mAnimating="
- + mInnerFields.mAnimating);
-
- mInnerFields.mTokenMayBeDrawn = false;
- mInnerFields.mWallpaperMayChange = false;
- mInnerFields.mForceHiding = false;
- mInnerFields.mDetachedWallpaper = null;
- mInnerFields.mWindowAnimationBackground = null;
- mInnerFields.mWindowAnimationBackgroundColor = 0;
-
- int changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
-
- if (mInnerFields.mTokenMayBeDrawn) {
- changes |= testTokenMayBeDrawnLocked();
- }
-
- // If we are ready to perform an app transition, check through
- // all of the app tokens to be shown and see if they are ready
- // to go.
- if (mAppTransitionReady) {
- changes |= handleAppTransitionReadyLocked();
- }
-
- mInnerFields.mAdjResult = 0;
-
- if (!mInnerFields.mAnimating && mAppTransitionRunning) {
- // We have finished the animation of an app transition. To do
- // this, we have delayed a lot of operations like showing and
- // hiding apps, moving apps in Z-order, etc. The app token list
- // reflects the correct Z-order, but the window list may now
- // be out of sync with it. So here we will just rebuild the
- // entire app window list. Fun!
- changes |= handleAnimatingStoppedAndTransitionLocked();
- }
-
- if (mInnerFields.mWallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
- // At this point, there was a window with a wallpaper that
- // was force hiding other windows behind it, but now it
- // is going away. This may be simple -- just animate
- // away the wallpaper and its window -- or it may be
- // hard -- the wallpaper now needs to be shown behind
- // something that was hidden.
- changes |= animateAwayWallpaperLocked();
}
-
- changes |= testWallpaperAndBackgroundLocked();
-
- if (mLayoutNeeded) {
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
- }
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
- + Integer.toHexString(changes));
- return changes;
}
// "Something has changed! Let's make it correct now."
@@ -8820,7 +8348,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInnerFields.mScreenBrightness = -1;
mInnerFields.mButtonBrightness = -1;
boolean focusDisplayed = false;
- mInnerFields.mAnimating = false;
+ mAnimator.mAnimating = false;
boolean createWatermark = false;
if (mFxSession == null) {
@@ -8855,12 +8383,15 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner");
+
if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
assignLayersLocked();
mLayoutNeeded = true;
}
}
+
if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (updateOrientationFromAppTokensLocked(true)) {
@@ -8868,6 +8399,7 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
+
if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
mLayoutNeeded = true;
}
@@ -8882,6 +8414,7 @@ public class WindowManagerService extends IWindowManager.Stub
// FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
// it is animating.
mPendingLayoutChanges = 0;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount);
mPolicy.beginAnimationLw(dw, dh);
for (i = mWindows.size() - 1; i >= 0; i--) {
WindowState w = mWindows.get(i);
@@ -8890,13 +8423,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
mPendingLayoutChanges |= mPolicy.finishAnimationLw();
-
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw");
} while (mPendingLayoutChanges != 0);
final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
mInnerFields.mObscured = false;
- mInnerFields.mBlurring = false;
mInnerFields.mDimming = false;
mInnerFields.mSyswin = false;
@@ -8931,9 +8463,59 @@ public class WindowManagerService extends IWindowManager.Stub
Surface.closeTransaction();
}
+ // If we are ready to perform an app transition, check through
+ // all of the app tokens to be shown and see if they are ready
+ // to go.
+ if (mAppTransitionReady) {
+ mPendingLayoutChanges |= handleAppTransitionReadyLocked();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked");
+ }
+
+ mInnerFields.mAdjResult = 0;
+
+ if (!mAnimator.mAnimating && mAppTransitionRunning) {
+ // We have finished the animation of an app transition. To do
+ // this, we have delayed a lot of operations like showing and
+ // hiding apps, moving apps in Z-order, etc. The app token list
+ // reflects the correct Z-order, but the window list may now
+ // be out of sync with it. So here we will just rebuild the
+ // entire app window list. Fun!
+ mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock");
+ }
+
+ if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 &&
+ !mAppTransitionReady) {
+ // At this point, there was a window with a wallpaper that
+ // was force hiding other windows behind it, but now it
+ // is going away. This may be simple -- just animate
+ // away the wallpaper and its window -- or it may be
+ // hard -- the wallpaper now needs to be shown behind
+ // something that was hidden.
+ mPendingLayoutChanges |= animateAwayWallpaperLocked();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked");
+ }
+
+ mPendingLayoutChanges |= testWallpaperAndBackgroundLocked();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after testWallpaperAndBackgroundLocked");
+
+ if (mLayoutNeeded) {
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded");
+ }
+
+ final int N = mWindows.size();
+ for (i=N-1; i>=0; i--) {
+ WindowState w = mWindows.get(i);
+ // TODO(cmautner): Can this move up to the loop at the end of try/catch above?
+ updateResizingWindows(w);
+ }
+
// Update animations of all applications, including those
// associated with exiting/removed apps
- animateAndUpdateSurfaces(currentTime, dw, dh, innerDw, innerDh, recoveringMemory);
+ mAnimator.animate();
+ mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()");
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -9026,6 +8608,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Make sure there is no animation running on this token,
// so any windows associated with it will be removed as
// soon as their animations are complete
+ token.clearAnimation();
token.animation = null;
token.animating = false;
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -9035,9 +8618,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- boolean needRelayout = false;
-
- if (!mInnerFields.mAnimating && mAppTransitionRunning) {
+ if (!mAnimator.mAnimating && mAppTransitionRunning) {
// We have finished the animation of an app transition. To do
// this, we have delayed a lot of operations like showing and
// hiding apps, moving apps in Z-order, etc. The app token list
@@ -9045,7 +8626,7 @@ public class WindowManagerService extends IWindowManager.Stub
// be out of sync with it. So here we will just rebuild the
// entire app window list. Fun!
mAppTransitionRunning = false;
- needRelayout = true;
+ mLayoutNeeded = true;
rebuildAppWindowListLocked();
assignLayersLocked();
// Clear information about apps that were moving.
@@ -9056,19 +8637,10 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
}
if (wallpaperDestroyed) {
- needRelayout = adjustWallpaperWindowsLocked() != 0;
- }
- if ((mPendingLayoutChanges & (
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER |
- ADJUST_WALLPAPER_LAYERS_CHANGED |
- WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG |
- WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
- needRelayout = true;
+ mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0;
}
- if (needRelayout) {
- requestTraversalLocked();
- } else if (mInnerFields.mAnimating) {
- scheduleAnimationLocked();
+ if (mPendingLayoutChanges != 0) {
+ mLayoutNeeded = true;
}
// Finally update all input windows now that the window changes have stabilized.
@@ -9111,7 +8683,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (mInnerFields.mOrientationChangeComplete && !needRelayout &&
+ if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
!mInnerFields.mUpdateRotation) {
checkDrawnWindowsLocked();
}
@@ -9333,6 +8905,7 @@ public class WindowManagerService extends IWindowManager.Stub
TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
final WindowState oldFocus = mCurrentFocus;
mCurrentFocus = newFocus;
+ mAnimator.setCurrentFocus(mCurrentFocus);
mLosingFocus.remove(newFocus);
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
@@ -9464,6 +9037,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = null;
mAppTransitionReady = true;
}
@@ -9473,16 +9047,16 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (CUSTOM_SCREEN_ROTATION) {
- if (mScreenRotationAnimation != null) {
- mScreenRotationAnimation.kill();
- mScreenRotationAnimation = null;
+ if (mAnimator.mScreenRotationAnimation != null) {
+ mAnimator.mScreenRotationAnimation.kill();
+ mAnimator.mScreenRotationAnimation = null;
}
- if (mScreenRotationAnimation == null) {
- mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+ if (mAnimator.mScreenRotationAnimation == null) {
+ mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
mDisplay.getRotation());
}
- if (!mScreenRotationAnimation.hasScreenshot()) {
+ if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
}
} else {
@@ -9507,20 +9081,20 @@ public class WindowManagerService extends IWindowManager.Stub
boolean updateRotation = false;
- if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
- && mScreenRotationAnimation.hasScreenshot()) {
+ if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
+ && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
- if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+ if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
scheduleAnimationLocked();
} else {
- mScreenRotationAnimation = null;
+ mAnimator.mScreenRotationAnimation = null;
updateRotation = true;
}
} else {
- if (mScreenRotationAnimation != null) {
- mScreenRotationAnimation.kill();
- mScreenRotationAnimation = null;
+ if (mAnimator.mScreenRotationAnimation != null) {
+ mAnimator.mScreenRotationAnimation.kill();
+ mAnimator.mScreenRotationAnimation = null;
}
updateRotation = true;
}
@@ -9987,8 +9561,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
pw.print(" mSystemBooted="); pw.print(mSystemBooted);
pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
- pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
- pw.print(" mBlurShown="); pw.println(mBlurShown);
+ pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
if (mDimAnimator != null) {
pw.println(" mDimAnimator:");
mDimAnimator.printTo(" ", pw);
@@ -10004,9 +9577,9 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation);
pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
- if (mScreenRotationAnimation != null) {
+ if (mAnimator.mScreenRotationAnimation != null) {
pw.println(" mScreenRotationAnimation:");
- mScreenRotationAnimation.printTo(" ", pw);
+ mAnimator.mScreenRotationAnimation.printTo(" ", pw);
}
pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
@@ -10025,6 +9598,12 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mNextAppTransitionExit=0x");
pw.print(Integer.toHexString(mNextAppTransitionExit));
}
+ if (mNextAppTransitionThumbnail != null) {
+ pw.print(" mNextAppTransitionThumbnail=");
+ pw.print(mNextAppTransitionThumbnail);
+ pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+ pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
+ }
pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
}
@@ -10192,4 +9771,11 @@ public class WindowManagerService extends IWindowManager.Stub
public interface OnHardKeyboardStatusChangeListener {
public void onHardKeyboardStatusChange(boolean available, boolean enabled);
}
+
+ void debugLayoutRepeats(final String msg) {
+ if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
+ Slog.v(TAG, "Layouts looping: " + msg);
+ Slog.v(TAG, "mPendingLayoutChanges = 0x" + Integer.toHexString(mPendingLayoutChanges));
+ }
+ }
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 57d0374..615cd80 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -45,7 +45,6 @@ import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
import android.view.animation.Transformation;
import java.io.PrintWriter;
@@ -91,7 +90,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mAttachedHidden; // is our parent window hidden?
boolean mLastHidden; // was this window last hidden?
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
- boolean mWasAnimating; // Were we animating going into the most recent animation step?
/**
* The window size that was requested by the application. These are in
@@ -110,9 +108,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mTurnOnScreen;
int mLayoutSeq = -1;
-
+
Configuration mConfiguration = null;
-
+
/**
* Actual frame shown on-screen (may be modified by animation). These
* are in the screen's coordinate space (WITH the compatibility scale
@@ -212,15 +210,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// an enter animation.
boolean mEnterAnimationPending;
- // Currently running animation.
- boolean mAnimating;
- boolean mLocalAnimating;
- Animation mAnimation;
- boolean mAnimationIsEntrance;
- boolean mHasTransformation;
- boolean mHasLocalTransformation;
- final Transformation mTransformation = new Transformation();
-
// If a window showing a wallpaper: the requested offset for the
// wallpaper; if a wallpaper window: the currently applied offset.
float mWallpaperX = -1;
@@ -305,6 +294,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
int mAnimDw;
int mAnimDh;
+ final WindowStateAnimator mWinAnimator;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
int viewVisibility) {
@@ -333,6 +324,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mBaseLayer = 0;
mSubLayer = 0;
mInputWindowHandle = null;
+ mWinAnimator = null;
return;
}
mDeathRecipient = deathRecipient;
@@ -369,9 +361,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mIsFloatingLayer = mIsImWindow || mIsWallpaper;
}
+ mWinAnimator = new WindowStateAnimator(service, this, mAttachedWindow);
+
WindowState appWin = this;
while (appWin.mAttachedWindow != null) {
- appWin = mAttachedWindow;
+ appWin = appWin.mAttachedWindow;
}
WindowToken appToken = appWin.mToken;
while (appToken.appWindowToken == null) {
@@ -405,6 +399,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mSession.windowAddedLocked();
}
+ @Override
public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
mHaveFrame = true;
@@ -547,38 +542,47 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
+ @Override
public Rect getFrameLw() {
return mFrame;
}
+ @Override
public RectF getShownFrameLw() {
return mShownFrame;
}
+ @Override
public Rect getDisplayFrameLw() {
return mDisplayFrame;
}
+ @Override
public Rect getContentFrameLw() {
return mContentFrame;
}
+ @Override
public Rect getVisibleFrameLw() {
return mVisibleFrame;
}
+ @Override
public boolean getGivenInsetsPendingLw() {
return mGivenInsetsPending;
}
+ @Override
public Rect getGivenContentInsetsLw() {
return mGivenContentInsets;
}
+ @Override
public Rect getGivenVisibleInsetsLw() {
return mGivenVisibleInsets;
}
+ @Override
public WindowManager.LayoutParams getAttrs() {
return mAttrs;
}
@@ -632,37 +636,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mAppToken != null ? mAppToken.firstWindowDrawn : false;
}
- public void setAnimation(Animation anim) {
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
- mAnimating = false;
- mLocalAnimating = false;
- mAnimation = anim;
- mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
- mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
- }
-
- public void clearAnimation() {
- if (mAnimation != null) {
- mAnimating = true;
- mLocalAnimating = false;
- mAnimation.cancel();
- mAnimation = null;
- }
- }
-
- // TODO: Fix and call finishExit() instead of cancelExitAnimationForNextAnimationLocked()
- // for avoiding the code duplication.
- void cancelExitAnimationForNextAnimationLocked() {
- if (!mExiting) return;
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- destroySurfaceLocked();
- }
- mExiting = false;
- }
-
Surface createSurfaceLocked() {
if (mSurface == null) {
mReportDestroySurface = false;
@@ -927,19 +900,21 @@ final class WindowState implements WindowManagerPolicy.WindowState {
+ (mAppToken != null ? mAppToken.hiddenRequested : false)
+ " tok.hidden="
+ (mAppToken != null ? mAppToken.hidden : false)
- + " animating=" + mAnimating
+ + " animating=" + mWinAnimator.mAnimating
+ " tok animating="
+ (mAppToken != null ? mAppToken.animating : false));
if (!mService.showSurfaceRobustlyLocked(this)) {
return false;
}
+
+ mService.enableScreenIfNeededLocked();
+
+ mService.applyEnterAnimationLocked(this);
+
mLastAlpha = -1;
mHasDrawn = true;
mLastHidden = false;
mReadyToShow = false;
- mService.enableScreenIfNeededLocked();
-
- mService.applyEnterAnimationLocked(this);
int i = mChildWindows.size();
while (i > 0) {
@@ -972,204 +947,21 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// will do an animation to reveal it from behind the
// starting window, so there is no need for it to also
// be doing its own stuff.
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
+ if (mWinAnimator.mAnimation != null) {
+ mWinAnimator.mAnimation.cancel();
+ mWinAnimator.mAnimation = null;
// Make sure we clean up the animation.
- mAnimating = true;
+ mWinAnimator.mAnimating = true;
}
mService.mFinishedStarting.add(mAppToken);
mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
}
mAppToken.updateReportedVisibilityLocked();
}
- }
- return true;
- }
-
- private boolean stepAnimation(long currentTime) {
- if ((mAnimation == null) || !mLocalAnimating) {
- return false;
- }
- mTransformation.clear();
- final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Stepped animation in " + this +
- ": more=" + more + ", xform=" + mTransformation);
- return more;
- }
-
- // This must be called while inside a transaction. Returns true if
- // there is more animation to run.
- boolean stepAnimationLocked(long currentTime) {
- // Save the animation state as it was before this step so WindowManagerService can tell if
- // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
- mWasAnimating = mAnimating;
- if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOnFully()) {
- // We will run animations as long as the display isn't frozen.
-
- if (isDrawnLw() && mAnimation != null) {
- mHasTransformation = true;
- mHasLocalTransformation = true;
- if (!mLocalAnimating) {
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Starting animation in " + this +
- " @ " + currentTime + ": ww=" + mFrame.width() +
- " wh=" + mFrame.height() +
- " dw=" + mAnimDw + " dh=" + mAnimDh +
- " scale=" + mService.mWindowAnimationScale);
- mAnimation.initialize(mFrame.width(), mFrame.height(), mAnimDw, mAnimDh);
- mAnimation.setStartTime(currentTime);
- mLocalAnimating = true;
- mAnimating = true;
- }
- if ((mAnimation != null) && mLocalAnimating) {
- if (stepAnimation(currentTime)) {
- return true;
- }
- }
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Finished animation in " + this +
- " @ " + currentTime);
- //WindowManagerService.this.dump();
- }
- mHasLocalTransformation = false;
- if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
- && mAppToken.animation != null) {
- // When our app token is animating, we kind-of pretend like
- // we are as well. Note the mLocalAnimating mAnimationIsEntrance
- // part of this check means that we will only do this if
- // our window is not currently exiting, or it is not
- // locally animating itself. The idea being that one that
- // is exiting and doing a local animation should be removed
- // once that animation is done.
- mAnimating = true;
- mHasTransformation = true;
- mTransformation.clear();
- return false;
- } else if (mHasTransformation) {
- // Little trick to get through the path below to act like
- // we have finished an animation.
- mAnimating = true;
- } else if (isAnimating()) {
- mAnimating = true;
- }
- } else if (mAnimation != null) {
- // If the display is frozen, and there is a pending animation,
- // clear it and make sure we run the cleanup code.
- mAnimating = true;
- mLocalAnimating = true;
- mAnimation.cancel();
- mAnimation = null;
- }
-
- if (!mAnimating && !mLocalAnimating) {
+ } else {
return false;
}
-
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mExiting
- + ", reportedVisible="
- + (mAppToken != null ? mAppToken.reportedVisible : false));
-
- mAnimating = false;
- mLocalAnimating = false;
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- }
- if (mService.mWindowDetachedWallpaper == this) {
- mService.mWindowDetachedWallpaper = null;
- }
- mAnimLayer = mLayer;
- if (mIsImWindow) {
- mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
- } else if (mIsWallpaper) {
- mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
- }
- if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this
- + " anim layer: " + mAnimLayer);
- mHasTransformation = false;
- mHasLocalTransformation = false;
- if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
- if (DEBUG_VISIBILITY) {
- Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": "
- + mPolicyVisibilityAfterAnim);
- }
- mPolicyVisibility = mPolicyVisibilityAfterAnim;
- mService.mLayoutNeeded = true;
- if (!mPolicyVisibility) {
- if (mService.mCurrentFocus == this) {
- mService.mFocusMayChange = true;
- }
- // Window is no longer visible -- make sure if we were waiting
- // for it to be displayed before enabling the display, that
- // we allow the display to be enabled now.
- mService.enableScreenIfNeededLocked();
- }
- }
- mTransformation.clear();
- if (mHasDrawn
- && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
- && mAppToken != null
- && mAppToken.firstWindowDrawn
- && mAppToken.startingData != null) {
- if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting "
- + mToken + ": first real window done animating");
- mService.mFinishedStarting.add(mAppToken);
- mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
- }
-
- finishExit();
- mService.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-
- if (mAppToken != null) {
- mAppToken.updateReportedVisibilityLocked();
- }
-
- return false;
- }
-
- void finishExit() {
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "finishExit in " + this
- + ": exiting=" + mExiting
- + " remove=" + mRemoveOnExit
- + " windowAnimating=" + isWindowAnimating());
-
- final int N = mChildWindows.size();
- for (int i=0; i<N; i++) {
- mChildWindows.get(i).finishExit();
- }
-
- if (!mExiting) {
- return;
- }
-
- if (isWindowAnimating()) {
- return;
- }
-
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Exit animation finished in " + this
- + ": remove=" + mRemoveOnExit);
- if (mSurface != null) {
- mService.mDestroySurface.add(this);
- mDestroying = true;
- if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "HIDE (finishExit)", null);
- mSurfaceShown = false;
- try {
- mSurface.hide();
- } catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e);
- }
- mLastHidden = true;
- }
- mExiting = false;
- if (mRemoveOnExit) {
- mService.mPendingRemove.add(this);
- mRemoveOnExit = false;
- }
+ return true;
}
boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
@@ -1190,10 +982,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
void computeShownFrameLocked() {
- final boolean selfTransformation = mHasLocalTransformation;
+ final boolean selfTransformation = mWinAnimator.mHasLocalTransformation;
Transformation attachedTransformation =
- (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
- ? mAttachedWindow.mTransformation : null;
+ (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation)
+ ? mAttachedWindow.mWinAnimator.mTransformation : null;
Transformation appTransformation =
(mAppToken != null && mAppToken.hasTransformation)
? mAppToken.transformation : null;
@@ -1202,10 +994,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// are currently targeting.
if (mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
&& mService.mWallpaperTarget != null) {
- if (mService.mWallpaperTarget.mHasLocalTransformation &&
- mService.mWallpaperTarget.mAnimation != null &&
- !mService.mWallpaperTarget.mAnimation.getDetachWallpaper()) {
- attachedTransformation = mService.mWallpaperTarget.mTransformation;
+ if (mService.mWallpaperTarget.mWinAnimator.mHasLocalTransformation &&
+ mService.mWallpaperTarget.mWinAnimator.mAnimation != null &&
+ !mService.mWallpaperTarget.mWinAnimator.mAnimation.getDetachWallpaper()) {
+ attachedTransformation = mService.mWallpaperTarget.mWinAnimator.mTransformation;
if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation);
}
@@ -1221,8 +1013,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
- final boolean screenAnimation = mService.mScreenRotationAnimation != null
- && mService.mScreenRotationAnimation.isAnimating();
+ final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null
+ && mService.mAnimator.mScreenRotationAnimation.isAnimating();
if (selfTransformation || attachedTransformation != null
|| appTransformation != null || screenAnimation) {
// cache often used attributes locally
@@ -1251,7 +1043,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
tmpMatrix.postScale(mGlobalScale, mGlobalScale);
if (selfTransformation) {
- tmpMatrix.postConcat(mTransformation.getMatrix());
+ tmpMatrix.postConcat(mWinAnimator.mTransformation.getMatrix());
}
tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
if (attachedTransformation != null) {
@@ -1262,7 +1054,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
if (screenAnimation) {
tmpMatrix.postConcat(
- mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+ mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
}
// "convert" it into SurfaceFlinger's format
@@ -1295,7 +1087,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
&& x == frame.left && y == frame.top))) {
//Slog.i(TAG, "Applying alpha transform");
if (selfTransformation) {
- mShownAlpha *= mTransformation.getAlpha();
+ mShownAlpha *= mWinAnimator.mTransformation.getAlpha();
}
if (attachedTransformation != null) {
mShownAlpha *= attachedTransformation.getAlpha();
@@ -1305,7 +1097,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
if (screenAnimation) {
mShownAlpha *=
- mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+ mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
}
} else {
//Slog.i(TAG, "Not applying alpha transform");
@@ -1314,7 +1106,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "computeShownFrameLocked: Animating " + this +
": " + mShownFrame +
- ", alpha=" + mTransformation.getAlpha() + ", mShownAlpha=" + mShownAlpha);
+ ", alpha=" + mWinAnimator.mTransformation.getAlpha() + ", mShownAlpha=" + mShownAlpha);
return;
}
@@ -1365,7 +1157,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
&& !mRootToken.hidden)
- || mAnimation != null || animating);
+ || mWinAnimator.mAnimation != null || animating);
}
/**
@@ -1422,10 +1214,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (atoken != null) {
return mSurface != null && mPolicyVisibility && !mDestroying
&& ((!mAttachedHidden && !atoken.hiddenRequested)
- || mAnimation != null || atoken.animation != null);
+ || mWinAnimator.mAnimation != null || atoken.animation != null);
} else {
return mSurface != null && mPolicyVisibility && !mDestroying
- && (!mAttachedHidden || mAnimation != null);
+ && (!mAttachedHidden || mWinAnimator.mAnimation != null);
}
}
@@ -1441,26 +1233,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mSurface != null && mPolicyVisibility && !mDestroying
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
&& !mRootToken.hidden)
- || mAnimation != null
+ || mWinAnimator.mAnimation != null
|| ((mAppToken != null) && (mAppToken.animation != null)));
}
- /** Is the window or its container currently animating? */
- boolean isAnimating() {
- final WindowState attached = mAttachedWindow;
- final AppWindowToken atoken = mAppToken;
- return mAnimation != null
- || (attached != null && attached.mAnimation != null)
- || (atoken != null &&
- (atoken.animation != null
- || atoken.inPendingTransaction));
- }
-
- /** Is this window currently animating? */
- boolean isWindowAnimating() {
- return mAnimation != null;
- }
-
/**
* Like isOnScreen, but returns false if the surface hasn't yet
* been drawn.
@@ -1470,7 +1246,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return isDrawnLw() && mPolicyVisibility
&& ((!mAttachedHidden &&
(atoken == null || !atoken.hiddenRequested))
- || mAnimating);
+ || mWinAnimator.mAnimating);
}
public boolean isGoneForLayoutLw() {
@@ -1499,7 +1275,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean isOpaqueDrawn() {
return (mAttrs.format == PixelFormat.OPAQUE
|| mAttrs.type == TYPE_WALLPAPER)
- && isDrawnLw() && mAnimation == null
+ && isDrawnLw() && mWinAnimator.mAnimation == null
&& (mAppToken == null || mAppToken.animation == null);
}
@@ -1509,11 +1285,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* sense to call from performLayoutAndPlaceSurfacesLockedInner().)
*/
boolean shouldAnimateMove() {
- return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen
+ return mContentChanged && !mExiting && !mLastHidden && mService.okToDisplay()
&& (mFrame.top != mLastFrame.top
|| mFrame.left != mLastFrame.left)
- && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
- && mService.mPolicy.isScreenOnFully();
+ && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());
}
boolean isFullscreen(int screenWidth, int screenHeight) {
@@ -1599,10 +1374,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
if (doAnimation) {
if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
- + mPolicyVisibility + " mAnimation=" + mAnimation);
- if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
+ + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
+ if (!mService.okToDisplay()) {
doAnimation = false;
- } else if (mPolicyVisibility && mAnimation == null) {
+ } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) {
// Check for the case where we are currently visible and
// not animating; we do not want to do animation at such a
// point to become visible when we already are.
@@ -1626,7 +1401,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean hideLw(boolean doAnimation, boolean requestAnim) {
if (doAnimation) {
- if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
+ if (!mService.okToDisplay()) {
doAnimation = false;
}
}
@@ -1638,7 +1413,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
if (doAnimation) {
mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
- if (mAnimation == null) {
+ if (mWinAnimator.mAnimation == null) {
doAnimation = false;
}
}
@@ -1813,20 +1588,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(" last="); mLastVisibleInsets.printShortString(pw);
pw.println();
}
- if (mAnimating || mLocalAnimating || mAnimationIsEntrance
- || mAnimation != null) {
- pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
- pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
- pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
- pw.print(" mAnimation="); pw.println(mAnimation);
- }
- if (mHasTransformation || mHasLocalTransformation) {
- pw.print(prefix); pw.print("XForm: has=");
- pw.print(mHasTransformation);
- pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
- pw.print(" "); mTransformation.printShortString(pw);
- pw.println();
- }
+ mWinAnimator.dump(pw, prefix, dumpAll);
if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
pw.print(" mAlpha="); pw.print(mAlpha);
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
new file mode 100644
index 0000000..d86d411
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -0,0 +1,298 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import android.util.Slog;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import java.io.PrintWriter;
+
+/**
+ * @author cmautner@google.com (Craig Mautner)
+ *
+ */
+class WindowStateAnimator {
+
+ final WindowManagerService mService;
+ final WindowState mWin;
+ final WindowState mAttachedWindow;
+
+ // Currently running animation.
+ boolean mAnimating;
+ boolean mLocalAnimating;
+ Animation mAnimation;
+ boolean mAnimationIsEntrance;
+ boolean mHasTransformation;
+ boolean mHasLocalTransformation;
+ final Transformation mTransformation = new Transformation();
+ boolean mWasAnimating; // Were we animating going into the most recent animation step?
+
+ public WindowStateAnimator(final WindowManagerService service, final WindowState win,
+ final WindowState attachedWindow) {
+ mService = service;
+ mWin = win;
+ mAttachedWindow = attachedWindow;
+ }
+
+ public void setAnimation(Animation anim) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+ mAnimating = false;
+ mLocalAnimating = false;
+ mAnimation = anim;
+ mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+ mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
+ // Start out animation gone if window is gone, or visible if window is visible.
+ mTransformation.clear();
+ mTransformation.setAlpha(mWin.mLastHidden ? 0 : 1);
+ mHasLocalTransformation = true;
+ }
+
+ public void clearAnimation() {
+ if (mAnimation != null) {
+ mAnimating = true;
+ mLocalAnimating = false;
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+ }
+
+ /** Is the window or its container currently animating? */
+ boolean isAnimating() {
+ final WindowState attached = mAttachedWindow;
+ final AppWindowToken atoken = mWin.mAppToken;
+ return mAnimation != null
+ || (attached != null && attached.mWinAnimator.mAnimation != null)
+ || (atoken != null &&
+ (atoken.animation != null
+ || atoken.inPendingTransaction));
+ }
+
+ /** Is this window currently animating? */
+ boolean isWindowAnimating() {
+ return mAnimation != null;
+ }
+
+ // TODO: Fix and call finishExit() instead of cancelExitAnimationForNextAnimationLocked()
+ // for avoiding the code duplication.
+ void cancelExitAnimationForNextAnimationLocked() {
+ if (!mWin.mExiting) return;
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ mWin.destroySurfaceLocked();
+ }
+ mWin.mExiting = false;
+ }
+
+ private boolean stepAnimation(long currentTime) {
+ if ((mAnimation == null) || !mLocalAnimating) {
+ return false;
+ }
+ mTransformation.clear();
+ final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Stepped animation in " + this +
+ ": more=" + more + ", xform=" + mTransformation);
+ return more;
+ }
+
+ // This must be called while inside a transaction. Returns true if
+ // there is more animation to run.
+ boolean stepAnimationLocked(long currentTime) {
+ // Save the animation state as it was before this step so WindowManagerService can tell if
+ // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
+ mWasAnimating = mAnimating;
+ if (mService.okToDisplay()) {
+ // We will run animations as long as the display isn't frozen.
+
+ if (mWin.isDrawnLw() && mAnimation != null) {
+ mHasTransformation = true;
+ mHasLocalTransformation = true;
+ if (!mLocalAnimating) {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Starting animation in " + this +
+ " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
+ " wh=" + mWin.mFrame.height() +
+ " dw=" + mWin.mAnimDw + " dh=" + mWin.mAnimDh +
+ " scale=" + mService.mWindowAnimationScale);
+ mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mWin.mAnimDw,
+ mWin.mAnimDh);
+ mAnimation.setStartTime(currentTime);
+ mLocalAnimating = true;
+ mAnimating = true;
+ }
+ if ((mAnimation != null) && mLocalAnimating) {
+ if (stepAnimation(currentTime)) {
+ return true;
+ }
+ }
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Finished animation in " + this +
+ " @ " + currentTime);
+ //WindowManagerService.this.dump();
+ }
+ mHasLocalTransformation = false;
+ if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null
+ && mWin.mAppToken.animation != null) {
+ // When our app token is animating, we kind-of pretend like
+ // we are as well. Note the mLocalAnimating mAnimationIsEntrance
+ // part of this check means that we will only do this if
+ // our window is not currently exiting, or it is not
+ // locally animating itself. The idea being that one that
+ // is exiting and doing a local animation should be removed
+ // once that animation is done.
+ mAnimating = true;
+ mHasTransformation = true;
+ mTransformation.clear();
+ return false;
+ } else if (mHasTransformation) {
+ // Little trick to get through the path below to act like
+ // we have finished an animation.
+ mAnimating = true;
+ } else if (isAnimating()) {
+ mAnimating = true;
+ }
+ } else if (mAnimation != null) {
+ // If the display is frozen, and there is a pending animation,
+ // clear it and make sure we run the cleanup code.
+ mAnimating = true;
+ mLocalAnimating = true;
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+
+ if (!mAnimating && !mLocalAnimating) {
+ return false;
+ }
+
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting
+ + ", reportedVisible="
+ + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
+
+ mAnimating = false;
+ mLocalAnimating = false;
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+ if (mService.mWindowDetachedWallpaper == mWin) {
+ mService.mWindowDetachedWallpaper = null;
+ }
+ mWin.mAnimLayer = mWin.mLayer;
+ if (mWin.mIsImWindow) {
+ mWin.mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
+ } else if (mWin.mIsWallpaper) {
+ mWin.mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+ }
+ if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this
+ + " anim layer: " + mWin.mAnimLayer);
+ mHasTransformation = false;
+ mHasLocalTransformation = false;
+ if (mWin.mPolicyVisibility != mWin.mPolicyVisibilityAfterAnim) {
+ if (WindowState.DEBUG_VISIBILITY) {
+ Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": "
+ + mWin.mPolicyVisibilityAfterAnim);
+ }
+ mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim;
+ mService.mLayoutNeeded = true;
+ if (!mWin.mPolicyVisibility) {
+ if (mService.mCurrentFocus == mWin) {
+ mService.mFocusMayChange = true;
+ }
+ // Window is no longer visible -- make sure if we were waiting
+ // for it to be displayed before enabling the display, that
+ // we allow the display to be enabled now.
+ mService.enableScreenIfNeededLocked();
+ }
+ }
+ mTransformation.clear();
+ if (mWin.mHasDrawn
+ && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
+ && mWin.mAppToken != null
+ && mWin.mAppToken.firstWindowDrawn
+ && mWin.mAppToken.startingData != null) {
+ if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting "
+ + mWin.mToken + ": first real window done animating");
+ mService.mFinishedStarting.add(mWin.mAppToken);
+ mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+
+ finishExit();
+ mService.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats("WindowState");
+
+ if (mWin.mAppToken != null) {
+ mWin.mAppToken.updateReportedVisibilityLocked();
+ }
+
+ return false;
+ }
+
+ void finishExit() {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "finishExit in " + this
+ + ": exiting=" + mWin.mExiting
+ + " remove=" + mWin.mRemoveOnExit
+ + " windowAnimating=" + isWindowAnimating());
+
+ final int N = mWin.mChildWindows.size();
+ for (int i=0; i<N; i++) {
+ mWin.mChildWindows.get(i).mWinAnimator.finishExit();
+ }
+
+ if (!mWin.mExiting) {
+ return;
+ }
+
+ if (isWindowAnimating()) {
+ return;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Exit animation finished in " + this
+ + ": remove=" + mWin.mRemoveOnExit);
+ if (mWin.mSurface != null) {
+ mService.mDestroySurface.add(mWin);
+ mWin.mDestroying = true;
+ if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface(
+ mWin, "HIDE (finishExit)", null);
+ mWin.mSurfaceShown = false;
+ try {
+ mWin.mSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e);
+ }
+ mWin.mLastHidden = true;
+ }
+ mWin.mExiting = false;
+ if (mWin.mRemoveOnExit) {
+ mService.mPendingRemove.add(mWin);
+ mWin.mRemoveOnExit = false;
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ if (mAnimating || mLocalAnimating || mAnimationIsEntrance
+ || mAnimation != null) {
+ pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
+ pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
+ pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
+ pw.print(" mAnimation="); pw.println(mAnimation);
+ }
+ if (mHasTransformation || mHasLocalTransformation) {
+ pw.print(prefix); pw.print("XForm: has=");
+ pw.print(mHasTransformation);
+ pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
+ pw.print(" "); mTransformation.printShortString(pw);
+ pw.println();
+ }
+ }
+
+}