summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/AlarmManagerService.java39
-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/ConnectivityService.java3
-rw-r--r--services/java/com/android/server/CountryDetectorService.java5
-rw-r--r--services/java/com/android/server/DropBoxManagerService.java30
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java10
-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/NativeDaemonConnector.java238
-rw-r--r--services/java/com/android/server/NativeDaemonEvent.java43
-rw-r--r--services/java/com/android/server/NetworkManagementService.java2
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java4
-rw-r--r--services/java/com/android/server/NsdService.java269
-rw-r--r--services/java/com/android/server/PowerManagerService.java348
-rw-r--r--services/java/com/android/server/StatusBarManagerService.java26
-rw-r--r--services/java/com/android/server/SystemServer.java34
-rw-r--r--services/java/com/android/server/TelephonyRegistry.java37
-rw-r--r--services/java/com/android/server/UiModeManagerService.java4
-rw-r--r--services/java/com/android/server/UpdateLockService.java125
-rw-r--r--services/java/com/android/server/WallpaperManagerService.java52
-rw-r--r--services/java/com/android/server/WifiService.java65
-rw-r--r--services/java/com/android/server/WiredAccessoryObserver.java150
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityInputFilter.java2
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java1041
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java104
-rw-r--r--services/java/com/android/server/am/ActivityStack.java256
-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/am/ContentProviderRecord.java2
-rw-r--r--services/java/com/android/server/am/IntentBindRecord.java4
-rw-r--r--services/java/com/android/server/am/PendingIntentRecord.java44
-rw-r--r--services/java/com/android/server/am/ProviderMap.java24
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java14
-rw-r--r--services/java/com/android/server/am/TaskRecord.java6
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java10
-rw-r--r--services/java/com/android/server/input/InputApplicationHandle.java (renamed from services/java/com/android/server/wm/InputApplicationHandle.java)7
-rw-r--r--services/java/com/android/server/input/InputFilter.java (renamed from services/java/com/android/server/wm/InputFilter.java)12
-rw-r--r--services/java/com/android/server/input/InputManagerService.java (renamed from services/java/com/android/server/wm/InputManager.java)620
-rw-r--r--services/java/com/android/server/input/InputWindowHandle.java (renamed from services/java/com/android/server/wm/InputWindowHandle.java)7
-rwxr-xr-xservices/java/com/android/server/location/ComprehensiveCountryDetector.java4
-rw-r--r--services/java/com/android/server/net/NetworkIdentitySet.java47
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java236
-rw-r--r--services/java/com/android/server/net/NetworkStatsRecorder.java5
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java116
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java795
-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.java717
-rw-r--r--services/java/com/android/server/pm/UserManager.java110
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java49
-rw-r--r--services/java/com/android/server/wm/AppWindowAnimator.java301
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java203
-rw-r--r--services/java/com/android/server/wm/BlackFrame.java33
-rw-r--r--services/java/com/android/server/wm/DimAnimator.java68
-rw-r--r--services/java/com/android/server/wm/DimSurface.java6
-rw-r--r--services/java/com/android/server/wm/DragState.java2
-rw-r--r--services/java/com/android/server/wm/FakeWindowImpl.java3
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java17
-rw-r--r--services/java/com/android/server/wm/ScreenRotationAnimation.java511
-rw-r--r--services/java/com/android/server/wm/WindowAnimator.java535
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java2347
-rw-r--r--services/java/com/android/server/wm/WindowState.java996
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java1231
68 files changed, 7833 insertions, 4671 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index b8c44d9..32ac8e1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -34,9 +34,9 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.text.TextUtils;
import android.text.format.Time;
-import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
@@ -50,6 +50,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
@@ -89,6 +90,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
private int mDescriptor;
private int mBroadcastRefCount = 0;
private PowerManager.WakeLock mWakeLock;
+ private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>();
private final AlarmThread mWaitThread = new AlarmThread();
private final AlarmHandler mHandler = new AlarmHandler();
private ClockReceiver mClockReceiver;
@@ -477,7 +479,8 @@ class AlarmManagerService extends IAlarmManager.Stub {
: bs.filterStats.entrySet()) {
pw.print(" "); pw.print(fe.getValue().count);
pw.print(" alarms: ");
- pw.println(fe.getKey().getIntent().toShortString(false, true, false));
+ pw.println(fe.getKey().getIntent().toShortString(
+ false, true, false, true));
}
}
}
@@ -667,10 +670,12 @@ class AlarmManagerService extends IAlarmManager.Stub {
Intent.EXTRA_ALARM_COUNT, alarm.count),
mResultReceiver, mHandler);
- // we have an active broadcast so stay awake.
+ // we have an active broadcast so stay awake.
if (mBroadcastRefCount == 0) {
+ setWakelockWorkSource(alarm.operation);
mWakeLock.acquire();
}
+ mInFlight.add(alarm.operation);
mBroadcastRefCount++;
BroadcastStats bs = getStatsLocked(alarm.operation);
@@ -699,7 +704,22 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
}
}
-
+
+ void setWakelockWorkSource(PendingIntent pi) {
+ try {
+ final int uid = ActivityManagerNative.getDefault()
+ .getUidForIntentSender(pi.getTarget());
+ if (uid >= 0) {
+ mWakeLock.setWorkSource(new WorkSource(uid));
+ return;
+ }
+ } catch (Exception e) {
+ }
+
+ // Something went wrong; fall back to attributing the lock to the OS
+ mWakeLock.setWorkSource(null);
+ }
+
private class AlarmHandler extends Handler {
public static final int ALARM_EVENT = 1;
public static final int MINUTE_CHANGE_EVENT = 2;
@@ -875,9 +895,20 @@ class AlarmManagerService extends IAlarmManager.Stub {
fs.count++;
}
}
+ mInFlight.removeFirst();
mBroadcastRefCount--;
if (mBroadcastRefCount == 0) {
mWakeLock.release();
+ } else {
+ // the next of our alarms is now in flight. reattribute the wakelock.
+ final PendingIntent nowInFlight = mInFlight.peekFirst();
+ if (nowInFlight != null) {
+ setWakelockWorkSource(nowInFlight);
+ } else {
+ // should never happen
+ Slog.e(TAG, "Alarm wakelock still held but sent queue empty");
+ mWakeLock.setWorkSource(null);
+ }
}
}
}
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/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index eab60a7..352decf 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2179,8 +2179,9 @@ private NetworkStateTracker makeWimaxStateTracker() {
String dnsString = dns.getHostAddress();
if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
changed = true;
- SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+ SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
}
+ j++;
}
return changed;
}
diff --git a/services/java/com/android/server/CountryDetectorService.java b/services/java/com/android/server/CountryDetectorService.java
index ab61a3c..3112b50 100644
--- a/services/java/com/android/server/CountryDetectorService.java
+++ b/services/java/com/android/server/CountryDetectorService.java
@@ -81,6 +81,9 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
private final static String TAG = "CountryDetector";
+ /** Whether to dump the state of the country detector service to bugreports */
+ private static final boolean DEBUG = false;
+
private final HashMap<IBinder, Receiver> mReceivers;
private final Context mContext;
private ComprehensiveCountryDetector mCountryDetector;
@@ -206,8 +209,10 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
return mSystemReady;
}
+ @SuppressWarnings("unused")
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ if (!DEBUG) return;
try {
final Printer p = new PrintWriterPrinter(fout);
p.println("CountryDetectorService state:");
diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java
index d37c9ab..932cba1 100644
--- a/services/java/com/android/server/DropBoxManagerService.java
+++ b/services/java/com/android/server/DropBoxManagerService.java
@@ -28,6 +28,7 @@ import android.os.Debug;
import android.os.DropBoxManager;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.Message;
import android.os.StatFs;
import android.os.SystemClock;
import android.provider.Settings;
@@ -64,6 +65,9 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int QUOTA_RESCAN_MILLIS = 5000;
+ // mHandler 'what' value.
+ private static final int MSG_SEND_BROADCAST = 1;
+
private static final boolean PROFILE_DUMP = false;
// TODO: This implementation currently uses one file per entry, which is
@@ -88,11 +92,11 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
private int mCachedQuotaBlocks = 0; // Space we can use: computed from free space, etc.
private long mCachedQuotaUptimeMillis = 0;
- // Ensure that all log entries have a unique timestamp
- private long mLastTimestamp = 0;
-
private volatile boolean mBooted = false;
+ // Provide a way to perform sendBroadcast asynchronously to avoid deadlocks.
+ private final Handler mHandler;
+
/** Receives events that might indicate a need to clean up files. */
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -143,11 +147,21 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
mContentResolver.registerContentObserver(
Settings.Secure.CONTENT_URI, true,
new ContentObserver(new Handler()) {
+ @Override
public void onChange(boolean selfChange) {
mReceiver.onReceive(context, (Intent) null);
}
});
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_SEND_BROADCAST) {
+ mContext.sendBroadcast((Intent)msg.obj, android.Manifest.permission.READ_LOGS);
+ }
+ }
+ };
+
// The real work gets done lazily in init() -- that way service creation always
// succeeds, and things like disk problems cause individual method failures.
}
@@ -157,6 +171,7 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
mContext.unregisterReceiver(mReceiver);
}
+ @Override
public void add(DropBoxManager.Entry entry) {
File temp = null;
OutputStream output = null;
@@ -227,14 +242,17 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
long time = createEntry(temp, tag, flags);
temp = null;
- Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
+ final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag);
dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time);
if (!mBooted) {
dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
- mContext.sendBroadcast(dropboxIntent, android.Manifest.permission.READ_LOGS);
-
+ // Call sendBroadcast after returning from this call to avoid deadlock. In particular
+ // the caller may be holding the WindowManagerService lock but sendBroadcast requires a
+ // lock in ActivityManagerService. ActivityManagerService has been caught holding that
+ // very lock while waiting for the WindowManagerService lock.
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_SEND_BROADCAST, dropboxIntent));
} catch (IOException e) {
Slog.e(TAG, "Can't write: " + tag, e);
} finally {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c705646..96ee2f0 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1132,6 +1132,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private boolean needsToShowImeSwitchOngoingNotification() {
if (!mShowOngoingImeSwitcherForPhones) return false;
+ if (isScreenLocked()) return false;
synchronized (mMethodMap) {
List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
final int N = imis.size();
@@ -2148,15 +2149,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mContext.startActivity(intent);
}
+ private boolean isScreenLocked() {
+ return mKeyguardManager != null
+ && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
+ }
private void showInputMethodMenuInternal(boolean showSubtypes) {
if (DEBUG) Slog.v(TAG, "Show switching menu");
final Context context = mContext;
final PackageManager pm = context.getPackageManager();
- final boolean isScreenLocked = mKeyguardManager != null
- && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
+ final boolean isScreenLocked = isScreenLocked();
- String lastInputMethodId = Settings.Secure.getString(context
+ final String lastInputMethodId = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
int lastInputMethodSubtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
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/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 308661f..0b5eaff 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -34,8 +34,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.LinkedList;
/**
* Generic connector class for interfacing with a native daemon which uses the
@@ -50,11 +50,15 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
private OutputStream mOutputStream;
private LocalLog mLocalLog;
- private final BlockingQueue<NativeDaemonEvent> mResponseQueue;
+ private final ResponseQueue mResponseQueue;
private INativeDaemonConnectorCallbacks mCallbacks;
private Handler mCallbackHandler;
+ private AtomicInteger mSequenceNumber;
+
+ private static final int DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */
+
/** Lock held whenever communicating with native daemon. */
private final Object mDaemonLock = new Object();
@@ -64,7 +68,8 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
int responseQueueSize, String logTag, int maxLogSize) {
mCallbacks = callbacks;
mSocket = socket;
- mResponseQueue = new LinkedBlockingQueue<NativeDaemonEvent>(responseQueueSize);
+ mResponseQueue = new ResponseQueue(responseQueueSize);
+ mSequenceNumber = new AtomicInteger(0);
TAG = logTag != null ? logTag : "NativeDaemonConnector";
mLocalLog = new LocalLog(maxLogSize);
}
@@ -79,7 +84,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
try {
listenToSocket();
} catch (Exception e) {
- Slog.e(TAG, "Error in NativeDaemonConnector", e);
+ loge("Error in NativeDaemonConnector: " + e);
SystemClock.sleep(5000);
}
}
@@ -90,12 +95,10 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
String event = (String) msg.obj;
try {
if (!mCallbacks.onEvent(msg.what, event, event.split(" "))) {
- Slog.w(TAG, String.format(
- "Unhandled event '%s'", event));
+ log(String.format("Unhandled event '%s'", event));
}
} catch (Exception e) {
- Slog.e(TAG, String.format(
- "Error handling '%s'", event), e);
+ loge("Error handling '" + event + "': " + e);
}
return true;
}
@@ -111,7 +114,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
socket.connect(address);
InputStream inputStream = socket.getInputStream();
- mOutputStream = socket.getOutputStream();
+ synchronized (mDaemonLock) {
+ mOutputStream = socket.getOutputStream();
+ }
mCallbacks.onDaemonConnected();
@@ -120,7 +125,10 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
while (true) {
int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
- if (count < 0) break;
+ if (count < 0) {
+ loge("got " + count + " reading with start = " + start);
+ break;
+ }
// Add our starting point to the count and reset the start.
count += start;
@@ -140,14 +148,10 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
event.getCode(), event.getRawEvent()));
} else {
- try {
- mResponseQueue.put(event);
- } catch (InterruptedException ex) {
- Slog.e(TAG, "Failed to put response onto queue: " + ex);
- }
+ mResponseQueue.add(event.getCmdNumber(), event);
}
} catch (IllegalArgumentException e) {
- Slog.w(TAG, "Problem parsing message: " + rawEvent, e);
+ log("Problem parsing message: " + rawEvent + " - " + e);
}
start = i + 1;
@@ -169,15 +173,16 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
}
}
} catch (IOException ex) {
- Slog.e(TAG, "Communications error", ex);
+ loge("Communications error: " + ex);
throw ex;
} finally {
synchronized (mDaemonLock) {
if (mOutputStream != null) {
try {
+ loge("closing stream for " + mSocket);
mOutputStream.close();
} catch (IOException e) {
- Slog.w(TAG, "Failed closing output stream", e);
+ loge("Failed closing output stream: " + e);
}
mOutputStream = null;
}
@@ -188,24 +193,22 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
socket.close();
}
} catch (IOException ex) {
- Slog.w(TAG, "Failed closing socket", ex);
+ loge("Failed closing socket: " + ex);
}
}
}
/**
- * Send command to daemon, escaping arguments as needed.
- *
- * @return the final command issued.
+ * Make command for daemon, escaping arguments as needed.
*/
- private String sendCommandLocked(String cmd, Object... args)
+ private void makeCommand(StringBuilder builder, String cmd, Object... args)
throws NativeDaemonConnectorException {
// TODO: eventually enforce that cmd doesn't contain arguments
if (cmd.indexOf('\0') >= 0) {
throw new IllegalArgumentException("unexpected command: " + cmd);
}
- final StringBuilder builder = new StringBuilder(cmd);
+ builder.append(cmd);
for (Object arg : args) {
final String argString = String.valueOf(arg);
if (argString.indexOf('\0') >= 0) {
@@ -215,23 +218,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
builder.append(' ');
appendEscaped(builder, argString);
}
-
- final String unterminated = builder.toString();
- log("SND -> {" + unterminated + "}");
-
- builder.append('\0');
-
- if (mOutputStream == null) {
- throw new NativeDaemonConnectorException("missing output stream");
- } else {
- try {
- mOutputStream.write(builder.toString().getBytes(Charsets.UTF_8));
- } catch (IOException e) {
- throw new NativeDaemonConnectorException("problem sending command", e);
- }
- }
-
- return unterminated;
}
/**
@@ -292,39 +278,63 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
*/
public NativeDaemonEvent[] executeForList(String cmd, Object... args)
throws NativeDaemonConnectorException {
- synchronized (mDaemonLock) {
- return executeLocked(cmd, args);
- }
+ return execute(DEFAULT_TIMEOUT, cmd, args);
}
- private NativeDaemonEvent[] executeLocked(String cmd, Object... args)
+ /**
+ * Issue the given command to the native daemon and return any
+ * {@linke NativeDaemonEvent@isClassContinue()} responses, including the
+ * final terminal response. Note that the timeout does not count time in
+ * deep sleep.
+ *
+ * @throws NativeDaemonConnectorException when problem communicating with
+ * native daemon, or if the response matches
+ * {@link NativeDaemonEvent#isClassClientError()} or
+ * {@link NativeDaemonEvent#isClassServerError()}.
+ */
+ public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
- while (mResponseQueue.size() > 0) {
- try {
- log("ignoring {" + mResponseQueue.take() + "}");
- } catch (Exception e) {}
- }
+ final int sequenceNumber = mSequenceNumber.incrementAndGet();
+ final StringBuilder cmdBuilder =
+ new StringBuilder(Integer.toString(sequenceNumber)).append(' ');
+
+ makeCommand(cmdBuilder, cmd, args);
- final String sentCommand = sendCommandLocked(cmd, args);
+ final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */
+ log("SND -> {" + logCmd + "}");
+
+ cmdBuilder.append('\0');
+ final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */
+
+ synchronized (mDaemonLock) {
+ if (mOutputStream == null) {
+ throw new NativeDaemonConnectorException("missing output stream");
+ } else {
+ try {
+ mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));
+ } catch (IOException e) {
+ throw new NativeDaemonConnectorException("problem sending command", e);
+ }
+ }
+ }
NativeDaemonEvent event = null;
do {
- try {
- event = mResponseQueue.take();
- } catch (InterruptedException e) {
- Slog.w(TAG, "interrupted waiting for event line");
- continue;
+ event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);
+ if (event == null) {
+ loge("timed-out waiting for response to " + logCmd);
+ throw new NativeDaemonFailureException(logCmd, event);
}
events.add(event);
} while (event.isClassContinue());
if (event.isClassClientError()) {
- throw new NativeDaemonArgumentException(sentCommand, event);
+ throw new NativeDaemonArgumentException(logCmd, event);
}
if (event.isClassServerError()) {
- throw new NativeDaemonFailureException(sentCommand, event);
+ throw new NativeDaemonFailureException(logCmd, event);
}
return events.toArray(new NativeDaemonEvent[events.size()]);
@@ -448,10 +458,120 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mLocalLog.dump(fd, pw, args);
+ pw.println();
+ mResponseQueue.dump(fd, pw, args);
}
private void log(String logstring) {
if (LOGD) Slog.d(TAG, logstring);
mLocalLog.log(logstring);
}
+
+ private void loge(String logstring) {
+ Slog.e(TAG, logstring);
+ mLocalLog.log(logstring);
+ }
+
+ private static class ResponseQueue {
+
+ private static class Response {
+ public int cmdNum;
+ public LinkedList<NativeDaemonEvent> responses = new LinkedList<NativeDaemonEvent>();
+ public String request;
+ public Response(int c, String r) {cmdNum = c; request = r;}
+ }
+
+ private final LinkedList<Response> mResponses;
+ private int mMaxCount;
+
+ ResponseQueue(int maxCount) {
+ mResponses = new LinkedList<Response>();
+ mMaxCount = maxCount;
+ }
+
+ public void add(int cmdNum, NativeDaemonEvent response) {
+ Response found = null;
+ synchronized (mResponses) {
+ for (Response r : mResponses) {
+ if (r.cmdNum == cmdNum) {
+ found = r;
+ break;
+ }
+ }
+ if (found == null) {
+ // didn't find it - make sure our queue isn't too big before adding
+ // another..
+ while (mResponses.size() >= mMaxCount) {
+ Slog.e("NativeDaemonConnector.ResponseQueue",
+ "more buffered than allowed: " + mResponses.size() +
+ " >= " + mMaxCount);
+ // let any waiter timeout waiting for this
+ Response r = mResponses.remove();
+ Slog.e("NativeDaemonConnector.ResponseQueue",
+ "Removing request: " + r.request + " (" + r.cmdNum + ")");
+ }
+ found = new Response(cmdNum, null);
+ mResponses.add(found);
+ }
+ found.responses.add(response);
+ }
+ synchronized (found) {
+ found.notify();
+ }
+ }
+
+ // note that the timeout does not count time in deep sleep. If you don't want
+ // the device to sleep, hold a wakelock
+ public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
+ long endTime = SystemClock.uptimeMillis() + timeoutMs;
+ long nowTime;
+ Response found = null;
+ while (true) {
+ synchronized (mResponses) {
+ for (Response response : mResponses) {
+ if (response.cmdNum == cmdNum) {
+ found = response;
+ // how many response fragments are left
+ switch (response.responses.size()) {
+ case 0: // haven't got any - must wait
+ break;
+ case 1: // last one - remove this from the master list
+ mResponses.remove(response); // fall through
+ default: // take one and move on
+ response.request = origCmd;
+ return response.responses.remove();
+ }
+ }
+ }
+ nowTime = SystemClock.uptimeMillis();
+ if (endTime <= nowTime) {
+ Slog.e("NativeDaemonConnector.ResponseQueue",
+ "Timeout waiting for response");
+ return null;
+ }
+ /* pre-allocate so we have something unique to wait on */
+ if (found == null) {
+ found = new Response(cmdNum, origCmd);
+ mResponses.add(found);
+ }
+ }
+ try {
+ synchronized (found) {
+ found.wait(endTime - nowTime);
+ }
+ } catch (InterruptedException e) {
+ // loop around to check if we're done or if it's time to stop waiting
+ }
+ }
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Pending requests:");
+ synchronized (mResponses) {
+ for (Response response : mResponses) {
+ pw.println(" Cmd " + response.cmdNum + " - " + response.request);
+ }
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/NativeDaemonEvent.java b/services/java/com/android/server/NativeDaemonEvent.java
index 62084c0..d5e9f66 100644
--- a/services/java/com/android/server/NativeDaemonEvent.java
+++ b/services/java/com/android/server/NativeDaemonEvent.java
@@ -28,16 +28,22 @@ public class NativeDaemonEvent {
// TODO: keep class ranges in sync with ResponseCode.h
// TODO: swap client and server error ranges to roughly mirror HTTP spec
+ private final int mCmdNumber;
private final int mCode;
private final String mMessage;
private final String mRawEvent;
- private NativeDaemonEvent(int code, String message, String rawEvent) {
+ private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) {
+ mCmdNumber = cmdNumber;
mCode = code;
mMessage = message;
mRawEvent = rawEvent;
}
+ public int getCmdNumber() {
+ return mCmdNumber;
+ }
+
public int getCode() {
return mCode;
}
@@ -89,7 +95,11 @@ public class NativeDaemonEvent {
* Test if event represents an unsolicited event from native daemon.
*/
public boolean isClassUnsolicited() {
- return mCode >= 600 && mCode < 700;
+ return isClassUnsolicited(mCode);
+ }
+
+ private static boolean isClassUnsolicited(int code) {
+ return code >= 600 && code < 700;
}
/**
@@ -110,20 +120,37 @@ public class NativeDaemonEvent {
* from native side.
*/
public static NativeDaemonEvent parseRawEvent(String rawEvent) {
- final int splitIndex = rawEvent.indexOf(' ');
- if (splitIndex == -1) {
- throw new IllegalArgumentException("unable to find ' ' separator");
+ final String[] parsed = rawEvent.split(" ");
+ if (parsed.length < 2) {
+ throw new IllegalArgumentException("Insufficient arguments");
}
+ int skiplength = 0;
+
final int code;
try {
- code = Integer.parseInt(rawEvent.substring(0, splitIndex));
+ code = Integer.parseInt(parsed[0]);
+ skiplength = parsed[0].length() + 1;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("problem parsing code", e);
}
- final String message = rawEvent.substring(splitIndex + 1);
- return new NativeDaemonEvent(code, message, rawEvent);
+ int cmdNumber = -1;
+ if (isClassUnsolicited(code) == false) {
+ if (parsed.length < 3) {
+ throw new IllegalArgumentException("Insufficient arguemnts");
+ }
+ try {
+ cmdNumber = Integer.parseInt(parsed[1]);
+ skiplength += parsed[1].length() + 1;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("problem parsing cmdNumber", e);
+ }
+ }
+
+ final String message = rawEvent.substring(skiplength);
+
+ return new NativeDaemonEvent(cmdNumber, code, message, rawEvent);
}
/**
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 7bb7938..09d0698 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -117,6 +117,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
public static final int InterfaceTxThrottleResult = 219;
public static final int QuotaCounterResult = 220;
public static final int TetheringStatsResult = 221;
+ public static final int DnsProxyQueryResult = 222;
public static final int InterfaceChange = 600;
public static final int BandwidthControl = 601;
@@ -879,7 +880,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
wifiFirmwareReload(wlanIface, "AP");
- mConnector.execute("softap", "start", wlanIface);
if (wifiConfig == null) {
mConnector.execute("softap", "set", wlanIface, softapIface);
} else {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 624ee98..3db4601 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -79,6 +79,7 @@ public class NotificationManagerService extends INotificationManager.Stub
private static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
+ private static final boolean SCORE_ONGOING_HIGHER = false;
final Context mContext;
final IActivityManager mAm;
@@ -171,6 +172,7 @@ public class NotificationManagerService extends INotificationManager.Stub
pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
pw.println(prefix + " tickerText=" + notification.tickerText);
pw.println(prefix + " contentView=" + notification.contentView);
+ pw.println(prefix + " uid=" + uid);
pw.println(prefix + " defaults=0x" + Integer.toHexString(notification.defaults));
pw.println(prefix + " flags=0x" + Integer.toHexString(notification.flags));
pw.println(prefix + " sound=" + notification.sound);
@@ -720,7 +722,7 @@ public class NotificationManagerService extends INotificationManager.Stub
// Migrate notification flags to scores
if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) {
if (notification.priority < Notification.PRIORITY_MAX) notification.priority = Notification.PRIORITY_MAX;
- } else if (0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {
+ } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {
if (notification.priority < Notification.PRIORITY_HIGH) notification.priority = Notification.PRIORITY_HIGH;
}
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
new file mode 100644
index 0000000..768be7d
--- /dev/null
+++ b/services/java/com/android/server/NsdService.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.nsd.DnsSdServiceInfo;
+import android.net.nsd.DnsSdTxtRecord;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.IBinder;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.List;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.AsyncChannel;
+import com.android.server.am.BatteryStatsService;
+import com.android.server.NativeDaemonConnector.Command;
+import com.android.internal.R;
+
+/**
+ * Network Service Discovery Service handles remote service discovery operation requests by
+ * implementing the INsdManager interface.
+ *
+ * @hide
+ */
+public class NsdService extends INsdManager.Stub {
+ private static final String TAG = "NsdService";
+ private static final String MDNS_TAG = "mDnsConnector";
+
+ private static final boolean DBG = true;
+
+ private Context mContext;
+
+ /**
+ * Clients receiving asynchronous messages
+ */
+ private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>();
+
+ private AsyncChannel mReplyChannel = new AsyncChannel();
+
+ /**
+ * Handles client(app) connections
+ */
+ private class AsyncServiceHandler extends Handler {
+
+ AsyncServiceHandler(android.os.Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ AsyncChannel c = (AsyncChannel) msg.obj;
+ if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
+ c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
+ mClients.add(c);
+ } else {
+ Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
+ }
+ break;
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
+ Slog.e(TAG, "Send failed, client connection lost");
+ } else {
+ if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+ }
+ mClients.remove((AsyncChannel) msg.obj);
+ break;
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
+ AsyncChannel ac = new AsyncChannel();
+ ac.connect(mContext, this, msg.replyTo);
+ break;
+ case NsdManager.DISCOVER_SERVICES:
+ if (DBG) Slog.d(TAG, "Discover services");
+ DnsSdServiceInfo s = (DnsSdServiceInfo) msg.obj;
+ discoverServices(1, s.getServiceType());
+ mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED);
+ break;
+ case NsdManager.STOP_DISCOVERY:
+ if (DBG) Slog.d(TAG, "Stop service discovery");
+ mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED);
+ break;
+ case NsdManager.REGISTER_SERVICE:
+ if (DBG) Slog.d(TAG, "Register service");
+ mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED);
+ break;
+ case NsdManager.UPDATE_SERVICE:
+ if (DBG) Slog.d(TAG, "Update service");
+ mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED);
+ break;
+ default:
+ Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg);
+ break;
+ }
+ }
+ }
+ private AsyncServiceHandler mAsyncServiceHandler;
+
+ private NativeDaemonConnector mNativeConnector;
+ private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
+
+ private NsdService(Context context) {
+ mContext = context;
+
+ HandlerThread nsdThread = new HandlerThread("NsdService");
+ nsdThread.start();
+ mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper());
+
+ /*
+ mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
+ MDNS_TAG, 25);
+ Thread th = new Thread(mNativeConnector, MDNS_TAG);
+ th.start();
+ */
+ }
+
+ public static NsdService create(Context context) throws InterruptedException {
+ NsdService service = new NsdService(context);
+ /* service.mNativeDaemonConnected.await(); */
+ return service;
+ }
+
+ public Messenger getMessenger() {
+ return new Messenger(mAsyncServiceHandler);
+ }
+
+ /* These should be in sync with system/netd/mDnsResponseCode.h */
+ class NativeResponseCode {
+ public static final int SERVICE_FOUND = 101;
+ public static final int SERVICE_LOST = 102;
+ public static final int SERVICE_DISCOVERY_FAILED = 103;
+
+ public static final int SERVICE_REGISTERED = 104;
+ public static final int SERVICE_REGISTRATION_FAILED = 105;
+
+ public static final int SERVICE_UPDATED = 106;
+ public static final int SERVICE_UPDATE_FAILED = 107;
+
+ public static final int SERVICE_RESOLVED = 108;
+ public static final int SERVICE_RESOLUTION_FAILED = 109;
+ }
+
+
+ class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
+ public void onDaemonConnected() {
+ mNativeDaemonConnected.countDown();
+ }
+
+ public boolean onEvent(int code, String raw, String[] cooked) {
+ switch (code) {
+ case NativeResponseCode.SERVICE_FOUND:
+ /* NNN uniqueId serviceName regType */
+ break;
+ case NativeResponseCode.SERVICE_LOST:
+ /* NNN uniqueId serviceName regType */
+ break;
+ case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
+ /* NNN uniqueId errorCode */
+ break;
+ case NativeResponseCode.SERVICE_REGISTERED:
+ /* NNN regId serviceName regType */
+ break;
+ case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
+ /* NNN regId errorCode */
+ break;
+ case NativeResponseCode.SERVICE_UPDATED:
+ /* NNN regId */
+ break;
+ case NativeResponseCode.SERVICE_UPDATE_FAILED:
+ /* NNN regId errorCode */
+ break;
+ case NativeResponseCode.SERVICE_RESOLVED:
+ /* NNN resolveId fullName hostName port txtlen txtdata */
+ break;
+ case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
+ /* NNN resovleId errorCode */
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+ }
+
+ private void registerService(int regId, DnsSdServiceInfo service) {
+ try {
+ //Add txtlen and txtdata
+ mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
+ service.getServiceType(), service.getPort());
+ } catch(NativeDaemonConnectorException e) {
+ Slog.e(TAG, "Failed to execute registerService");
+ }
+ }
+
+ private void updateService(int regId, DnsSdTxtRecord t) {
+ try {
+ if (t == null) return;
+ mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
+ } catch(NativeDaemonConnectorException e) {
+ Slog.e(TAG, "Failed to updateServices");
+ }
+ }
+
+ private void discoverServices(int discoveryId, String serviceType) {
+ try {
+ mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
+ } catch(NativeDaemonConnectorException e) {
+ Slog.e(TAG, "Failed to discoverServices");
+ }
+ }
+
+ private void stopServiceDiscovery(int discoveryId) {
+ try {
+ mNativeConnector.execute("mdnssd", "stopdiscover", discoveryId);
+ } catch(NativeDaemonConnectorException e) {
+ Slog.e(TAG, "Failed to stopServiceDiscovery");
+ }
+ }
+
+ private void resolveService(DnsSdServiceInfo service) {
+ try {
+ mNativeConnector.execute("mdnssd", "resolve", service.getServiceName(),
+ service.getServiceType());
+ } catch(NativeDaemonConnectorException e) {
+ Slog.e(TAG, "Failed to resolveService");
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ pw.println("Internal state:");
+ }
+}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 7b4372f..52a4110 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -45,6 +45,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.LocalPowerManager;
+import android.os.Message;
import android.os.Power;
import android.os.PowerManager;
import android.os.Process;
@@ -57,6 +58,7 @@ import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.view.WindowManagerPolicy;
+import static android.view.WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR;
import static android.provider.Settings.System.DIM_SCREEN;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
@@ -76,6 +78,7 @@ import java.util.Observer;
public class PowerManagerService extends IPowerManager.Stub
implements LocalPowerManager, Watchdog.Monitor {
+ private static final int NOMINAL_FRAME_TIME_MS = 1000/60;
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
@@ -131,6 +134,7 @@ public class PowerManagerService extends IPowerManager.Stub
private static final int DEFAULT_SCREEN_BRIGHTNESS = 192;
// flags for setPowerState
+ private static final int ALL_LIGHTS_OFF = 0x00000000;
private static final int SCREEN_ON_BIT = 0x00000001;
private static final int SCREEN_BRIGHT_BIT = 0x00000002;
private static final int BUTTON_BRIGHT_BIT = 0x00000004;
@@ -157,11 +161,12 @@ public class PowerManagerService extends IPowerManager.Stub
// used for noChangeLights in setPowerState()
private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
+ // animate screen lights in PowerManager (as opposed to SurfaceFlinger)
boolean mAnimateScreenLights = true;
- static final int ANIM_STEPS = 60/4;
+ static final int ANIM_STEPS = 60; // nominal # of frames at 60Hz
// Slower animation for autobrightness changes
- static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
+ static final int AUTOBRIGHTNESS_ANIM_STEPS = 2 * ANIM_STEPS;
// Number of steps when performing a more immediate brightness change.
static final int IMMEDIATE_ANIM_STEPS = 4;
@@ -221,12 +226,11 @@ public class PowerManagerService extends IPowerManager.Stub
private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
private UnsynchronizedWakeLock mProximityPartialLock;
private HandlerThread mHandlerThread;
- private HandlerThread mScreenOffThread;
private Handler mScreenOffHandler;
+ private Handler mScreenBrightnessHandler;
private Handler mHandler;
private final TimeoutTask mTimeoutTask = new TimeoutTask();
- private final BrightnessState mScreenBrightness
- = new BrightnessState(SCREEN_BRIGHT_BIT);
+ private ScreenBrightnessAnimator mScreenBrightnessAnimator;
private boolean mStillNeedSleepNotification;
private boolean mIsPowered = false;
private IActivityManager mActivityService;
@@ -271,6 +275,7 @@ public class PowerManagerService extends IPowerManager.Stub
private int mWarningSpewThrottleCount;
private long mWarningSpewThrottleTime;
private int mAnimationSetting = ANIM_SETTING_OFF;
+ private float mWindowScaleAnimation;
// Must match with the ISurfaceComposer constants in C++.
private static final int ANIM_SETTING_ON = 0x01;
@@ -285,7 +290,8 @@ public class PowerManagerService extends IPowerManager.Stub
private static final boolean mSpew = false;
private static final boolean mDebugProximitySensor = (false || mSpew);
private static final boolean mDebugLightSensor = (false || mSpew);
-
+ private static final boolean mDebugLightAnimation = (false || mSpew);
+
private native void nativeInit();
private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
private native void nativeStartSurfaceFlingerAnimation(int mode);
@@ -487,10 +493,10 @@ public class PowerManagerService extends IPowerManager.Stub
// recalculate everything
setScreenOffTimeoutsLocked();
- final float windowScale = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
+ mWindowScaleAnimation = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f);
mAnimationSetting = 0;
- if (windowScale > 0.5f) {
+ if (mWindowScaleAnimation > 0.5f) {
mAnimationSetting |= ANIM_SETTING_OFF;
}
if (transitionScale > 0.5f) {
@@ -540,28 +546,20 @@ public class PowerManagerService extends IPowerManager.Stub
}
mInitComplete = false;
- mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") {
- @Override
- protected void onLooperPrepared() {
- mScreenOffHandler = new Handler();
- synchronized (mScreenOffThread) {
- mInitComplete = true;
- mScreenOffThread.notifyAll();
- }
- }
- };
- mScreenOffThread.start();
+ mScreenBrightnessAnimator = new ScreenBrightnessAnimator("mScreenBrightnessUpdaterThread",
+ Process.THREAD_PRIORITY_DISPLAY);
+ mScreenBrightnessAnimator.start();
- synchronized (mScreenOffThread) {
+ synchronized (mScreenBrightnessAnimator) {
while (!mInitComplete) {
try {
- mScreenOffThread.wait();
+ mScreenBrightnessAnimator.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
-
+
mInitComplete = false;
mHandlerThread = new HandlerThread("PowerManagerService") {
@Override
@@ -581,7 +579,7 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
}
-
+
nativeInit();
Power.powerInitNative();
synchronized (mLocks) {
@@ -1079,7 +1077,6 @@ public class PowerManagerService extends IPowerManager.Stub
int oldPokey = mPokey;
int cumulative = 0;
- boolean oldAwakeOnSet = mPokeAwakeOnSet;
boolean awakeOnSet = false;
for (PokeLock p: mPokeLocks.values()) {
cumulative |= p.pokey;
@@ -1199,7 +1196,7 @@ public class PowerManagerService extends IPowerManager.Stub
+ " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled);
- mScreenBrightness.dump(pw, " mScreenBrightness: ");
+ mScreenBrightnessAnimator.dump(pw, " mScreenBrightnessAnimator: ");
int N = mLocks.size();
pw.println();
@@ -1431,7 +1428,7 @@ public class PowerManagerService extends IPowerManager.Stub
private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
new WindowManagerPolicy.ScreenOnListener() {
- @Override public void onScreenOn() {
+ public void onScreenOn() {
synchronized (mLocks) {
if (mPreparingForScreenOn) {
mPreparingForScreenOn = false;
@@ -1720,7 +1717,8 @@ public class PowerManagerService extends IPowerManager.Stub
+ Integer.toHexString(mPowerState)
+ " mSkippedScreenOn=" + mSkippedScreenOn);
}
- mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
+ mScreenBrightnessHandler.removeMessages(ScreenBrightnessAnimator.ANIMATE_LIGHTS);
+ mScreenBrightnessAnimator.animateTo(Power.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0);
}
}
int err = Power.setScreenState(on);
@@ -1860,6 +1858,7 @@ public class PowerManagerService extends IPowerManager.Stub
} else {
// Update the lights *before* taking care of turning the
// screen off, so we can initiate any animations that are desired.
+ mScreenOffReason = reason;
if (stateChanged) {
updateLightsLocked(newState, 0);
}
@@ -1878,8 +1877,7 @@ public class PowerManagerService extends IPowerManager.Stub
Binder.restoreCallingIdentity(identity);
}
mPowerState &= ~SCREEN_ON_BIT;
- mScreenOffReason = reason;
- if (!mScreenBrightness.animating) {
+ if (!mScreenBrightnessAnimator.isAnimating()) {
err = screenOffFinishedAnimatingLocked(reason);
} else {
err = 0;
@@ -1953,11 +1951,11 @@ public class PowerManagerService extends IPowerManager.Stub
// If the screen is not currently on, we will want to delay actually
// turning the lights on if we are still getting the UI put up.
- if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
+ if ((oldState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
// Don't turn screen on until we know we are really ready to.
// This is to avoid letting the screen go on before things like the
// lock screen have been displayed.
- if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) {
+ if ((mSkippedScreenOn = shouldDeferScreenOnLocked())) {
newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
}
}
@@ -2017,7 +2015,7 @@ public class PowerManagerService extends IPowerManager.Stub
case SCREEN_BRIGHT_BIT:
default:
// not possible
- nominalCurrentValue = (int)mScreenBrightness.curValue;
+ nominalCurrentValue = (int)mScreenBrightnessAnimator.getCurrentBrightness();
break;
}
}
@@ -2067,8 +2065,8 @@ public class PowerManagerService extends IPowerManager.Stub
Binder.restoreCallingIdentity(identity);
}
if (!mSkippedScreenOn) {
- mScreenBrightness.setTargetLocked(brightness, steps,
- INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ int dt = steps * NOMINAL_FRAME_TIME_MS;
+ mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, dt);
if (DEBUG_SCREEN_ON) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
@@ -2111,154 +2109,168 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
- private void setLightBrightness(int mask, int value) {
- int brightnessMode = (mAutoBrightessEnabled
- ? LightsService.BRIGHTNESS_MODE_SENSOR
- : LightsService.BRIGHTNESS_MODE_USER);
- if ((mask & SCREEN_BRIGHT_BIT) != 0) {
- if (DEBUG_SCREEN_ON) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Slog.i(TAG, "Set LCD brightness: " + value, e);
- }
- mLcdLight.setBrightness(value, brightnessMode);
- }
- if ((mask & BUTTON_BRIGHT_BIT) != 0) {
- mButtonLight.setBrightness(value);
- }
- if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
- mKeyboardLight.setBrightness(value);
+ /**
+ * Note: by design this class does not hold mLocks while calling native methods.
+ * Nor should it. Ever.
+ */
+ class ScreenBrightnessAnimator extends HandlerThread {
+ static final int ANIMATE_LIGHTS = 10;
+ static final int ANIMATE_POWER_OFF = 11;
+ volatile int startValue;
+ volatile int endValue;
+ volatile int currentValue;
+ private int currentMask;
+ private int duration;
+ private long startTimeMillis;
+ private final String prefix;
+
+ public ScreenBrightnessAnimator(String name, int priority) {
+ super(name, priority);
+ prefix = name;
}
- }
- class BrightnessState implements Runnable {
- final int mask;
+ @Override
+ protected void onLooperPrepared() {
+ mScreenBrightnessHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ int brightnessMode = (mAutoBrightessEnabled && !mInitialAnimation
+ ? LightsService.BRIGHTNESS_MODE_SENSOR
+ : LightsService.BRIGHTNESS_MODE_USER);
+ if (msg.what == ANIMATE_LIGHTS) {
+ final int mask = msg.arg1;
+ int value = msg.arg2;
+ long tStart = SystemClock.uptimeMillis();
+ if ((mask & SCREEN_BRIGHT_BIT) != 0) {
+ if (mDebugLightAnimation) Log.v(TAG, "Set brightness: " + value);
+ mLcdLight.setBrightness(value, brightnessMode);
+ }
+ long elapsed = SystemClock.uptimeMillis() - tStart;
+ if ((mask & BUTTON_BRIGHT_BIT) != 0) {
+ mButtonLight.setBrightness(value);
+ }
+ if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
+ mKeyboardLight.setBrightness(value);
+ }
- boolean initialized;
- int targetValue;
- float curValue;
- float delta;
- boolean animating;
+ if (elapsed > 100) {
+ Log.e(TAG, "Excessive delay setting brightness: " + elapsed
+ + "ms, mask=" + mask);
+ }
- BrightnessState(int m) {
- mask = m;
+ // Throttle brightness updates to frame refresh rate
+ int delay = elapsed < NOMINAL_FRAME_TIME_MS ? NOMINAL_FRAME_TIME_MS : 0;
+ synchronized(this) {
+ currentValue = value;
+ }
+ animateInternal(mask, false, delay);
+ } else if (msg.what == ANIMATE_POWER_OFF) {
+ int mode = msg.arg1;
+ nativeStartSurfaceFlingerAnimation(mode);
+ }
+ }
+ };
+ synchronized (this) {
+ mInitComplete = true;
+ notifyAll();
+ }
}
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "animating=" + animating
- + " targetValue=" + targetValue
- + " curValue=" + curValue
- + " delta=" + delta);
- }
+ private void animateInternal(int mask, boolean turningOff, int delay) {
+ synchronized (this) {
+ if (currentValue != endValue) {
+ final long now = SystemClock.elapsedRealtime();
+ final int elapsed = (int) (now - startTimeMillis);
+ int newValue;
+ if (elapsed < duration) {
+ int delta = endValue - startValue;
+ newValue = startValue + delta * elapsed / duration;
+ newValue = Math.max(Power.BRIGHTNESS_OFF, newValue);
+ newValue = Math.min(Power.BRIGHTNESS_ON, newValue);
+ } else {
+ newValue = endValue;
+ mInitialAnimation = false;
+ }
- void forceValueLocked(int value) {
- targetValue = -1;
- curValue = value;
- setLightBrightness(mask, value);
- if (animating) {
- finishAnimationLocked(false, value);
- }
- }
+ if (mDebugLightAnimation) {
+ Log.v(TAG, "Animating light: " + "start:" + startValue
+ + ", end:" + endValue + ", elapsed:" + elapsed
+ + ", duration:" + duration + ", current:" + currentValue
+ + ", delay:" + delay);
+ }
- void setTargetLocked(int target, int stepsToTarget, int initialValue,
- int nominalCurrentValue) {
- if (!initialized) {
- initialized = true;
- curValue = (float)initialValue;
- } else if (targetValue == target) {
- return;
- }
- targetValue = target;
- delta = (targetValue -
- (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
- / stepsToTarget;
- if (mSpew || DEBUG_SCREEN_ON) {
- String noticeMe = nominalCurrentValue == curValue ? "" : " ******************";
- Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue
- + " target=" + target + " targetValue=" + targetValue + " delta=" + delta
- + " nominalCurrentValue=" + nominalCurrentValue
- + noticeMe);
+ if (turningOff && !mHeadless && !mAnimateScreenLights) {
+ int mode = mScreenOffReason == OFF_BECAUSE_OF_PROX_SENSOR
+ ? 0 : mAnimationSetting;
+ if (mDebugLightAnimation) Log.v(TAG, "Doing power-off anim, mode=" + mode);
+ mScreenBrightnessHandler.obtainMessage(ANIMATE_POWER_OFF, mode, 0)
+ .sendToTarget();
+ }
+ Message msg = mScreenBrightnessHandler
+ .obtainMessage(ANIMATE_LIGHTS, mask, newValue);
+ mScreenBrightnessHandler.sendMessageDelayed(msg, delay);
+ }
}
- animating = true;
+ }
- if (mSpew) {
- Slog.i(TAG, "scheduling light animator");
- }
- mScreenOffHandler.removeCallbacks(this);
- mScreenOffHandler.post(this);
+ public void dump(PrintWriter pw, String string) {
+ pw.println(prefix + "animating: " + "start:" + startValue + ", end:" + endValue
+ + ", duration:" + duration + ", current:" + currentValue);
}
- boolean stepLocked() {
- if (!animating) return false;
- if (false && mSpew) {
- Slog.i(TAG, "Step target " + mask + ": cur=" + curValue
- + " target=" + targetValue + " delta=" + delta);
- }
- curValue += delta;
- int curIntValue = (int)curValue;
- boolean more = true;
- if (delta == 0) {
- curValue = curIntValue = targetValue;
- more = false;
- } else if (delta > 0) {
- if (curIntValue >= targetValue) {
- curValue = curIntValue = targetValue;
- more = false;
+ public void animateTo(int target, int mask, int animationDuration) {
+ synchronized(this) {
+ startValue = currentValue;
+ endValue = target;
+ currentMask = mask;
+ duration = (int) (mWindowScaleAnimation * animationDuration);
+ startTimeMillis = SystemClock.elapsedRealtime();
+ mInitialAnimation = currentValue == 0 && target > 0;
+
+ if (mDebugLightAnimation) {
+ Log.v(TAG, "animateTo(target=" + target + ", mask=" + mask
+ + ", duration=" + animationDuration +")"
+ + ", currentValue=" + currentValue
+ + ", startTime=" + startTimeMillis);
}
- } else {
- if (curIntValue <= targetValue) {
- curValue = curIntValue = targetValue;
- more = false;
+
+ if (target != currentValue) {
+ final boolean doScreenAnim = (mask & (SCREEN_BRIGHT_BIT | SCREEN_ON_BIT)) != 0;
+ final boolean turningOff = endValue == Power.BRIGHTNESS_OFF;
+ if (turningOff && doScreenAnim) {
+ // Cancel all pending animations since we're turning off
+ mScreenBrightnessHandler.removeCallbacksAndMessages(null);
+ screenOffFinishedAnimatingLocked(mScreenOffReason);
+ duration = 200; // TODO: how long should this be?
+ }
+ if (doScreenAnim) {
+ animateInternal(mask, turningOff, 0);
+ }
+ // TODO: Handle keyboard light animation when we have devices that support it
}
}
- if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask);
- setLightBrightness(mask, curIntValue);
- finishAnimationLocked(more, curIntValue);
- return more;
}
- void jumpToTargetLocked() {
- if (mSpew) Slog.d(TAG, "jumpToTargetLocked targetValue=" + targetValue + ": " + mask);
- setLightBrightness(mask, targetValue);
- final int tv = targetValue;
- curValue = tv;
- targetValue = -1;
- finishAnimationLocked(false, tv);
+ public int getCurrentBrightness() {
+ synchronized (this) {
+ return currentValue;
+ }
}
- private void finishAnimationLocked(boolean more, int curIntValue) {
- animating = more;
- if (!more) {
- if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
- screenOffFinishedAnimatingLocked(mScreenOffReason);
- }
+ public boolean isAnimating() {
+ synchronized (this) {
+ return currentValue != endValue;
}
}
- public void run() {
- synchronized (mLocks) {
- // we're turning off
- final boolean turningOff = animating && targetValue == Power.BRIGHTNESS_OFF;
- if (mAnimateScreenLights || !turningOff) {
- long now = SystemClock.uptimeMillis();
- boolean more = mScreenBrightness.stepLocked();
- if (more) {
- mScreenOffHandler.postAtTime(this, now+(1000/60));
- }
- } else {
- if (!mHeadless) {
- // It's pretty scary to hold mLocks for this long, and we should
- // redesign this, but it works for now.
- nativeStartSurfaceFlingerAnimation(
- mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
- ? 0 : mAnimationSetting);
- }
- mScreenBrightness.jumpToTargetLocked();
- }
- }
+ public void cancelAnimation() {
+ animateTo(endValue, currentMask, 0);
}
}
+ private void setLightBrightness(int mask, int value) {
+ mScreenBrightnessAnimator.animateTo(value, mask, 0);
+ }
+
private int getPreferredBrightness() {
if (mScreenBrightnessOverride >= 0) {
return mScreenBrightnessOverride;
@@ -2326,7 +2338,8 @@ public class PowerManagerService extends IPowerManager.Stub
}
private boolean isScreenTurningOffLocked() {
- return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
+ return (mScreenBrightnessAnimator.isAnimating()
+ && mScreenBrightnessAnimator.endValue == Power.BRIGHTNESS_OFF);
}
private boolean shouldLog(long time) {
@@ -2347,7 +2360,7 @@ public class PowerManagerService extends IPowerManager.Stub
private void forceUserActivityLocked() {
if (isScreenTurningOffLocked()) {
// cancel animation so userActivity will succeed
- mScreenBrightness.animating = false;
+ mScreenBrightnessAnimator.cancelAnimation();
}
boolean savedActivityAllowed = mUserActivityAllowed;
mUserActivityAllowed = true;
@@ -2526,6 +2539,8 @@ public class PowerManagerService extends IPowerManager.Stub
}
};
+ private boolean mInitialAnimation; // used to prevent lightsensor changes while turning on
+
private void dockStateChanged(int state) {
synchronized (mLocks) {
mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);
@@ -2587,10 +2602,11 @@ public class PowerManagerService extends IPowerManager.Stub
}
if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
- if (!mSkippedScreenOn) {
- mScreenBrightness.setTargetLocked(lcdValue,
- immediate ? IMMEDIATE_ANIM_STEPS : AUTOBRIGHTNESS_ANIM_STEPS,
- INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
+ if (!mSkippedScreenOn && !mInitialAnimation) {
+ int steps = immediate ? IMMEDIATE_ANIM_STEPS : AUTOBRIGHTNESS_ANIM_STEPS;
+ mScreenBrightnessAnimator.cancelAnimation();
+ mScreenBrightnessAnimator.animateTo(lcdValue,
+ SCREEN_BRIGHT_BIT, steps * NOMINAL_FRAME_TIME_MS);
}
}
if (mButtonBrightnessOverride < 0) {
@@ -2642,7 +2658,7 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (this) {
ShutdownThread.reboot(mContext, finalReason, false);
}
-
+
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
@@ -2996,9 +3012,7 @@ public class PowerManagerService extends IPowerManager.Stub
} finally {
Binder.restoreCallingIdentity(identity);
}
-
- mScreenBrightness.targetValue = brightness;
- mScreenBrightness.jumpToTargetLocked();
+ mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, 0);
}
}
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index a9ff6c5..8429086 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -292,27 +292,27 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
- public void setSystemUiVisibility(int vis) {
+ public void setSystemUiVisibility(int vis, int mask) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
synchronized (mLock) {
- updateUiVisibilityLocked(vis);
+ updateUiVisibilityLocked(vis, mask);
disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken,
"WindowManager.LayoutParams");
}
}
- private void updateUiVisibilityLocked(final int vis) {
+ private void updateUiVisibilityLocked(final int vis, final int mask) {
if (mSystemUiVisibility != vis) {
mSystemUiVisibility = vis;
mHandler.post(new Runnable() {
public void run() {
if (mBar != null) {
try {
- mBar.setSystemUiVisibility(vis);
+ mBar.setSystemUiVisibility(vis, mask);
} catch (RemoteException ex) {
}
}
@@ -352,6 +352,24 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
+ @Override
+ public void preloadRecentApps() {
+ if (mBar != null) {
+ try {
+ mBar.preloadRecentApps();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void cancelPreloadRecentApps() {
+ if (mBar != null) {
+ try {
+ mBar.cancelPreloadRecentApps();
+ } catch (RemoteException ex) {}
+ }
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c9b5997..7dd736d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -47,6 +47,7 @@ import android.view.WindowManager;
import com.android.internal.app.ShutdownThread;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.widget.LockSettingsService;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.net.NetworkPolicyManagerService;
@@ -120,6 +121,7 @@ class ServerThread extends Thread {
ConnectivityService connectivity = null;
WifiP2pService wifiP2p = null;
WifiService wifi = null;
+ NsdService serviceDiscovery= null;
IPackageManager pm = null;
Context context = null;
WindowManagerService wm = null;
@@ -219,6 +221,7 @@ class ServerThread extends Thread {
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
+ ServiceManager.addService(Context.INPUT_SERVICE, wm.getInputManagerService());
ActivityManagerService.self().setWindowManager(wm);
@@ -265,6 +268,7 @@ class ServerThread extends Thread {
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
TextServicesManagerService tsms = null;
+ LockSettingsService lockSettings = null;
// Bring up services needed for UI.
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
@@ -307,6 +311,14 @@ class ServerThread extends Thread {
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
+ Slog.i(TAG, "LockSettingsService");
+ lockSettings = new LockSettingsService(context);
+ ServiceManager.addService("lock_settings", lockSettings);
+ } catch (Throwable e) {
+ reportWtf("starting LockSettingsService service", e);
+ }
+
+ try {
Slog.i(TAG, "Device Policy");
devicePolicy = new DevicePolicyManagerService(context);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
@@ -394,6 +406,15 @@ class ServerThread extends Thread {
}
try {
+ Slog.i(TAG, "Network Service Discovery Service");
+ serviceDiscovery = NsdService.create(context);
+ ServiceManager.addService(
+ Context.NSD_SERVICE, serviceDiscovery);
+ } catch (Throwable e) {
+ reportWtf("starting Service Discovery Service", e);
+ }
+
+ try {
Slog.i(TAG, "Throttle Service");
throttle = new ThrottleService(context);
ServiceManager.addService(
@@ -402,6 +423,14 @@ class ServerThread extends Thread {
reportWtf("starting ThrottleService", e);
}
+ try {
+ Slog.i(TAG, "UpdateLock Service");
+ ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
+ new UpdateLockService(context));
+ } catch (Throwable e) {
+ reportWtf("starting UpdateLockService", e);
+ }
+
if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
try {
/*
@@ -643,6 +672,11 @@ class ServerThread extends Thread {
} catch (Throwable e) {
reportWtf("making Package Manager Service ready", e);
}
+ try {
+ lockSettings.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Lock Settings Service ready", e);
+ }
// These are needed to propagate to the runnable below.
final Context contextF = context;
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 8c8e725..1b1638a 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -29,6 +29,7 @@ import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.CellInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -107,6 +108,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
+ private CellInfo mCellInfo = null;
+
static final int PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
PhoneStateListener.LISTEN_CALL_STATE |
@@ -236,6 +239,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+ try {
+ r.callback.onCellInfoChanged(new CellInfo(mCellInfo));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -325,6 +335,26 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
broadcastSignalStrengthChanged(signalStrength);
}
+ public void notifyCellInfo(CellInfo cellInfo) {
+ if (!checkNotifyPermission("notifyCellInfo()")) {
+ return;
+ }
+
+ synchronized (mRecords) {
+ mCellInfo = cellInfo;
+ for (Record r : mRecords) {
+ if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+ try {
+ r.callback.onCellInfoChanged(new CellInfo(cellInfo));
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
public void notifyMessageWaitingChanged(boolean mwi) {
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
return;
@@ -530,6 +560,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
pw.println(" mCellLocation=" + mCellLocation);
+ pw.println(" mCellInfo=" + mCellInfo);
pw.println("registrations: count=" + recordCount);
for (Record r : mRecords) {
pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
@@ -655,6 +686,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
+ if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
+
+ }
+
if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PHONE_STATE, null);
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index c5c2901..84daead 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -189,8 +189,8 @@ class UiModeManagerService extends IUiModeManager.Stub {
}
try {
ActivityManagerNative.getDefault().startActivityWithConfig(
- null, homeIntent, null, null, 0, null, null, 0, false, false,
- newConfig);
+ null, homeIntent, null, null, null, 0, 0,
+ newConfig, null);
mHoldingConfiguration = false;
} catch (RemoteException e) {
Slog.w(TAG, e.getCause());
diff --git a/services/java/com/android/server/UpdateLockService.java b/services/java/com/android/server/UpdateLockService.java
new file mode 100644
index 0000000..1ffd196
--- /dev/null
+++ b/services/java/com/android/server/UpdateLockService.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IUpdateLock;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.TokenWatcher;
+import android.os.UpdateLock;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class UpdateLockService extends IUpdateLock.Stub {
+ static final boolean DEBUG = false;
+ static final String TAG = "UpdateLockService";
+
+ // signatureOrSystem required to use update locks
+ static final String PERMISSION = "android.permission.UPDATE_LOCK";
+
+ Context mContext;
+ LockWatcher mLocks;
+
+ class LockWatcher extends TokenWatcher {
+ LockWatcher(Handler h, String tag) {
+ super(h, tag);
+ }
+
+ public void acquired() {
+ if (DEBUG) {
+ Slog.d(TAG, "first acquire; broadcasting convenient=false");
+ }
+ sendLockChangedBroadcast(false);
+ }
+ public void released() {
+ if (DEBUG) {
+ Slog.d(TAG, "last release; broadcasting convenient=true");
+ }
+ sendLockChangedBroadcast(true);
+ }
+ }
+
+ UpdateLockService(Context context) {
+ mContext = context;
+ mLocks = new LockWatcher(new Handler(), "UpdateLocks");
+
+ // Consider just-booting to be a reasonable time to allow
+ // interruptions for update installation etc.
+ sendLockChangedBroadcast(true);
+ }
+
+ void sendLockChangedBroadcast(boolean state) {
+ // Safe early during boot because this broadcast only goes to registered receivers.
+ long oldIdent = Binder.clearCallingIdentity();
+ try {
+ Intent intent = new Intent(UpdateLock.UPDATE_LOCK_CHANGED)
+ .putExtra(UpdateLock.NOW_IS_CONVENIENT, state)
+ .putExtra(UpdateLock.TIMESTAMP, System.currentTimeMillis())
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendStickyBroadcast(intent);
+ } finally {
+ Binder.restoreCallingIdentity(oldIdent);
+ }
+ }
+
+ @Override
+ public void acquireUpdateLock(IBinder token, String tag) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "acquire(" + token + ") by " + makeTag(tag));
+ }
+
+ mContext.enforceCallingOrSelfPermission(PERMISSION, "acquireUpdateLock");
+ mLocks.acquire(token, makeTag(tag));
+ }
+
+ @Override
+ public void releaseUpdateLock(IBinder token) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "release(" + token + ')');
+ }
+
+ mContext.enforceCallingOrSelfPermission(PERMISSION, "releaseUpdateLock");
+ mLocks.release(token);
+ };
+
+ private String makeTag(String tag) {
+ return "{tag=" + tag
+ + " uid=" + Binder.getCallingUid()
+ + " pid=" + Binder.getCallingPid() + '}';
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump update lock service from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ mLocks.dump(pw);
+ }
+}
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/WifiService.java b/services/java/com/android/server/WifiService.java
index 5208785..e2a2c83 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -101,9 +101,6 @@ public class WifiService extends IWifiManager.Stub {
private boolean mEmergencyCallbackMode = false;
private int mPluggedType;
- /* Chipset supports background scan */
- private final boolean mBackgroundScanSupported;
-
private final LockList mLocks = new LockList();
// some wifi lock statistics
private int mFullHighPerfLocksAcquired;
@@ -263,47 +260,46 @@ public class WifiService extends IWifiManager.Stub {
ac.connect(mContext, this, msg.replyTo);
break;
}
- case WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL: {
+ case WifiManager.ENABLE_TRAFFIC_STATS_POLL: {
mEnableTrafficStatsPoll = (msg.arg1 == 1);
mTrafficStatsPollToken++;
if (mEnableTrafficStatsPoll) {
notifyOnDataActivity();
- sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL,
+ sendMessageDelayed(Message.obtain(this, WifiManager.TRAFFIC_STATS_POLL,
mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
}
break;
}
- case WifiManager.CMD_TRAFFIC_STATS_POLL: {
+ case WifiManager.TRAFFIC_STATS_POLL: {
if (msg.arg1 == mTrafficStatsPollToken) {
notifyOnDataActivity();
- sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL,
+ sendMessageDelayed(Message.obtain(this, WifiManager.TRAFFIC_STATS_POLL,
mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
}
break;
}
- case WifiManager.CMD_CONNECT_NETWORK: {
- if (msg.obj != null) {
- mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj);
- } else {
- mWifiStateMachine.connectNetwork(msg.arg1);
- }
+ case WifiManager.CONNECT_NETWORK: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
break;
}
- case WifiManager.CMD_SAVE_NETWORK: {
- mWifiStateMachine.saveNetwork((WifiConfiguration)msg.obj);
+ case WifiManager.SAVE_NETWORK: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
break;
}
- case WifiManager.CMD_FORGET_NETWORK: {
- mWifiStateMachine.forgetNetwork(msg.arg1);
+ case WifiManager.FORGET_NETWORK: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
break;
}
- case WifiManager.CMD_START_WPS: {
- //replyTo has the original source
- mWifiStateMachine.startWps(msg.replyTo, (WpsInfo)msg.obj);
+ case WifiManager.START_WPS: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
break;
}
- case WifiManager.CMD_DISABLE_NETWORK: {
- mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2);
+ case WifiManager.CANCEL_WPS: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
+ break;
+ }
+ case WifiManager.DISABLE_NETWORK: {
+ mWifiStateMachine.sendMessage(Message.obtain(msg));
break;
}
default: {
@@ -436,9 +432,6 @@ public class WifiService extends IWifiManager.Stub {
Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
mNotificationEnabledSettingObserver.register();
-
- mBackgroundScanSupported = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_wifi_background_scan_support);
}
/**
@@ -914,7 +907,7 @@ public class WifiService extends IWifiManager.Stub {
* Get a reference to handler. This is used by a client to establish
* an AsyncChannel communication with WifiService
*/
- public Messenger getMessenger() {
+ public Messenger getWifiServiceMessenger() {
/* Enforce the highest permissions
TODO: when we consider exposing the asynchronous API, think about
how to provide both access and change permissions seperately
@@ -924,6 +917,13 @@ public class WifiService extends IWifiManager.Stub {
return new Messenger(mAsyncServiceHandler);
}
+ /** Get a reference to WifiStateMachine handler for AsyncChannel communication */
+ public Messenger getWifiStateMachineMessenger() {
+ enforceAccessPermission();
+ enforceChangePermission();
+ return mWifiStateMachine.getMessenger();
+ }
+
/**
* Get the IP and proxy configuration file
*/
@@ -950,11 +950,6 @@ public class WifiService extends IWifiManager.Stub {
mAlarmManager.cancel(mIdleIntent);
mScreenOff = false;
evaluateTrafficStatsPolling();
- mWifiStateMachine.enableRssiPolling(true);
- if (mBackgroundScanSupported) {
- mWifiStateMachine.enableBackgroundScanCommand(false);
- }
- mWifiStateMachine.enableAllNetworks();
setDeviceIdleAndUpdateWifi(false);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
if (DBG) {
@@ -962,10 +957,6 @@ public class WifiService extends IWifiManager.Stub {
}
mScreenOff = true;
evaluateTrafficStatsPolling();
- mWifiStateMachine.enableRssiPolling(false);
- if (mBackgroundScanSupported) {
- mWifiStateMachine.enableBackgroundScanCommand(true);
- }
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND the "stay on while plugged in" setting doesn't match the
@@ -1587,10 +1578,10 @@ public class WifiService extends IWifiManager.Stub {
Message msg;
if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED && !mScreenOff) {
msg = Message.obtain(mAsyncServiceHandler,
- WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL, 1, 0);
+ WifiManager.ENABLE_TRAFFIC_STATS_POLL, 1, 0);
} else {
msg = Message.obtain(mAsyncServiceHandler,
- WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL, 0, 0);
+ WifiManager.ENABLE_TRAFFIC_STATS_POLL, 0, 0);
}
msg.sendToTarget();
}
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/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 769cb6a..31aa21e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -16,7 +16,7 @@
package com.android.server.accessibility;
-import com.android.server.wm.InputFilter;
+import com.android.server.input.InputFilter;
import android.content.Context;
import android.util.Slog;
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 41cf9a6..d07aa7a 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -29,7 +29,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
-import com.android.server.wm.InputFilter;
+import com.android.server.input.InputFilter;
import java.util.Arrays;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3ac446c..80e59cd 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import com.android.internal.R;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessStats;
@@ -32,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;
@@ -49,19 +52,20 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
-import android.app.WallpaperManager;
import android.app.backup.IBackupManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
+import android.content.ClipData;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -71,12 +75,12 @@ import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -107,11 +111,12 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserId;
import android.provider.Settings;
+import android.text.format.Time;
import android.util.EventLog;
-import android.util.Pair;
-import android.util.Slog;
import android.util.Log;
+import android.util.Pair;
import android.util.PrintWriterPrinter;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
@@ -135,7 +140,6 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
@@ -147,6 +151,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;
@@ -194,6 +199,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
+ static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
+
// Maximum number of recent tasks that we can remember.
static final int MAX_RECENT_TASKS = 20;
@@ -283,9 +290,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static class PendingActivityLaunch {
ActivityRecord r;
ActivityRecord sourceRecord;
- Uri[] grantedUriPermissions;
- int grantedMode;
- boolean onlyIfNeeded;
+ int startFlags;
}
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
@@ -746,6 +751,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ParcelFileDescriptor mProfileFd;
int mProfileType = 0;
boolean mAutoStopProfiler = false;
+ String mOpenGlTraceApp = null;
final RemoteCallbackList<IProcessObserver> mProcessObservers
= new RemoteCallbackList<IProcessObserver>();
@@ -897,10 +903,15 @@ public final class ActivityManagerService extends ActivityManagerNative
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
- Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
- mContext, proc, (ActivityRecord)data.get("activity"));
- d.show();
- proc.anrDialog = d;
+ if (mShowDialogs) {
+ Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
+ mContext, proc, (ActivityRecord)data.get("activity"));
+ d.show();
+ proc.anrDialog = d;
+ } else {
+ // Just kill the app if there is no dialog to be shown.
+ killAppAtUsersRequest(proc, null);
+ }
}
ensureBootCompleted();
@@ -1074,7 +1085,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: {
@@ -1284,7 +1296,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) {
@@ -1786,7 +1798,8 @@ public final class ActivityManagerService extends ActivityManagerNative
final ProcessRecord getProcessRecordLocked(
String processName, int uid) {
- if (uid == Process.SYSTEM_UID) {
+ // Temporary hack to make Settings run per user
+ if (uid == Process.SYSTEM_UID && !processName.equals("com.android.settings")) {
// The system gets to run in any process. If there are multiple
// processes with the same uid, just pick the first (this
// should never happen).
@@ -2091,8 +2104,8 @@ public final class ActivityManagerService extends ActivityManagerNative
aInfo.applicationInfo.uid);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
- mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
- null, null, 0, 0, 0, false, false, null);
+ mMainStack.startActivityLocked(null, intent, null, aInfo,
+ null, null, 0, 0, 0, 0, null, false, null);
}
}
@@ -2146,8 +2159,8 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name));
- mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
- null, null, 0, 0, 0, false, false, null);
+ mMainStack.startActivityLocked(null, intent, null, ri.activityInfo,
+ null, null, 0, 0, 0, 0, null, false, null);
}
}
}
@@ -2253,17 +2266,15 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<N; i++) {
PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
- pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
- doResume && i == (N-1));
+ pal.startFlags, doResume && i == (N-1), null);
}
mPendingActivityLaunches.clear();
}
public final int startActivity(IApplicationThread caller,
- Intent intent, String resolvedType, Uri[] grantedUriPermissions,
- int grantedMode, IBinder resultTo,
- String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
- String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+ Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags,
+ String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
enforceNotIsolatedCaller("startActivity");
int userId = 0;
if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
@@ -2280,42 +2291,38 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
- grantedUriPermissions, grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded,
- debug, profileFile, profileFd, autoStopProfiler, null, null, userId);
+ resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
+ null, null, options, userId);
}
public final WaitResult startActivityAndWait(IApplicationThread caller,
- Intent intent, String resolvedType, Uri[] grantedUriPermissions,
- int grantedMode, IBinder resultTo,
- String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
- String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+ Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags, String profileFile,
+ ParcelFileDescriptor profileFd, Bundle options) {
enforceNotIsolatedCaller("startActivityAndWait");
WaitResult res = new WaitResult();
int userId = Binder.getOrigCallingUser();
mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
- grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
- res, null, userId);
+ resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
+ res, null, options, userId);
return res;
}
-
+
public final int startActivityWithConfig(IApplicationThread caller,
- Intent intent, String resolvedType, Uri[] grantedUriPermissions,
- int grantedMode, IBinder resultTo,
- String resultWho, int requestCode, boolean onlyIfNeeded,
- boolean debug, Configuration config) {
+ Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags, Configuration config,
+ Bundle options) {
enforceNotIsolatedCaller("startActivityWithConfig");
int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
- grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded,
- debug, null, null, false, null, config, Binder.getOrigCallingUser());
+ resultTo, resultWho, requestCode, startFlags,
+ null, null, null, config, options, Binder.getOrigCallingUser());
return ret;
}
public int startActivityIntentSender(IApplicationThread caller,
IntentSender intent, Intent fillInIntent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode,
- int flagsMask, int flagsValues) {
+ int flagsMask, int flagsValues, Bundle options) {
enforceNotIsolatedCaller("startActivityIntentSender");
// Refuse possible leaked file descriptors
if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
@@ -2338,13 +2345,13 @@ public final class ActivityManagerService extends ActivityManagerNative
mAppSwitchesAllowedTime = 0;
}
}
- int ret = pir.sendInner(0, fillInIntent, resolvedType, null,
- null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
+ int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null,
+ resultTo, resultWho, requestCode, flagsMask, flagsValues, options);
return ret;
}
public boolean startNextMatchingActivity(IBinder callingActivity,
- Intent intent) {
+ Intent intent, Bundle options) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -2353,10 +2360,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);
@@ -2370,7 +2379,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;
@@ -2392,6 +2402,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (aInfo == null) {
// Nobody who is next!
+ ActivityOptions.abort(options);
return false;
}
@@ -2421,16 +2432,14 @@ 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, null, 0, aInfo,
- resultTo != null ? resultTo.appToken : null, resultWho,
- requestCode, -1, r.launchedFromUid, false, false, null);
+ r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
+ resultWho, requestCode, -1, r.launchedFromUid, 0,
+ options, false, null);
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
- if (res != START_SUCCESS) {
+ if (res != ActivityManager.START_SUCCESS) {
return false;
}
return true;
@@ -2439,7 +2448,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public final int startActivityInPackage(int uid,
Intent intent, String resolvedType, IBinder resultTo,
- String resultWho, int requestCode, boolean onlyIfNeeded) {
+ String resultWho, int requestCode, int startFlags, Bundle options) {
// This is so super not safe, that only the system (or okay root)
// can do it.
@@ -2451,21 +2460,22 @@ public final class ActivityManagerService extends ActivityManagerNative
}
int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
- null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
- null, null, false, null, null, userId);
+ resultTo, resultWho, requestCode, startFlags,
+ null, null, null, null, options, userId);
return ret;
}
public final int startActivities(IApplicationThread caller,
- Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
+ Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options) {
enforceNotIsolatedCaller("startActivities");
int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
- Binder.getOrigCallingUser());
+ options, Binder.getOrigCallingUser());
return ret;
}
public final int startActivitiesInPackage(int uid,
- Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
+ Intent[] intents, String[] resolvedTypes, IBinder resultTo,
+ Bundle options) {
// This is so super not safe, that only the system (or okay root)
// can do it.
@@ -2475,7 +2485,7 @@ public final class ActivityManagerService extends ActivityManagerNative
"startActivityInPackage only available to the system");
}
int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
- UserId.getUserId(uid));
+ options, UserId.getUserId(uid));
return ret;
}
@@ -2965,6 +2975,12 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
+ dumpStackTraces(tracesPath, firstPids, processStats, lastPids);
+ return tracesFile;
+ }
+
+ private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
+ ProcessStats processStats, SparseArray<Boolean> lastPids) {
// Use a FileObserver to detect when traces finish writing.
// The order of traces is considered important to maintain for legibility.
FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
@@ -2975,16 +2991,18 @@ public final class ActivityManagerService extends ActivityManagerNative
observer.startWatching();
// First collect all of the stacks of the most important pids.
- try {
- int num = firstPids.size();
- for (int i = 0; i < num; i++) {
- synchronized (observer) {
- Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+ if (firstPids != null) {
+ try {
+ int num = firstPids.size();
+ for (int i = 0; i < num; i++) {
+ synchronized (observer) {
+ Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
+ observer.wait(200); // Wait for write-close, give up after 200msec
+ }
}
+ } catch (InterruptedException e) {
+ Log.wtf(TAG, e);
}
- } catch (InterruptedException e) {
- Log.wtf(TAG, e);
}
// Next measure CPU usage.
@@ -3020,13 +3038,83 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- return tracesFile;
-
} finally {
observer.stopWatching();
}
}
+ final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
+ if (true || IS_USER_BUILD) {
+ return;
+ }
+ String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+ if (tracesPath == null || tracesPath.length() == 0) {
+ return;
+ }
+
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ StrictMode.allowThreadDiskWrites();
+ try {
+ final File tracesFile = new File(tracesPath);
+ final File tracesDir = tracesFile.getParentFile();
+ final File tracesTmp = new File(tracesDir, "__tmp__");
+ try {
+ if (!tracesDir.exists()) tracesFile.mkdirs();
+ FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
+
+ if (tracesFile.exists()) {
+ tracesTmp.delete();
+ tracesFile.renameTo(tracesTmp);
+ }
+ StringBuilder sb = new StringBuilder();
+ Time tobj = new Time();
+ tobj.set(System.currentTimeMillis());
+ sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
+ sb.append(": ");
+ TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
+ sb.append(" since ");
+ sb.append(msg);
+ FileOutputStream fos = new FileOutputStream(tracesFile);
+ fos.write(sb.toString().getBytes());
+ if (app == null) {
+ fos.write("\n*** No application process!".getBytes());
+ }
+ fos.close();
+ FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesPath, e);
+ return;
+ }
+
+ if (app != null) {
+ ArrayList<Integer> firstPids = new ArrayList<Integer>();
+ firstPids.add(app.pid);
+ dumpStackTraces(tracesPath, firstPids, null, null);
+ }
+
+ File lastTracesFile = null;
+ File curTracesFile = null;
+ for (int i=9; i>=0; i--) {
+ String name = String.format("slow%02d.txt", i);
+ curTracesFile = new File(tracesDir, name);
+ if (curTracesFile.exists()) {
+ if (lastTracesFile != null) {
+ curTracesFile.renameTo(lastTracesFile);
+ } else {
+ curTracesFile.delete();
+ }
+ }
+ lastTracesFile = curTracesFile;
+ }
+ tracesFile.renameTo(curTracesFile);
+ if (tracesTmp.exists()) {
+ tracesTmp.renameTo(tracesFile);
+ }
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, final String annotation) {
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
@@ -3213,7 +3301,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) {
@@ -3234,7 +3322,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);
@@ -3261,13 +3349,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) {
@@ -3334,16 +3423,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) {
@@ -3352,7 +3439,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 "
@@ -3467,7 +3554,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) {
@@ -3501,9 +3588,12 @@ 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))) {
if (app.setAdj >= minOomAdj) {
if (!doit) {
return true;
@@ -3524,13 +3614,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) {
}
}
@@ -3554,7 +3644,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) {
@@ -3574,14 +3665,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)) {
@@ -3605,7 +3695,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) {
@@ -3833,6 +3923,11 @@ public final class ActivityManagerService extends ActivityManagerNative
profileFd = mProfileFd;
profileAutoStop = mAutoStopProfiler;
}
+ boolean enableOpenGlTrace = false;
+ if (mOpenGlTraceApp != null && mOpenGlTraceApp.equals(processName)) {
+ enableOpenGlTrace = true;
+ mOpenGlTraceApp = null;
+ }
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
@@ -3858,8 +3953,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
- app.instrumentationArguments, app.instrumentationWatcher, testMode,
- isRestrictedBackupMode || !normalMode, app.persistent,
+ app.instrumentationArguments, app.instrumentationWatcher, testMode,
+ enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, true);
@@ -4024,16 +4119,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.
@@ -4169,7 +4273,8 @@ public final class ActivityManagerService extends ActivityManagerNative
public IIntentSender getIntentSender(int type,
String packageName, IBinder token, String resultWho,
- int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
+ int requestCode, Intent[] intents, String[] resolvedTypes,
+ int flags, Bundle options) {
enforceNotIsolatedCaller("getIntentSender");
// Refuse possible leaked file descriptors
if (intents != null) {
@@ -4182,7 +4287,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- if (type == INTENT_SENDER_BROADCAST &&
+ if (type == ActivityManager.INTENT_SENDER_BROADCAST &&
(intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
throw new IllegalArgumentException(
"Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
@@ -4195,14 +4300,19 @@ public final class ActivityManagerService extends ActivityManagerNative
"Intent array length does not match resolvedTypes length");
}
}
+ if (options != null) {
+ if (options.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in options");
+ }
+ }
synchronized(this) {
int callingUid = Binder.getCallingUid();
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()
@@ -4217,7 +4327,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.i(TAG_MU, "Getting intent sender for origCallingUid="
+ Binder.getOrigCallingUid());
return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(),
- token, resultWho, requestCode, intents, resolvedTypes, flags);
+ token, resultWho, requestCode, intents, resolvedTypes, flags, options);
} catch (RemoteException e) {
throw new SecurityException(e);
@@ -4227,11 +4337,12 @@ public final class ActivityManagerService extends ActivityManagerNative
IIntentSender getIntentSenderLocked(int type,
String packageName, int callingUid, IBinder token, String resultWho,
- int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
+ int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
+ Bundle options) {
if (DEBUG_MU)
Slog.v(TAG_MU, "getIntentSenderLocked(): uid=" + callingUid);
ActivityRecord activity = null;
- if (type == INTENT_SENDER_ACTIVITY_RESULT) {
+ if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
activity = mMainStack.isInStackLocked(token);
if (activity == null) {
return null;
@@ -4249,7 +4360,7 @@ public final class ActivityManagerService extends ActivityManagerNative
PendingIntentRecord.Key key = new PendingIntentRecord.Key(
type, packageName, activity, resultWho,
- requestCode, intents, resolvedTypes, flags);
+ requestCode, intents, resolvedTypes, flags, options);
WeakReference<PendingIntentRecord> ref;
ref = mIntentSenderRecords.get(key);
PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -4278,7 +4389,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
rec = new PendingIntentRecord(this, key, callingUid);
mIntentSenderRecords.put(key, rec.ref);
- if (type == INTENT_SENDER_ACTIVITY_RESULT) {
+ if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
if (activity.pendingResults == null) {
activity.pendingResults
= new HashSet<WeakReference<PendingIntentRecord>>();
@@ -4296,8 +4407,8 @@ public final class ActivityManagerService extends ActivityManagerNative
PendingIntentRecord rec = (PendingIntentRecord)sender;
try {
int uid = AppGlobals.getPackageManager()
- .getPackageUid(rec.key.packageName);
- if (uid != Binder.getCallingUid()) {
+ .getPackageUid(rec.key.packageName, UserId.getCallingUserId());
+ if (!UserId.isSameApp(uid, Binder.getCallingUid())) {
String msg = "Permission Denial: cancelIntentSender() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
@@ -4333,6 +4444,17 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
+ public int getUidForIntentSender(IIntentSender sender) {
+ if (sender instanceof PendingIntentRecord) {
+ try {
+ PendingIntentRecord res = (PendingIntentRecord)sender;
+ return res.uid;
+ } catch (ClassCastException e) {
+ }
+ }
+ return -1;
+ }
+
public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return false;
@@ -4543,76 +4665,91 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
- ProviderInfo pi, Uri uri, int uid, int modeFlags) {
- boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
- boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
+ /**
+ * Determine if UID is holding permissions required to access {@link Uri} in
+ * the given {@link ProviderInfo}. Final permission checking is always done
+ * in {@link ContentProvider}.
+ */
+ private final boolean checkHoldingPermissionsLocked(
+ IPackageManager pm, ProviderInfo pi, Uri uri, int uid, int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
- try {
- // Is the component private from the target uid?
- final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
- // Acceptable if the there is no read permission needed from the
- // target or the target is holding the read permission.
- if (!readPerm) {
- if ((!prv && pi.readPermission == null) ||
- (pm.checkUidPermission(pi.readPermission, uid)
- == PackageManager.PERMISSION_GRANTED)) {
- readPerm = true;
- }
- }
+ if (pi.applicationInfo.uid == uid) {
+ return true;
+ } else if (!pi.exported) {
+ return false;
+ }
- // Acceptable if the there is no write permission needed from the
- // target or the target is holding the read permission.
- if (!writePerm) {
- if (!prv && (pi.writePermission == null) ||
- (pm.checkUidPermission(pi.writePermission, uid)
- == PackageManager.PERMISSION_GRANTED)) {
- writePerm = true;
- }
+ boolean readMet = (modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
+ boolean writeMet = (modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
+ try {
+ // check if target holds top-level <provider> permissions
+ if (!readMet && pi.readPermission != null
+ && (pm.checkUidPermission(pi.readPermission, uid) == PERMISSION_GRANTED)) {
+ readMet = true;
}
+ if (!writeMet && pi.writePermission != null
+ && (pm.checkUidPermission(pi.writePermission, uid) == PERMISSION_GRANTED)) {
+ writeMet = true;
+ }
+
+ // track if unprotected read/write is allowed; any denied
+ // <path-permission> below removes this ability
+ boolean allowDefaultRead = pi.readPermission == null;
+ boolean allowDefaultWrite = pi.writePermission == null;
- // Acceptable if there is a path permission matching the URI that
- // the target holds the permission on.
- PathPermission[] pps = pi.pathPermissions;
- if (pps != null && (!readPerm || !writePerm)) {
+ // check if target holds any <path-permission> that match uri
+ final PathPermission[] pps = pi.pathPermissions;
+ if (pps != null) {
final String path = uri.getPath();
int i = pps.length;
- while (i > 0 && (!readPerm || !writePerm)) {
+ while (i > 0 && (!readMet || !writeMet)) {
i--;
PathPermission pp = pps[i];
- if (!readPerm) {
- final String pprperm = pp.getReadPermission();
- if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
- + pprperm + " for " + pp.getPath()
- + ": match=" + pp.match(path)
- + " check=" + pm.checkUidPermission(pprperm, uid));
- if (pprperm != null && pp.match(path) &&
- (pm.checkUidPermission(pprperm, uid)
- == PackageManager.PERMISSION_GRANTED)) {
- readPerm = true;
+ if (pp.match(path)) {
+ if (!readMet) {
+ final String pprperm = pp.getReadPermission();
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
+ + pprperm + " for " + pp.getPath()
+ + ": match=" + pp.match(path)
+ + " check=" + pm.checkUidPermission(pprperm, uid));
+ if (pprperm != null) {
+ if (pm.checkUidPermission(pprperm, uid) == PERMISSION_GRANTED) {
+ readMet = true;
+ } else {
+ allowDefaultRead = false;
+ }
+ }
}
- }
- if (!writePerm) {
- final String ppwperm = pp.getWritePermission();
- if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
- + ppwperm + " for " + pp.getPath()
- + ": match=" + pp.match(path)
- + " check=" + pm.checkUidPermission(ppwperm, uid));
- if (ppwperm != null && pp.match(path) &&
- (pm.checkUidPermission(ppwperm, uid)
- == PackageManager.PERMISSION_GRANTED)) {
- writePerm = true;
+ if (!writeMet) {
+ final String ppwperm = pp.getWritePermission();
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
+ + ppwperm + " for " + pp.getPath()
+ + ": match=" + pp.match(path)
+ + " check=" + pm.checkUidPermission(ppwperm, uid));
+ if (ppwperm != null) {
+ if (pm.checkUidPermission(ppwperm, uid) == PERMISSION_GRANTED) {
+ writeMet = true;
+ } else {
+ allowDefaultWrite = false;
+ }
+ }
}
}
}
}
+
+ // grant unprotected <provider> read/write, if not blocked by
+ // <path-permission> above
+ if (allowDefaultRead) readMet = true;
+ if (allowDefaultWrite) writeMet = true;
+
} catch (RemoteException e) {
return false;
}
- return readPerm && writePerm;
+ return readMet && writeMet;
}
private final boolean checkUriPermissionLocked(Uri uri, int uid,
@@ -4657,9 +4794,11 @@ public final class ActivityManagerService extends ActivityManagerNative
* if callingUid is not allowed to do this. Returns the uid of the target
* if the URI permission grant should be performed; returns -1 if it is not
* needed (for example targetPkg already has permission to access the URI).
+ * If you already know the uid of the target, you can supply it in
+ * lastTargetUid else set that to -1.
*/
int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, int modeFlags, int lastTargetUid) {
modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (modeFlags == 0) {
@@ -4689,7 +4828,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) {
}
}
@@ -4698,10 +4837,10 @@ public final class ActivityManagerService extends ActivityManagerNative
return -1;
}
- int targetUid;
- if (targetPkg != null) {
+ 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);
@@ -4710,8 +4849,6 @@ public final class ActivityManagerService extends ActivityManagerNative
} catch (RemoteException ex) {
return -1;
}
- } else {
- targetUid = -1;
}
if (targetUid >= 0) {
@@ -4783,7 +4920,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Uri uri, int modeFlags) {
enforceNotIsolatedCaller("checkGrantUriPermission");
synchronized(this) {
- return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
+ return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
}
}
@@ -4830,13 +4967,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- void grantUriPermissionLocked(int callingUid,
- String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
+ void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, UriPermissionOwner owner) {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
}
- int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
+ int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
if (targetUid < 0) {
return;
}
@@ -4844,13 +4981,26 @@ public final class ActivityManagerService extends ActivityManagerNative
grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
}
+ static class NeededUriGrants extends ArrayList<Uri> {
+ final String targetPkg;
+ final int targetUid;
+ final int flags;
+
+ NeededUriGrants(String _targetPkg, int _targetUid, int _flags) {
+ targetPkg = _targetPkg;
+ targetUid = _targetUid;
+ flags = _flags;
+ }
+ }
+
/**
* Like checkGrantUriPermissionLocked, but takes an Intent.
*/
- int checkGrantUriPermissionFromIntentLocked(int callingUid,
- String targetPkg, Intent intent) {
+ NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid,
+ String targetPkg, Intent intent, int mode, NeededUriGrants needed) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Checking URI perm to " + (intent != null ? intent.getData() : null)
+ "Checking URI perm to data=" + (intent != null ? intent.getData() : null)
+ + " clip=" + (intent != null ? intent.getClipData() : null)
+ " from " + intent + "; flags=0x"
+ Integer.toHexString(intent != null ? intent.getFlags() : 0));
@@ -4859,33 +5009,74 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (intent == null) {
- return -1;
+ return null;
}
Uri data = intent.getData();
- if (data == null) {
- return -1;
+ ClipData clip = intent.getClipData();
+ if (data == null && clip == null) {
+ return null;
+ }
+ if (data != null) {
+ int target = checkGrantUriPermissionLocked(callingUid, targetPkg, data,
+ mode, needed != null ? needed.targetUid : -1);
+ if (target > 0) {
+ if (needed == null) {
+ needed = new NeededUriGrants(targetPkg, target, mode);
+ }
+ needed.add(data);
+ }
+ }
+ if (clip != null) {
+ for (int i=0; i<clip.getItemCount(); i++) {
+ Uri uri = clip.getItemAt(i).getUri();
+ if (uri != null) {
+ int target = -1;
+ target = checkGrantUriPermissionLocked(callingUid, targetPkg, uri,
+ mode, needed != null ? needed.targetUid : -1);
+ if (target > 0) {
+ if (needed == null) {
+ needed = new NeededUriGrants(targetPkg, target, mode);
+ }
+ needed.add(uri);
+ }
+ } else {
+ Intent clipIntent = clip.getItemAt(i).getIntent();
+ if (clipIntent != null) {
+ NeededUriGrants newNeeded = checkGrantUriPermissionFromIntentLocked(
+ callingUid, targetPkg, clipIntent, mode, needed);
+ if (newNeeded != null) {
+ needed = newNeeded;
+ }
+ }
+ }
+ }
}
- return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
- intent.getFlags());
+
+ return needed;
}
/**
* Like grantUriPermissionUncheckedLocked, but takes an Intent.
*/
- void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
- String targetPkg, Intent intent, UriPermissionOwner owner) {
- grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
- intent.getFlags(), owner);
+ void grantUriPermissionUncheckedFromIntentLocked(NeededUriGrants needed,
+ UriPermissionOwner owner) {
+ if (needed != null) {
+ for (int i=0; i<needed.size(); i++) {
+ grantUriPermissionUncheckedLocked(needed.targetUid, needed.targetPkg,
+ needed.get(i), needed.flags, owner);
+ }
+ }
}
void grantUriPermissionFromIntentLocked(int callingUid,
String targetPkg, Intent intent, UriPermissionOwner owner) {
- int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
- if (targetUid < 0) {
+ NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg,
+ intent, intent != null ? intent.getFlags() : 0, null);
+ if (needed == null) {
return;
}
- grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
+ grantUriPermissionUncheckedFromIntentLocked(needed, owner);
}
public void grantUriPermission(IApplicationThread caller, String targetPkg,
@@ -4941,14 +5132,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) {
}
}
@@ -5043,7 +5234,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) {
}
}
@@ -5321,12 +5512,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;
}
}
@@ -5372,15 +5564,16 @@ public final class ActivityManagerService extends ActivityManagerNative
"removeSubTask()");
long ident = Binder.clearCallingIdentity();
try {
- return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
+ return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex,
+ true) != null;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
- private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
- TaskRecord tr = root.task;
+ private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
+ final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;
Intent baseIntent = new Intent(
tr.intent != null ? tr.intent : tr.affinityIntent);
ComponentName component = baseIntent.getComponent();
@@ -5391,7 +5584,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Find any running services associated with this app.
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
- for (ServiceRecord sr : mServiceMap.getAllServices(root.userId)) {
+ for (ServiceRecord sr : mServiceMap.getAllServices(tr.userId)) {
if (sr.packageName.equals(component.getPackageName())) {
services.add(sr);
}
@@ -5406,7 +5599,7 @@ public final class ActivityManagerService extends ActivityManagerNative
stopServiceLocked(sr);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
- sr.makeNextStartId(), baseIntent, -1));
+ sr.makeNextStartId(), baseIntent, null));
if (sr.app != null && sr.app.thread != null) {
sendServiceArgsLocked(sr, false);
}
@@ -5446,11 +5639,11 @@ public final class ActivityManagerService extends ActivityManagerNative
"removeTask()");
long ident = Binder.clearCallingIdentity();
try {
- ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
+ ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1,
+ false);
if (r != null) {
mRecentTasks.remove(r.task);
- cleanUpRemovedTaskLocked(r,
- (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
+ cleanUpRemovedTaskLocked(r.task, flags);
return true;
} else {
TaskRecord tr = null;
@@ -5468,6 +5661,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Caller is just removing a recent task that is
// not actively running. That is easy!
mRecentTasks.remove(i);
+ cleanUpRemovedTaskLocked(tr, flags);
+ return true;
} else {
Slog.w(TAG, "removeTask: task " + taskId
+ " does not have activities to remove, "
@@ -5523,13 +5718,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();
@@ -5544,7 +5740,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--) {
@@ -5558,13 +5754,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);
}
}
@@ -5765,6 +5962,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return providers;
}
+ /**
+ * Check if {@link ProcessRecord} has a possible chance at accessing the
+ * given {@link ProviderInfo}. Final permission checking is always done
+ * in {@link ContentProvider}.
+ */
private final String checkContentProviderPermissionLocked(
ProviderInfo cpi, ProcessRecord r) {
final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
@@ -5965,15 +6167,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) {
@@ -5990,7 +6191,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 {
@@ -5998,13 +6199,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.
@@ -6045,7 +6246,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 "
@@ -6379,7 +6580,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 "
@@ -6611,12 +6812,25 @@ 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);
}
}
}
+ void setOpenGlTraceApp(ApplicationInfo app, String processName) {
+ synchronized (this) {
+ boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+ if (!isDebuggable) {
+ if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+ throw new SecurityException("Process not debuggable: " + app.packageName);
+ }
+ }
+
+ mOpenGlTraceApp = processName;
+ }
+ }
+
void setProfileApp(ApplicationInfo app, String processName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
synchronized (this) {
@@ -6813,7 +7027,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) {
@@ -6957,7 +7207,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) {
@@ -7214,6 +7464,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;
@@ -7261,7 +7515,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 "
@@ -7623,7 +7877,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) {
@@ -7952,6 +8206,22 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private void fillInProcMemInfo(ProcessRecord app,
+ ActivityManager.RunningAppProcessInfo outInfo) {
+ outInfo.pid = app.pid;
+ outInfo.uid = app.info.uid;
+ if (mHeavyWeightProcess == app) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
+ }
+ if (app.persistent) {
+ outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
+ }
+ outInfo.lastTrimLevel = app.trimMemoryLevel;
+ int adj = app.curAdj;
+ outInfo.importance = oomAdjToImportance(adj, outInfo);
+ outInfo.importanceReasonCode = app.adjTypeCode;
+ }
+
public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
enforceNotIsolatedCaller("getRunningAppProcesses");
// Lazy instantiation of list
@@ -7965,16 +8235,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ActivityManager.RunningAppProcessInfo currApp =
new ActivityManager.RunningAppProcessInfo(app.processName,
app.pid, app.getPackageList());
- currApp.uid = app.info.uid;
- if (mHeavyWeightProcess == app) {
- currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
- }
- if (app.persistent) {
- currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
- }
- int adj = app.curAdj;
- currApp.importance = oomAdjToImportance(adj, currApp);
- currApp.importanceReasonCode = app.adjTypeCode;
+ fillInProcMemInfo(app, currApp);
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
currApp.importanceReasonImportance = oomAdjToImportance(
@@ -8014,7 +8275,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);
}
@@ -8026,6 +8287,18 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) {
+ enforceNotIsolatedCaller("getMyMemoryState");
+ synchronized (this) {
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(Binder.getCallingPid());
+ }
+ fillInProcMemInfo(proc, outInfo);
+ }
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (checkCallingPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -8479,8 +8752,8 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(" Process "); pw.print(pname);
pw.print(" uid "); pw.print(puid);
pw.print(": last crashed ");
- pw.print((now-uids.valueAt(i)));
- pw.println(" ms ago");
+ TimeUtils.formatDuration(now-uids.valueAt(i), pw);
+ pw.println(" ago");
}
}
}
@@ -8552,6 +8825,9 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " mDebugTransient=" + mDebugTransient
+ " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
}
+ if (mOpenGlTraceApp != null) {
+ pw.println(" mOpenGlTraceApp=" + mOpenGlTraceApp);
+ }
if (mProfileApp != null || mProfileProc != null || mProfileFile != null
|| mProfileFd != null) {
pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
@@ -9025,7 +9301,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<N; i++) {
sb.setLength(0);
sb.append(" Intent: ");
- intents.get(i).toShortString(sb, false, true, false);
+ intents.get(i).toShortString(sb, false, true, false, false);
pw.println(sb.toString());
Bundle bundle = intents.get(i).getExtras();
if (bundle != null) {
@@ -9110,7 +9386,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ConnectionRecord conn = clist.get(i);
pw.print(" ");
pw.print(conn.binding.intent.intent.getIntent()
- .toShortString(false, false, false));
+ .toShortString(false, false, false, false));
pw.print(" -> ");
ProcessRecord proc = conn.binding.client;
pw.println(proc != null ? proc.toShortString() : "null");
@@ -9249,7 +9525,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
- boolean needSep = false;
+ boolean needSep = true;
ItemMatcher matcher = new ItemMatcher();
matcher.build(args, opti);
@@ -9361,7 +9637,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Complete + brief == give a summary. Isn't that obvious?!?
if (lastTask.intent != null) {
pw.print(prefix); pw.print(" ");
- pw.println(lastTask.intent.toInsecureString());
+ pw.println(lastTask.intent.toInsecureStringWithClip());
}
}
}
@@ -9997,6 +10273,29 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println();
pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
+ final int[] SINGLE_LONG_FORMAT = new int[] {
+ Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+ };
+ long[] longOut = new long[1];
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+ SINGLE_LONG_FORMAT, null, longOut, null);
+ long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+ longOut[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+ SINGLE_LONG_FORMAT, null, longOut, null);
+ long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+ longOut[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+ SINGLE_LONG_FORMAT, null, longOut, null);
+ long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+ longOut[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+ SINGLE_LONG_FORMAT, null, longOut, null);
+ long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+ pw.print(" KSM: "); pw.print(sharing); pw.print(" kB saved from shared ");
+ pw.print(shared); pw.println(" kB");
+ pw.print(" "); pw.print(unshared); pw.print(" kB unshared; ");
+ pw.print(voltile); pw.println(" kB volatile");
}
}
@@ -10480,21 +10779,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) {
@@ -10565,7 +10864,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) {
@@ -10673,9 +10972,9 @@ public final class ActivityManagerService extends ActivityManagerNative
si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
- if (si.targetPermissionUid >= 0 && si.intent != null) {
- grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
- r.packageName, si.intent, si.getUriPermissionsLocked());
+ if (si.neededGrants != null) {
+ grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
+ si.getUriPermissionsLocked());
}
bumpServiceExecutingLocked(r, "start");
if (!oomAdjusted) {
@@ -10753,7 +11052,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean created = false;
try {
mStringBuilder.setLength(0);
- r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
+ r.intent.getIntent().toShortString(mStringBuilder, true, false, true, false);
EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
System.identityHashCode(r), r.shortName,
mStringBuilder.toString(), r.app.pid);
@@ -10779,7 +11078,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- null, -1));
+ null, null));
}
sendServiceArgsLocked(r, true);
@@ -10930,7 +11229,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 "
@@ -11151,15 +11450,15 @@ public final class ActivityManagerService extends ActivityManagerNative
? res.permission : "private to package");
}
ServiceRecord r = res.record;
- int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
- callingUid, r.packageName, service);
+ NeededUriGrants neededGrants = checkGrantUriPermissionFromIntentLocked(
+ callingUid, r.packageName, service, service.getFlags(), null);
if (unscheduleServiceRestartLocked(r)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.startRequested = true;
r.callStart = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- service, targetPermissionUid));
+ service, neededGrants));
r.lastActivity = SystemClock.uptimeMillis();
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
@@ -11235,7 +11534,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();
@@ -11263,7 +11563,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
@@ -11892,7 +12193,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 "
@@ -12221,7 +12522,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!");
}
@@ -12256,7 +12557,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);
@@ -12267,7 +12568,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,
@@ -12334,7 +12636,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
- return BROADCAST_SUCCESS;
+ return ActivityManager.BROADCAST_SUCCESS;
}
}
@@ -12352,7 +12654,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (requiredPermission != null) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
+ " and enforce permission " + requiredPermission);
- return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
+ return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
if (intent.getComponent() != null) {
throw new SecurityException(
@@ -12384,7 +12686,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();
@@ -12392,15 +12694,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.
@@ -12526,7 +12828,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- return BROADCAST_SUCCESS;
+ return ActivityManager.BROADCAST_SUCCESS;
}
final Intent verifyBroadcastLocked(Intent intent) {
@@ -12691,7 +12993,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) {
@@ -12719,9 +13021,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;
@@ -12776,11 +13079,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");
@@ -13010,6 +13314,102 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
+ public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) {
+ ActivityRecord srec = ActivityRecord.forToken(token);
+ return srec.task.affinity != null && srec.task.affinity.equals(destAffinity);
+ }
+
+ public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
+ Intent resultData) {
+ ComponentName dest = destIntent.getComponent();
+
+ synchronized (this) {
+ ActivityRecord srec = ActivityRecord.forToken(token);
+ ArrayList<ActivityRecord> history = srec.stack.mHistory;
+ final int start = history.indexOf(srec);
+ if (start < 0) {
+ // Current activity is not in history stack; do nothing.
+ return false;
+ }
+ int finishTo = start - 1;
+ ActivityRecord parent = null;
+ boolean foundParentInTask = false;
+ if (dest != null) {
+ TaskRecord tr = srec.task;
+ for (int i = start - 1; i >= 0; i--) {
+ ActivityRecord r = history.get(i);
+ if (tr != r.task) {
+ // Couldn't find parent in the same task; stop at the one above this.
+ // (Root of current task; in-app "home" behavior)
+ // Always at least finish the current activity.
+ finishTo = Math.min(start - 1, i + 1);
+ parent = history.get(finishTo);
+ break;
+ } else if (r.info.packageName.equals(dest.getPackageName()) &&
+ r.info.name.equals(dest.getClassName())) {
+ finishTo = i;
+ parent = r;
+ foundParentInTask = true;
+ break;
+ }
+ }
+ }
+
+ if (mController != null) {
+ ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
+ if (next != null) {
+ // ask watcher if this is allowed
+ boolean resumeOK = true;
+ try {
+ resumeOK = mController.activityResuming(next.packageName);
+ } catch (RemoteException e) {
+ mController = null;
+ }
+
+ if (!resumeOK) {
+ return false;
+ }
+ }
+ }
+ final long origId = Binder.clearCallingIdentity();
+ for (int i = start; i > finishTo; i--) {
+ ActivityRecord r = history.get(i);
+ mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
+ "navigate-up");
+ // Only return the supplied result for the first activity finished
+ resultCode = Activity.RESULT_CANCELED;
+ resultData = null;
+ }
+
+ if (parent != null && foundParentInTask) {
+ final int parentLaunchMode = parent.info.launchMode;
+ final int destIntentFlags = destIntent.getFlags();
+ if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
+ parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
+ parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
+ (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+ parent.deliverNewIntentLocked(srec.app.uid, destIntent);
+ } else {
+ try {
+ ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
+ destIntent.getComponent(), 0, UserId.getCallingUserId());
+ int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
+ null, aInfo, parent.appToken, null,
+ 0, -1, parent.launchedFromUid, 0, null, true, null);
+ foundParentInTask = res == ActivityManager.START_SUCCESS;
+ } catch (RemoteException e) {
+ foundParentInTask = false;
+ }
+ mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
+ resultData, "navigate-up");
+ }
+ }
+ Binder.restoreCallingIdentity(origId);
+ return foundParentInTask;
+ }
+ }
+
// =========================================================
// LIFETIME MANAGEMENT
// =========================================================
@@ -13982,6 +14382,14 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mPreviousProcess != null) minFactor++;
if (factor < minFactor) factor = minFactor;
step = 0;
+ int fgTrimLevel;
+ if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/5)) {
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+ } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) {
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+ } else {
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+ }
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (i=0; i<N; i++) {
ProcessRecord app = mLruProcesses.get(i);
@@ -14008,6 +14416,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.trimMemoryLevel = curLevel;
step++;
if (step >= factor) {
+ step = 0;
switch (curLevel) {
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
@@ -14027,20 +14436,28 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
- } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
- && app.pendingUiClean) {
- if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
- && app.thread != null) {
+ } else {
+ if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
+ && app.pendingUiClean) {
+ // If this application is now in the background and it
+ // had done UI, then give it the special trim level to
+ // have it free UI resources.
+ final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+ if (app.trimMemoryLevel < level && app.thread != null) {
+ try {
+ app.thread.scheduleTrimMemory(level);
+ } catch (RemoteException e) {
+ }
+ }
+ app.pendingUiClean = false;
+ }
+ if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
- app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
- app.pendingUiClean = false;
- } else {
- app.trimMemoryLevel = 0;
+ app.trimMemoryLevel = fgTrimLevel;
}
}
} else {
@@ -14057,11 +14474,9 @@ public final class ActivityManagerService extends ActivityManagerNative
} catch (RemoteException e) {
}
}
- app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
app.pendingUiClean = false;
- } else {
- app.trimMemoryLevel = 0;
}
+ app.trimMemoryLevel = 0;
}
}
@@ -14327,25 +14742,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();
@@ -14356,8 +14752,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.
@@ -14374,23 +14768,54 @@ 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;
+ @Override
+ public UserInfo getCurrentUser() throws RemoteException {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != 0 && callingUid != Process.myUid()) {
+ Slog.e(TAG, "Trying to get user from unauthorized app");
+ return null;
+ }
+ return AppGlobals.getPackageManager().getUser(mCurrentUserId);
+ }
+
+ 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 cdab6c6..a098f18 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -16,16 +16,17 @@
package com.android.server.am;
+import com.android.internal.app.ResolverActivity;
import com.android.server.AttributeCache;
import com.android.server.am.ActivityStack.ActivityState;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.content.ComponentName;
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;
@@ -85,6 +86,8 @@ final class ActivityRecord {
long startTime; // last time this activity was started
long lastVisibleTime; // last time this activity became visible
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
+ long pauseTime; // last time we started pausing the activity
+ long launchTickTime; // base time for launch tick messages
Configuration configuration; // configuration activity was last running in
CompatibilityInfo compat;// last used compatibility mode
ActivityRecord resultTo; // who started this entry, so will get our reply
@@ -93,6 +96,7 @@ final class ActivityRecord {
ArrayList results; // pending ActivityResult objs we have received
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
ArrayList newIntents; // any pending new intents for single-top mode
+ ActivityOptions pendingOptions; // most recently given options
HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
UriPermissionOwner uriPermissions; // current special URI access perms.
ProcessRecord app; // if non-null, hosting application
@@ -127,26 +131,27 @@ final class ActivityRecord {
pw.print(prefix); pw.print("packageName="); pw.print(packageName);
pw.print(" processName="); pw.println(processName);
pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
- pw.print(prefix); pw.print("userId="); pw.print(userId);
- pw.print(" app="); pw.println(app);
- pw.print(prefix); pw.println(intent.toInsecureString());
+ pw.print(" userId="); pw.println(userId);
+ pw.print(prefix); pw.print("app="); pw.println(app);
+ pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
pw.print(" task="); pw.println(task);
pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
pw.print(prefix); pw.print("realActivity=");
pw.println(realActivity.flattenToShortString());
- pw.print(prefix); pw.print("base="); pw.print(baseDir);
- if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir);
- pw.print(" data="); pw.println(dataDir);
- pw.print(prefix); pw.print("labelRes=0x");
- pw.print(Integer.toHexString(labelRes));
- pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
- pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
+ pw.print(prefix); pw.print("baseDir="); pw.println(baseDir);
+ if (!resDir.equals(baseDir)) {
+ pw.print(prefix); pw.print("resDir="); pw.println(resDir);
+ }
+ pw.print(prefix); pw.print("dataDir="); pw.println(dataDir);
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified);
pw.print(" isHomeActivity="); pw.println(isHomeActivity);
+ pw.print(prefix); pw.print("compat="); pw.print(compat);
+ pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
+ pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
+ pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
pw.print(prefix); pw.print("config="); pw.println(configuration);
- pw.print(prefix); pw.print("compat="); pw.println(compat);
if (resultTo != null || resultWho != null) {
pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
pw.print(" resultWho="); pw.print(resultWho);
@@ -193,13 +198,11 @@ final class ActivityRecord {
TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
TimeUtils.formatDuration(startTime, pw); pw.println("");
}
- if (lastVisibleTime != 0) {
- pw.print(prefix); pw.print("lastVisibleTime=");
- TimeUtils.formatDuration(lastVisibleTime, pw); pw.println("");
- }
- if (waitingVisible || nowVisible) {
+ if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
- pw.print(" nowVisible="); pw.println(nowVisible);
+ pw.print(" nowVisible="); pw.print(nowVisible);
+ pw.print("lastVisibleTime=");
+ TimeUtils.formatDuration(lastVisibleTime, pw); pw.println("");
}
if (configDestroy || configChangeFlags != 0) {
pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
@@ -380,7 +383,7 @@ final class ActivityRecord {
_intent.getData() == null &&
_intent.getType() == null &&
(intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
- !"android".equals(realActivity.getClassName())) {
+ !ResolverActivity.class.getName().equals(realActivity.getClassName())) {
// This sure looks like a home activity!
// Note the last check is so we don't count the resolver
// activity as being home... really, we don't care about
@@ -537,6 +540,42 @@ final class ActivityRecord {
}
}
+ void updateOptionsLocked(Bundle options) {
+ if (options != null) {
+ if (pendingOptions != null) {
+ pendingOptions.abort();
+ }
+ pendingOptions = new ActivityOptions(options);
+ }
+ }
+
+ void applyOptionsLocked() {
+ if (pendingOptions != null) {
+ 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() {
+ if (pendingOptions != null) {
+ pendingOptions.abort();
+ pendingOptions = null;
+ }
+ }
+
void removeUriPermissionsLocked() {
if (uriPermissions != null) {
uriPermissions.removeUriPermissionsLocked();
@@ -577,6 +616,32 @@ final class ActivityRecord {
}
}
+ void startLaunchTickingLocked() {
+ if (ActivityManagerService.IS_USER_BUILD) {
+ return;
+ }
+ if (launchTickTime == 0) {
+ launchTickTime = SystemClock.uptimeMillis();
+ continueLaunchTickingLocked();
+ }
+ }
+
+ boolean continueLaunchTickingLocked() {
+ if (launchTickTime != 0) {
+ Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG);
+ msg.obj = this;
+ stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+ stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
+ return true;
+ }
+ return false;
+ }
+
+ void finishLaunchTickingLocked() {
+ launchTickTime = 0;
+ stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+ }
+
// IApplicationToken
public boolean mayFreezeScreenLocked(ProcessRecord app) {
@@ -632,6 +697,7 @@ final class ActivityRecord {
stack.mInitialStartTime = 0;
}
startTime = 0;
+ finishLaunchTickingLocked();
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index f9641eb..a01ed25 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -22,18 +22,10 @@ import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IThumbnailRetriever;
-import static android.app.IActivityManager.START_CLASS_NOT_FOUND;
-import static android.app.IActivityManager.START_DELIVERED_TO_TOP;
-import static android.app.IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
-import static android.app.IActivityManager.START_INTENT_NOT_RESOLVED;
-import static android.app.IActivityManager.START_PERMISSION_DENIED;
-import static android.app.IActivityManager.START_RETURN_INTENT_TO_CALLER;
-import static android.app.IActivityManager.START_SUCCESS;
-import static android.app.IActivityManager.START_SWITCHES_CANCELED;
-import static android.app.IActivityManager.START_TASK_TO_FRONT;
import android.app.IApplicationThread;
import android.app.PendingIntent;
import android.app.ResultInfo;
@@ -96,7 +88,10 @@ final class ActivityStack {
// How long we wait until giving up on the last activity telling us it
// is idle.
static final int IDLE_TIMEOUT = 10*1000;
-
+
+ // Ticks during which we check progress while waiting for an app to launch.
+ static final int LAUNCH_TICK = 500;
+
// How long we wait until giving up on the last activity to pause. This
// is short because it directly impacts the responsiveness of starting the
// next activity.
@@ -284,6 +279,7 @@ final class ActivityStack {
static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
+ static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
final Handler mHandler = new Handler() {
//public Handler() {
@@ -306,6 +302,13 @@ final class ActivityStack {
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
Slog.w(TAG, "Activity pause timeout for " + r);
+ synchronized (mService) {
+ if (r.app != null) {
+ mService.logAppTooSlow(r.app, r.pauseTime,
+ "pausing " + r);
+ }
+ }
+
activityPaused(r != null ? r.appToken : null, true);
} break;
case IDLE_TIMEOUT_MSG: {
@@ -322,6 +325,15 @@ final class ActivityStack {
Slog.w(TAG, "Activity idle timeout for " + r);
activityIdleInternal(r != null ? r.appToken : null, true, null);
} break;
+ case LAUNCH_TICK_MSG: {
+ ActivityRecord r = (ActivityRecord)msg.obj;
+ synchronized (mService) {
+ if (r.continueLaunchTickingLocked()) {
+ mService.logAppTooSlow(r.app, r.launchTickTime,
+ "launching " + r);
+ }
+ }
+ } break;
case DESTROY_TIMEOUT_MSG: {
ActivityRecord r = (ActivityRecord)msg.obj;
// We don't at this point know if the activity is fullscreen,
@@ -563,6 +575,9 @@ final class ActivityStack {
r.startFreezingScreenLocked(app, 0);
mService.mWindowManager.setAppVisibility(r.appToken, true);
+ // schedule launch ticks to collect information about slow apps.
+ r.startLaunchTickingLocked();
+
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order. Note that
// as a result of this, it can call back into the activity
@@ -945,6 +960,7 @@ final class ActivityStack {
// responsiveness seen by the user.
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
+ prev.pauseTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
} else {
@@ -1429,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 "
@@ -1441,6 +1456,7 @@ final class ActivityStack {
// We are starting up the next activity, so tell the window manager
// that the previous one will be hidden soon. This way it can know
// to ignore it when computing the desired screen orientation.
+ boolean noAnim = false;
if (prev != null) {
if (prev.finishing) {
if (DEBUG_TRANSITION) Slog.v(TAG,
@@ -1459,6 +1475,7 @@ final class ActivityStack {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
+ noAnim = true;
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE, false);
} else {
@@ -1475,6 +1492,7 @@ final class ActivityStack {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
+ noAnim = true;
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE, false);
} else {
@@ -1482,6 +1500,11 @@ final class ActivityStack {
WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, false);
}
}
+ if (!noAnim) {
+ next.applyOptionsLocked();
+ } else {
+ next.clearOptionsLocked();
+ }
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
@@ -1489,6 +1512,9 @@ final class ActivityStack {
// This activity is now becoming visible.
mService.mWindowManager.setAppVisibility(next.appToken, true);
+ // schedule launch ticks to collect information about slow apps.
+ next.startLaunchTickingLocked();
+
ActivityRecord lastResumedActivity = mResumedActivity;
ActivityState lastState = next.state;
@@ -1637,7 +1663,7 @@ final class ActivityStack {
}
private final void startActivityLocked(ActivityRecord r, boolean newTask,
- boolean doResume, boolean keepCurTransition) {
+ boolean doResume, boolean keepCurTransition, Bundle options) {
final int NH = mHistory.size();
int addPos = -1;
@@ -1669,6 +1695,7 @@ final class ActivityStack {
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
+ ActivityOptions.abort(options);
return;
}
break;
@@ -1730,6 +1757,7 @@ final class ActivityStack {
: WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
+ r.updateOptionsLocked(options);
mService.mWindowManager.addAppToken(
addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen);
boolean doShow = true;
@@ -1770,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();
@@ -1821,6 +1850,10 @@ final class ActivityStack {
if (below != null && below.finishing) {
continue;
}
+ // Don't check any lower in the stack if we're crossing a user boundary.
+ if (below != null && below.userId != taskTop.userId) {
+ break;
+ }
if (target == null) {
target = below;
targetI = i;
@@ -2266,14 +2299,12 @@ final class ActivityStack {
}
final int startActivityLocked(IApplicationThread caller,
- Intent intent, String resolvedType,
- Uri[] grantedUriPermissions,
- int grantedMode, ActivityInfo aInfo, IBinder resultTo,
+ Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
- int callingPid, int callingUid, boolean onlyIfNeeded,
+ int callingPid, int callingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
- int err = START_SUCCESS;
+ int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
@@ -2285,13 +2316,13 @@ final class ActivityStack {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
- err = START_PERMISSION_DENIED;
+ err = ActivityManager.START_PERMISSION_DENIED;
}
}
- if (err == START_SUCCESS) {
- Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid "
- + (callerApp != null ? callerApp.pid : callingPid));
+ if (err == ActivityManager.START_SUCCESS) {
+ Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
+ + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
}
ActivityRecord sourceRecord = null;
@@ -2315,7 +2346,8 @@ final class ActivityStack {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
if (requestCode >= 0) {
- return START_FORWARD_AND_REQUEST_CONFLICT;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
resultWho = sourceRecord.resultWho;
@@ -2327,25 +2359,26 @@ final class ActivityStack {
}
}
- if (err == START_SUCCESS && intent.getComponent() == null) {
+ if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
// We couldn't find a class that can handle the given Intent.
// That's the end of that!
- err = START_INTENT_NOT_RESOLVED;
+ err = ActivityManager.START_INTENT_NOT_RESOLVED;
}
- if (err == START_SUCCESS && aInfo == null) {
+ if (err == ActivityManager.START_SUCCESS && aInfo == null) {
// We couldn't find the specific class specified in the Intent.
// Also the end of the line.
- err = START_CLASS_NOT_FOUND;
+ err = ActivityManager.START_CLASS_NOT_FOUND;
}
- if (err != START_SUCCESS) {
+ if (err != ActivityManager.START_SUCCESS) {
if (resultRecord != null) {
sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
mDismissKeyguardOnNextActivity = false;
+ ActivityOptions.abort(options);
return err;
}
@@ -2396,7 +2429,8 @@ final class ActivityStack {
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
mDismissKeyguardOnNextActivity = false;
- return START_SUCCESS;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_SUCCESS;
}
}
}
@@ -2415,12 +2449,11 @@ final class ActivityStack {
PendingActivityLaunch pal = new PendingActivityLaunch();
pal.r = r;
pal.sourceRecord = sourceRecord;
- pal.grantedUriPermissions = grantedUriPermissions;
- pal.grantedMode = grantedMode;
- pal.onlyIfNeeded = onlyIfNeeded;
+ pal.startFlags = startFlags;
mService.mPendingActivityLaunches.add(pal);
mDismissKeyguardOnNextActivity = false;
- return START_SWITCHES_CANCELED;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_SWITCHES_CANCELED;
}
}
@@ -2439,7 +2472,7 @@ final class ActivityStack {
}
err = startActivityUncheckedLocked(r, sourceRecord,
- grantedUriPermissions, grantedMode, onlyIfNeeded, true);
+ startFlags, true, options);
if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
// Someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
@@ -2462,8 +2495,8 @@ final class ActivityStack {
}
final int startActivityUncheckedLocked(ActivityRecord r,
- ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
- int grantedMode, boolean onlyIfNeeded, boolean doResume) {
+ ActivityRecord sourceRecord, int startFlags, boolean doResume,
+ Bundle options) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
final int userId = r.userId;
@@ -2490,14 +2523,14 @@ final class ActivityStack {
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
- if (onlyIfNeeded) {
+ if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
checkedCaller = topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
- onlyIfNeeded = false;
+ startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
}
}
@@ -2574,7 +2607,7 @@ final class ActivityStack {
// We really do want to push this one into the
// user's face, right now.
moveHomeToFrontFromLaunchLocked(launchFlags);
- moveTaskToFrontLocked(taskTop.task, r);
+ moveTaskToFrontLocked(taskTop.task, r, options);
}
}
// If the caller has requested that the target task be
@@ -2582,7 +2615,7 @@ final class ActivityStack {
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
taskTop = resetTaskIfNeededLocked(taskTop, r);
}
- if (onlyIfNeeded) {
+ 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
// is the case, so this is it! And for paranoia, make
@@ -2590,7 +2623,8 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
- return START_RETURN_INTENT_TO_CALLER;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
@@ -2677,7 +2711,8 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
- return START_TASK_TO_FRONT;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_TASK_TO_FRONT;
}
}
}
@@ -2706,14 +2741,15 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
- if (onlyIfNeeded) {
+ 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
// is the case, so this is it!
- return START_RETURN_INTENT_TO_CALLER;
+ return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent);
- return START_DELIVERED_TO_TOP;
+ return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
@@ -2725,7 +2761,8 @@ final class ActivityStack {
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
}
- return START_CLASS_NOT_FOUND;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_CLASS_NOT_FOUND;
}
boolean newTask = false;
@@ -2766,7 +2803,8 @@ final class ActivityStack {
if (doResume) {
resumeTopActivityLocked(null);
}
- return START_DELIVERED_TO_TOP;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
@@ -2777,11 +2815,12 @@ final class ActivityStack {
if (where >= 0) {
ActivityRecord top = moveActivityToFrontLocked(where);
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
+ top.updateOptionsLocked(options);
top.deliverNewIntentLocked(callingUid, r.intent);
if (doResume) {
resumeTopActivityLocked(null);
}
- return START_DELIVERED_TO_TOP;
+ return ActivityManager.START_DELIVERED_TO_TOP;
}
}
// An existing activity is starting this new activity, so we want
@@ -2805,13 +2844,6 @@ final class ActivityStack {
+ " in new guessed " + r.task);
}
- if (grantedUriPermissions != null && callingUid > 0) {
- for (int i=0; i<grantedUriPermissions.length; i++) {
- mService.grantUriPermissionLocked(callingUid, r.packageName,
- grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked());
- }
- }
-
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked());
@@ -2819,12 +2851,12 @@ final class ActivityStack {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
}
logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
- startActivityLocked(r, newTask, doResume, keepCurTransition);
- return START_SUCCESS;
+ startActivityLocked(r, newTask, doResume, keepCurTransition, options);
+ return ActivityManager.START_SUCCESS;
}
- ActivityInfo resolveActivity(Intent intent, String resolvedType, boolean debug,
- String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+ ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
+ String profileFile, ParcelFileDescriptor profileFd, int userId) {
// Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
@@ -2832,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;
@@ -2847,16 +2879,23 @@ final class ActivityStack {
aInfo.applicationInfo.packageName, aInfo.name));
// Don't debug things in the system process
- if (debug) {
+ if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
if (!aInfo.processName.equals("system")) {
mService.setDebugApp(aInfo.processName, true, false);
}
}
+ if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
+ if (!aInfo.processName.equals("system")) {
+ mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
+ }
+ }
+
if (profileFile != null) {
if (!aInfo.processName.equals("system")) {
mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
- profileFile, profileFd, autoStopProfiler);
+ profileFile, profileFd,
+ (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
}
}
}
@@ -2864,12 +2903,10 @@ final class ActivityStack {
}
final int startActivityMayWait(IApplicationThread caller, int callingUid,
- Intent intent, String resolvedType, Uri[] grantedUriPermissions,
- int grantedMode, IBinder resultTo,
- String resultWho, int requestCode, boolean onlyIfNeeded,
- boolean debug, String profileFile, ParcelFileDescriptor profileFd,
- boolean autoStopProfiler,
- WaitResult outResult, Configuration config, int userId) {
+ Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags, String profileFile,
+ ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
+ Bundle options, int userId) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -2880,8 +2917,8 @@ final class ActivityStack {
intent = new Intent(intent);
// Collect information about the target of the Intent.
- ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
- profileFile, profileFd, autoStopProfiler);
+ ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
+ profileFile, profileFd, userId);
aInfo = mService.getActivityInfoForUser(aInfo, userId);
synchronized (mService) {
@@ -2921,15 +2958,16 @@ final class ActivityStack {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + realCallingPid + ") when starting: "
+ intent.toString());
- return START_PERMISSION_DENIED;
+ ActivityOptions.abort(options);
+ return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(
- IActivityManager.INTENT_SENDER_ACTIVITY, "android",
+ ActivityManager.INTENT_SENDER_ACTIVITY, "android",
realCallingUid, null, null, 0, new Intent[] { intent },
new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
- | PendingIntent.FLAG_ONE_SHOT);
+ | PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
if (requestCode >= 0) {
@@ -2961,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) {
@@ -2972,9 +3010,8 @@ final class ActivityStack {
}
int res = startActivityLocked(caller, intent, resolvedType,
- grantedUriPermissions, grantedMode, aInfo,
- resultTo, resultWho, requestCode, callingPid, callingUid,
- onlyIfNeeded, componentSpecified, null);
+ aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
+ startFlags, options, componentSpecified, null);
if (mConfigWillChange && mMainStack) {
// If the caller also wants to switch to a new configuration,
@@ -2993,7 +3030,7 @@ final class ActivityStack {
if (outResult != null) {
outResult.result = res;
- if (res == IActivityManager.START_SUCCESS) {
+ if (res == ActivityManager.START_SUCCESS) {
mWaitingActivityLaunched.add(outResult);
do {
try {
@@ -3001,7 +3038,7 @@ final class ActivityStack {
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
- } else if (res == IActivityManager.START_TASK_TO_FRONT) {
+ } else if (res == ActivityManager.START_TASK_TO_FRONT) {
ActivityRecord r = this.topRunningActivityLocked(null);
if (r.nowVisible) {
outResult.timeout = false;
@@ -3026,8 +3063,8 @@ final class ActivityStack {
}
final int startActivities(IApplicationThread caller, int callingUid,
- Intent[] intents,
- String[] resolvedTypes, IBinder resultTo, int userId) {
+ Intent[] intents, String[] resolvedTypes, IBinder resultTo,
+ Bundle options, int userId) {
if (intents == null) {
throw new NullPointerException("intents is null");
}
@@ -3070,8 +3107,8 @@ final class ActivityStack {
intent = new Intent(intent);
// Collect information about the target of the Intent.
- ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i], false,
- null, null, false);
+ ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
+ 0, null, null, userId);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -3081,9 +3118,15 @@ final class ActivityStack {
"FLAG_CANT_SAVE_STATE not supported here");
}
+ Bundle theseOptions;
+ if (options != null && i == intents.length-1) {
+ theseOptions = options;
+ } else {
+ theseOptions = null;
+ }
int res = startActivityLocked(caller, intent, resolvedTypes[i],
- null, 0, aInfo, resultTo, null, -1, callingPid, callingUid,
- false, componentSpecified, outActivity);
+ aInfo, resultTo, null, -1, callingPid, callingUid,
+ 0, theseOptions, componentSpecified, outActivity);
if (res < 0) {
return res;
}
@@ -3095,7 +3138,7 @@ final class ActivityStack {
Binder.restoreCallingIdentity(origId);
}
- return IActivityManager.START_SUCCESS;
+ return ActivityManager.START_SUCCESS;
}
void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
@@ -3270,6 +3313,7 @@ final class ActivityStack {
ActivityRecord r = ActivityRecord.forToken(token);
if (r != null) {
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
+ r.finishLaunchTickingLocked();
}
// Get the activity record.
@@ -3447,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;
@@ -3488,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,
@@ -3640,6 +3696,7 @@ final class ActivityStack {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
+ r.finishLaunchTickingLocked();
}
final void removeActivityFromHistoryLocked(ActivityRecord r) {
@@ -3853,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;
@@ -3866,6 +3923,7 @@ final class ActivityStack {
if (top < 0 || (mHistory.get(top)).task.taskId == task) {
// nothing to do!
+ ActivityOptions.abort(options);
return;
}
@@ -3907,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);
}
@@ -4024,10 +4091,13 @@ final class ActivityStack {
return info;
}
- public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex) {
+ public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
+ boolean taskRequired) {
TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
if (info.root == null) {
- Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
+ if (taskRequired) {
+ Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
+ }
return null;
}
@@ -4038,7 +4108,9 @@ final class ActivityStack {
}
if (subTaskIndex >= info.subtasks.size()) {
- Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
+ if (taskRequired) {
+ Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
+ }
return null;
}
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/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index f338cfc..608b09a 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -157,7 +157,7 @@ class ContentProviderRecord extends ContentProviderHolder {
sb.append("ContentProviderRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
- sb.append(info.name);
+ sb.append(name.flattenToShortString());
sb.append('}');
return stringName = sb.toString();
}
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index 2618c77..c94f714 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -54,7 +54,7 @@ class IntentBindRecord {
void dumpInService(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("intent={");
- pw.print(intent.getIntent().toShortString(false, true, false));
+ pw.print(intent.getIntent().toShortString(false, true, false, false));
pw.println('}');
pw.print(prefix); pw.print("binder="); pw.println(binder);
pw.print(prefix); pw.print("requested="); pw.print(requested);
@@ -89,7 +89,7 @@ class IntentBindRecord {
sb.append(service.shortName);
sb.append(':');
if (intent != null) {
- intent.getIntent().toShortString(sb, false, false, false);
+ intent.getIntent().toShortString(sb, false, false, false, false);
}
sb.append('}');
return stringName = sb.toString();
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 3b6a97c..ad15da1 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -16,12 +16,13 @@
package com.android.server.am;
-import android.app.IActivityManager;
+import android.app.ActivityManager;
import android.content.IIntentSender;
import android.content.IIntentReceiver;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserId;
@@ -48,6 +49,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
final int requestCode;
final Intent requestIntent;
final String requestResolvedType;
+ final Bundle options;
Intent[] allIntents;
String[] allResolvedTypes;
final int flags;
@@ -56,7 +58,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
private static final int ODD_PRIME_NUMBER = 37;
Key(int _t, String _p, ActivityRecord _a, String _w,
- int _r, Intent[] _i, String[] _it, int _f) {
+ int _r, Intent[] _i, String[] _it, int _f, Bundle _o) {
type = _t;
packageName = _p;
activity = _a;
@@ -67,6 +69,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
allIntents = _i;
allResolvedTypes = _it;
flags = _f;
+ options = _o;
int hash = 23;
hash = (ODD_PRIME_NUMBER*hash) + _f;
@@ -152,19 +155,19 @@ class PendingIntentRecord extends IIntentSender.Stub {
return "Key{" + typeName() + " pkg=" + packageName
+ " intent="
+ (requestIntent != null
- ? requestIntent.toShortString(false, true, false) : "<null>")
+ ? requestIntent.toShortString(false, true, false, false) : "<null>")
+ " flags=0x" + Integer.toHexString(flags) + "}";
}
String typeName() {
switch (type) {
- case IActivityManager.INTENT_SENDER_ACTIVITY:
+ case ActivityManager.INTENT_SENDER_ACTIVITY:
return "startActivity";
- case IActivityManager.INTENT_SENDER_BROADCAST:
+ case ActivityManager.INTENT_SENDER_BROADCAST:
return "broadcastIntent";
- case IActivityManager.INTENT_SENDER_SERVICE:
+ case ActivityManager.INTENT_SENDER_SERVICE:
return "startService";
- case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
+ case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
return "activityResult";
}
return Integer.toString(type);
@@ -181,13 +184,13 @@ class PendingIntentRecord extends IIntentSender.Stub {
public int send(int code, Intent intent, String resolvedType,
IIntentReceiver finishedReceiver, String requiredPermission) {
return sendInner(code, intent, resolvedType, finishedReceiver,
- requiredPermission, null, null, 0, 0, 0);
+ requiredPermission, null, null, 0, 0, 0, null);
}
int sendInner(int code, Intent intent, String resolvedType,
IIntentReceiver finishedReceiver, String requiredPermission,
IBinder resultTo, String resultWho, int requestCode,
- int flagsMask, int flagsValues) {
+ int flagsMask, int flagsValues, Bundle options) {
synchronized(owner) {
if (!canceled) {
sent = true;
@@ -213,7 +216,14 @@ class PendingIntentRecord extends IIntentSender.Stub {
boolean sendFinish = finishedReceiver != null;
switch (key.type) {
- case IActivityManager.INTENT_SENDER_ACTIVITY:
+ case ActivityManager.INTENT_SENDER_ACTIVITY:
+ if (options == null) {
+ options = key.options;
+ } else if (key.options != null) {
+ Bundle opts = new Bundle(key.options);
+ opts.putAll(options);
+ options = opts;
+ }
try {
if (key.allIntents != null && key.allIntents.length > 1) {
Intent[] allIntents = new Intent[key.allIntents.length];
@@ -227,22 +237,22 @@ class PendingIntentRecord extends IIntentSender.Stub {
allIntents[allIntents.length-1] = finalIntent;
allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
owner.startActivitiesInPackage(uid, allIntents,
- allResolvedTypes, resultTo);
+ allResolvedTypes, resultTo, options);
} else {
owner.startActivityInPackage(uid,
finalIntent, resolvedType,
- resultTo, resultWho, requestCode, false);
+ resultTo, resultWho, requestCode, 0, options);
}
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Unable to send startActivity intent", e);
}
break;
- case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
+ case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
key.activity.stack.sendActivityResultLocked(-1, key.activity,
key.who, key.requestCode, code, finalIntent);
break;
- case IActivityManager.INTENT_SENDER_BROADCAST:
+ case ActivityManager.INTENT_SENDER_BROADCAST:
try {
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
@@ -257,7 +267,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
"Unable to send startActivity intent", e);
}
break;
- case IActivityManager.INTENT_SENDER_SERVICE:
+ case ActivityManager.INTENT_SENDER_SERVICE:
try {
owner.startServiceInPackage(uid,
finalIntent, resolvedType);
@@ -281,7 +291,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
return 0;
}
}
- return IActivityManager.START_CANCELED;
+ return ActivityManager.START_CANCELED;
}
protected void finalize() throws Throwable {
@@ -320,7 +330,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
}
if (key.requestIntent != null) {
pw.print(prefix); pw.print("requestIntent=");
- pw.println(key.requestIntent.toShortString(false, true, true));
+ pw.println(key.requestIntent.toShortString(false, true, true, true));
}
if (sent || canceled) {
pw.print(prefix); pw.print("sent="); pw.print(sent);
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 2021e0d..ccc928f 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -183,16 +183,20 @@ public class ProviderMap {
r.dump(pw, " ");
} else {
pw.print(" * ");
- pw.print(r.name.toShortString());
- /*
- if (r.app != null) {
- pw.println(":");
- pw.print(" ");
- pw.println(r.app);
- } else {
- pw.println();
+ pw.println(r);
+ if (r.proc != null) {
+ pw.print(" proc=");
+ pw.println(r.proc);
+ }
+ if (r.launchingApp != null) {
+ pw.print(" launchingApp=");
+ pw.println(r.launchingApp);
+ }
+ if (r.clients.size() > 0 || r.externalProcessNoHandleCount > 0) {
+ pw.print(" "); pw.print(r.clients.size());
+ pw.print(" clients, "); pw.print(r.externalProcessNoHandleCount);
+ pw.println(" external handles");
}
- */
}
}
}
@@ -217,7 +221,7 @@ public class ProviderMap {
pw.println(" ");
pw.println(" Published content providers (by class):");
dumpProvidersByClassLocked(pw, dumpAll, mGlobalByClass);
- pw.println(" ");
+ pw.println("");
}
if (mProvidersByClassPerUser.size() > 1) {
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index daa3653..828eef7 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -106,7 +106,7 @@ class ServiceRecord extends Binder {
final boolean taskRemoved;
final int id;
final Intent intent;
- final int targetPermissionUid;
+ final ActivityManagerService.NeededUriGrants neededGrants;
long deliveredTime;
int deliveryCount;
int doneExecutingCount;
@@ -115,12 +115,12 @@ class ServiceRecord extends Binder {
String stringName; // caching of toString
StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent,
- int _targetPermissionUid) {
+ ActivityManagerService.NeededUriGrants _neededGrants) {
sr = _sr;
taskRemoved = _taskRemoved;
id = _id;
intent = _intent;
- targetPermissionUid = _targetPermissionUid;
+ neededGrants = _neededGrants;
}
UriPermissionOwner getUriPermissionsLocked() {
@@ -177,9 +177,9 @@ class ServiceRecord extends Binder {
pw.print(prefix); pw.print(" intent=");
if (si.intent != null) pw.println(si.intent.toString());
else pw.println("null");
- if (si.targetPermissionUid >= 0) {
- pw.print(prefix); pw.print(" targetPermissionUid=");
- pw.println(si.targetPermissionUid);
+ if (si.neededGrants != null) {
+ pw.print(prefix); pw.print(" neededGrants=");
+ pw.println(si.neededGrants);
}
if (si.uriPermissions != null) {
if (si.uriPermissions.readUriPermissions != null) {
@@ -196,7 +196,7 @@ class ServiceRecord extends Binder {
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("intent={");
- pw.print(intent.getIntent().toShortString(false, true, false));
+ pw.print(intent.getIntent().toShortString(false, true, false, true));
pw.println('}');
pw.print(prefix); pw.print("packageName="); pw.println(packageName);
pw.print(prefix); pw.print("processName="); pw.println(processName);
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 47ec218..e3ebcc6 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -39,7 +39,7 @@ class TaskRecord extends ThumbnailHolder {
boolean askedCompatMode;// Have asked the user about compat mode for this task.
String stringName; // caching of toString() result.
- int userId; // user for which this task was created
+ int userId; // user for which this task was created
TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
taskId = _taskId;
@@ -111,14 +111,14 @@ class TaskRecord extends ThumbnailHolder {
if (intent != null) {
StringBuilder sb = new StringBuilder(128);
sb.append(prefix); sb.append("intent={");
- intent.toShortString(sb, false, true, false);
+ intent.toShortString(sb, false, true, false, true);
sb.append('}');
pw.println(sb.toString());
}
if (affinityIntent != null) {
StringBuilder sb = new StringBuilder(128);
sb.append(prefix); sb.append("affinityIntent={");
- affinityIntent.toShortString(sb, false, true, false);
+ affinityIntent.toShortString(sb, false, true, false, true);
sb.append('}');
pw.println(sb.toString());
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 9573fda..88a0ccb 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -1215,6 +1215,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return retValue;
}
protected boolean turnOffUpstreamMobileConnection() {
+ // ignore pending renewal requests
+ ++mCurrentConnectionSequence;
if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
try {
mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
@@ -1304,6 +1306,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
turnOnUpstreamMobileConnection(upType);
+ } else if (upType != ConnectivityManager.TYPE_NONE) {
+ /* If we've found an active upstream connection that's not DUN/HIPRI
+ * we should stop any outstanding DUN/HIPRI start requests.
+ *
+ * If we found NONE we don't want to do this as we want any previous
+ * requests to keep trying to bring up something we can use.
+ */
+ turnOffUpstreamMobileConnection();
}
if (upType == ConnectivityManager.TYPE_NONE) {
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/input/InputApplicationHandle.java
index 1812f11..42c1052 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/input/InputApplicationHandle.java
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-package com.android.server.wm;
-
+package com.android.server.input;
/**
* Functions as a handle for an application that can receive input.
@@ -30,7 +29,7 @@ public final class InputApplicationHandle {
private int ptr;
// The window manager's application window token.
- public final AppWindowToken appWindowToken;
+ public final Object appWindowToken;
// Application name.
public String name;
@@ -40,7 +39,7 @@ public final class InputApplicationHandle {
private native void nativeDispose();
- public InputApplicationHandle(AppWindowToken appWindowToken) {
+ public InputApplicationHandle(Object appWindowToken) {
this.appWindowToken = appWindowToken;
}
diff --git a/services/java/com/android/server/wm/InputFilter.java b/services/java/com/android/server/input/InputFilter.java
index 8f0001a..2ce0a02 100644
--- a/services/java/com/android/server/wm/InputFilter.java
+++ b/services/java/com/android/server/input/InputFilter.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.server.wm;
+package com.android.server.input;
+
+import com.android.server.wm.WindowManagerService;
import android.os.Handler;
import android.os.Looper;
@@ -33,7 +35,7 @@ import android.view.WindowManagerPolicy;
* system's behavior changes as follows:
* <ul>
* <li>Input events are first delivered to the {@link WindowManagerPolicy}
- * interception methods before queueing as usual. This critical step takes care of managing
+ * interception methods before queuing as usual. This critical step takes care of managing
* the power state of the device and handling wake keys.</li>
* <li>Input events are then asynchronously delivered to the input filter's
* {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
@@ -79,7 +81,7 @@ import android.view.WindowManagerPolicy;
* {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag. The input filter may
* sometimes receive events that do not have this flag set. It should take note of
* the fact that the policy intends to drop the event, clean up its state, and
- * then send appropriate cancelation events to the dispatcher if needed.
+ * then send appropriate cancellation events to the dispatcher if needed.
* </p><p>
* For example, suppose the input filter is processing a gesture and one of the touch events
* it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set.
@@ -89,8 +91,8 @@ import android.view.WindowManagerPolicy;
* Corollary: Events that set sent to the dispatcher should usually include the
* {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag. Otherwise, they will be dropped!
* </p><p>
- * It may be prudent to disable automatic key repeating for synthetically generated
- * keys by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
+ * It may be prudent to disable automatic key repeating for synthetic key events
+ * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
* </p>
*/
public abstract class InputFilter {
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/input/InputManagerService.java
index 56c3519..b8cc65e 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-package com.android.server.wm;
+package com.android.server.input;
import com.android.internal.util.XmlUtils;
import com.android.server.Watchdog;
+import com.android.server.input.InputFilter.Host;
+import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
@@ -25,9 +27,14 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.hardware.input.IInputManager;
+import android.hardware.input.InputManager;
+import android.os.Binder;
import android.os.Environment;
+import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
+import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -44,6 +51,7 @@ import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
@@ -53,62 +61,65 @@ import java.util.ArrayList;
/*
* Wraps the C++ InputManager and provides its callbacks.
*/
-public class InputManager implements Watchdog.Monitor {
+public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor {
static final String TAG = "InputManager";
-
- private static final boolean DEBUG = false;
+ static final boolean DEBUG = false;
+
+ private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
+
+ // Pointer to native input manager service object.
+ private final int mPtr;
- private final Callbacks mCallbacks;
private final Context mContext;
- private final WindowManagerService mWindowManagerService;
-
- private static native void nativeInit(Context context,
- Callbacks callbacks, MessageQueue messageQueue);
- private static native void nativeStart();
- private static native void nativeSetDisplaySize(int displayId, int width, int height,
- int externalWidth, int externalHeight);
- private static native void nativeSetDisplayOrientation(int displayId, int rotation);
+ private final Callbacks mCallbacks;
+ private final Handler mHandler;
+
+ private static native int nativeInit(InputManagerService service,
+ Context context, MessageQueue messageQueue);
+ private static native void nativeStart(int ptr);
+ private static native void nativeSetDisplaySize(int ptr, int displayId,
+ int width, int height, int externalWidth, int externalHeight);
+ private static native void nativeSetDisplayOrientation(int ptr, int displayId, int rotation);
- private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
- int scanCode);
- private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
- int keyCode);
- private static native int nativeGetSwitchState(int deviceId, int sourceMask,
- int sw);
- private static native boolean nativeHasKeys(int deviceId, int sourceMask,
- int[] keyCodes, boolean[] keyExists);
- private static native void nativeRegisterInputChannel(InputChannel inputChannel,
+ private static native int nativeGetScanCodeState(int ptr,
+ int deviceId, int sourceMask, int scanCode);
+ private static native int nativeGetKeyCodeState(int ptr,
+ int deviceId, int sourceMask, int keyCode);
+ private static native int nativeGetSwitchState(int ptr,
+ int deviceId, int sourceMask, int sw);
+ private static native boolean nativeHasKeys(int ptr,
+ int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
+ private static native void nativeRegisterInputChannel(int ptr, InputChannel inputChannel,
InputWindowHandle inputWindowHandle, boolean monitor);
- private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
- private static native void nativeSetInputFilterEnabled(boolean enable);
- private static native int nativeInjectInputEvent(InputEvent event,
+ private static native void nativeUnregisterInputChannel(int ptr, InputChannel inputChannel);
+ private static native void nativeSetInputFilterEnabled(int ptr, boolean enable);
+ private static native int nativeInjectInputEvent(int ptr, InputEvent event,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags);
- private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles);
- private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
- private static native void nativeSetSystemUiVisibility(int visibility);
- private static native void nativeSetFocusedApplication(InputApplicationHandle application);
- private static native InputDevice nativeGetInputDevice(int deviceId);
- private static native void nativeGetInputConfiguration(Configuration configuration);
- private static native int[] nativeGetInputDeviceIds();
- private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
- InputChannel toChannel);
- private static native void nativeSetPointerSpeed(int speed);
- private static native void nativeSetShowTouches(boolean enabled);
- private static native String nativeDump();
- private static native void nativeMonitor();
-
+ private static native void nativeSetInputWindows(int ptr, InputWindowHandle[] windowHandles);
+ private static native void nativeSetInputDispatchMode(int ptr, boolean enabled, boolean frozen);
+ private static native void nativeSetSystemUiVisibility(int ptr, int visibility);
+ private static native void nativeSetFocusedApplication(int ptr,
+ InputApplicationHandle application);
+ private static native InputDevice nativeGetInputDevice(int ptr, int deviceId);
+ private static native void nativeGetInputConfiguration(int ptr, Configuration configuration);
+ private static native int[] nativeGetInputDeviceIds(int ptr);
+ private static native boolean nativeTransferTouchFocus(int ptr,
+ InputChannel fromChannel, InputChannel toChannel);
+ private static native void nativeSetPointerSpeed(int ptr, int speed);
+ private static native void nativeSetShowTouches(int ptr, boolean enabled);
+ private static native String nativeDump(int ptr);
+ private static native void nativeMonitor(int ptr);
+
// Input event injection constants defined in InputDispatcher.h.
- static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
- static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
- static final int INPUT_EVENT_INJECTION_FAILED = 2;
- static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
-
- // Input event injection synchronization modes defined in InputDispatcher.h
- static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
- static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
- static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
-
+ private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
+ private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
+ private static final int INPUT_EVENT_INJECTION_FAILED = 2;
+ private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
+
+ // Maximum number of milliseconds to wait for input event injection.
+ private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
+
// Key states (may be returned by queries about the current state of a
// particular key code, scan code or switch).
@@ -129,23 +140,21 @@ public class InputManager implements Watchdog.Monitor {
InputFilter mInputFilter;
InputFilterHost mInputFilterHost;
- public InputManager(Context context, WindowManagerService windowManagerService) {
+ public InputManagerService(Context context, Callbacks callbacks) {
this.mContext = context;
- this.mWindowManagerService = windowManagerService;
- this.mCallbacks = new Callbacks();
-
- Looper looper = windowManagerService.mH.getLooper();
+ this.mCallbacks = callbacks;
+ this.mHandler = new Handler();
Slog.i(TAG, "Initializing input manager");
- nativeInit(mContext, mCallbacks, looper.getQueue());
-
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
+ mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
public void start() {
Slog.i(TAG, "Starting input manager");
- nativeStart();
+ nativeStart(mPtr);
+
+ // Add ourself to the Watchdog monitors.
+ Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
@@ -164,7 +173,7 @@ public class InputManager implements Watchdog.Monitor {
Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height
+ " external size " + externalWidth + "x" + externalHeight);
}
- nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight);
+ nativeSetDisplaySize(mPtr, displayId, width, height, externalWidth, externalHeight);
}
public void setDisplayOrientation(int displayId, int rotation) {
@@ -175,7 +184,7 @@ public class InputManager implements Watchdog.Monitor {
if (DEBUG) {
Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
}
- nativeSetDisplayOrientation(displayId, rotation);
+ nativeSetDisplayOrientation(mPtr, displayId, rotation);
}
public void getInputConfiguration(Configuration config) {
@@ -183,9 +192,9 @@ public class InputManager implements Watchdog.Monitor {
throw new IllegalArgumentException("config must not be null.");
}
- nativeGetInputConfiguration(config);
+ nativeGetInputConfiguration(mPtr, config);
}
-
+
/**
* Gets the current state of a key or button by key code.
* @param deviceId The input device id, or -1 to consult all devices.
@@ -196,7 +205,7 @@ public class InputManager implements Watchdog.Monitor {
* @return The key state.
*/
public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
- return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
+ return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
}
/**
@@ -209,7 +218,7 @@ public class InputManager implements Watchdog.Monitor {
* @return The key state.
*/
public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
- return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
+ return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
}
/**
@@ -222,7 +231,7 @@ public class InputManager implements Watchdog.Monitor {
* @return The switch state.
*/
public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
- return nativeGetSwitchState(deviceId, sourceMask, switchCode);
+ return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
}
/**
@@ -237,6 +246,7 @@ public class InputManager implements Watchdog.Monitor {
* key codes.
* @return True if the lookup was successful, false otherwise.
*/
+ @Override
public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
if (keyCodes == null) {
throw new IllegalArgumentException("keyCodes must not be null.");
@@ -246,7 +256,7 @@ public class InputManager implements Watchdog.Monitor {
+ "least as large as keyCodes.");
}
- return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
+ return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
}
/**
@@ -260,7 +270,7 @@ public class InputManager implements Watchdog.Monitor {
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- nativeRegisterInputChannel(inputChannels[0], null, true);
+ nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
@@ -277,7 +287,7 @@ public class InputManager implements Watchdog.Monitor {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
+ nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
/**
@@ -289,7 +299,7 @@ public class InputManager implements Watchdog.Monitor {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- nativeUnregisterInputChannel(inputChannel);
+ nativeUnregisterInputChannel(mPtr, inputChannel);
}
/**
@@ -323,47 +333,46 @@ public class InputManager implements Watchdog.Monitor {
filter.install(mInputFilterHost);
}
- nativeSetInputFilterEnabled(filter != null);
+ nativeSetInputFilterEnabled(mPtr, filter != null);
}
}
- /**
- * Injects an input event into the event system on behalf of an application.
- * The synchronization mode determines whether the method blocks while waiting for
- * input injection to proceed.
- *
- * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and
- * is assumed always to be successful.
- *
- * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be
- * dispatched so that the input dispatcher can determine whether input event injection will
- * be permitted based on the current input focus. Does not wait for the input event to
- * finish processing.
- *
- * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to
- * be completely processed.
- *
- * @param event The event to inject.
- * @param injectorPid The pid of the injecting application.
- * @param injectorUid The uid of the injecting application.
- * @param syncMode The synchronization mode.
- * @param timeoutMillis The injection timeout in milliseconds.
- * @return One of the INPUT_EVENT_INJECTION_XXX constants.
- */
- public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid,
- int syncMode, int timeoutMillis) {
+ @Override
+ public boolean injectInputEvent(InputEvent event, int mode) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
- if (injectorPid < 0 || injectorUid < 0) {
- throw new IllegalArgumentException("injectorPid and injectorUid must not be negative.");
- }
- if (timeoutMillis <= 0) {
- throw new IllegalArgumentException("timeoutMillis must be positive");
+ if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
+ && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
+ && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
+ throw new IllegalArgumentException("mode is invalid");
}
- return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis,
- WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ final int result;
+ try {
+ result = nativeInjectInputEvent(mPtr, event, pid, uid, mode,
+ INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ switch (result) {
+ case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
+ Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
+ throw new SecurityException(
+ "Injecting to another application requires INJECT_EVENTS permission");
+ case INPUT_EVENT_INJECTION_SUCCEEDED:
+ return true;
+ case INPUT_EVENT_INJECTION_TIMED_OUT:
+ Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
+ return false;
+ case INPUT_EVENT_INJECTION_FAILED:
+ default:
+ Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
+ return false;
+ }
}
/**
@@ -371,32 +380,34 @@ public class InputManager implements Watchdog.Monitor {
* @param id The device id.
* @return The input device or null if not found.
*/
+ @Override
public InputDevice getInputDevice(int deviceId) {
- return nativeGetInputDevice(deviceId);
+ return nativeGetInputDevice(mPtr, deviceId);
}
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
*/
+ @Override
public int[] getInputDeviceIds() {
- return nativeGetInputDeviceIds();
+ return nativeGetInputDeviceIds(mPtr);
}
public void setInputWindows(InputWindowHandle[] windowHandles) {
- nativeSetInputWindows(windowHandles);
+ nativeSetInputWindows(mPtr, windowHandles);
}
public void setFocusedApplication(InputApplicationHandle application) {
- nativeSetFocusedApplication(application);
+ nativeSetFocusedApplication(mPtr, application);
}
public void setInputDispatchMode(boolean enabled, boolean frozen) {
- nativeSetInputDispatchMode(enabled, frozen);
+ nativeSetInputDispatchMode(mPtr, enabled, frozen);
}
public void setSystemUiVisibility(int visibility) {
- nativeSetSystemUiVisibility(visibility);
+ nativeSetSystemUiVisibility(mPtr, visibility);
}
/**
@@ -419,7 +430,7 @@ public class InputManager implements Watchdog.Monitor {
if (toChannel == null) {
throw new IllegalArgumentException("toChannel must not be null.");
}
- return nativeTransferTouchFocus(fromChannel, toChannel);
+ return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
}
/**
@@ -427,20 +438,31 @@ public class InputManager implements Watchdog.Monitor {
* @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest)
* where 0 is the default speed.
*/
- public void setPointerSpeed(int speed) {
- speed = Math.min(Math.max(speed, -7), 7);
- nativeSetPointerSpeed(speed);
+ @Override
+ public void tryPointerSpeed(int speed) {
+ if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
+ "tryPointerSpeed()")) {
+ throw new SecurityException("Requires SET_POINTER_SPEED permission");
+ }
+
+ setPointerSpeedUnchecked(speed);
}
public void updatePointerSpeedFromSettings() {
- int speed = getPointerSpeedSetting(0);
- setPointerSpeed(speed);
+ int speed = getPointerSpeedSetting();
+ setPointerSpeedUnchecked(speed);
+ }
+
+ private void setPointerSpeedUnchecked(int speed) {
+ speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
+ InputManager.MAX_POINTER_SPEED);
+ nativeSetPointerSpeed(mPtr, speed);
}
private void registerPointerSpeedSettingObserver() {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
- new ContentObserver(mWindowManagerService.mH) {
+ new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
updatePointerSpeedFromSettings();
@@ -448,8 +470,8 @@ public class InputManager implements Watchdog.Monitor {
});
}
- private int getPointerSpeedSetting(int defaultValue) {
- int speed = defaultValue;
+ private int getPointerSpeedSetting() {
+ int speed = InputManager.DEFAULT_POINTER_SPEED;
try {
speed = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.POINTER_SPEED);
@@ -460,13 +482,13 @@ public class InputManager implements Watchdog.Monitor {
public void updateShowTouchesFromSettings() {
int setting = getShowTouchesSetting(0);
- nativeSetShowTouches(setting != 0);
+ nativeSetShowTouches(mPtr, setting != 0);
}
private void registerShowTouchesSettingObserver() {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
- new ContentObserver(mWindowManagerService.mH) {
+ new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
updateShowTouchesFromSettings();
@@ -484,200 +506,238 @@ public class InputManager implements Watchdog.Monitor {
return result;
}
- public void dump(PrintWriter pw) {
- String dumpStr = nativeDump();
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump InputManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ pw.println("INPUT MANAGER (dumpsys input)\n");
+ String dumpStr = nativeDump(mPtr);
if (dumpStr != null) {
pw.println(dumpStr);
}
}
- // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
+ private boolean checkCallingPermission(String permission, String func) {
+ // Quick check: if the calling permission is me, it's all okay.
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return true;
+ }
+
+ if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ String msg = "Permission Denial: " + func + " from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + permission;
+ Slog.w(TAG, msg);
+ return false;
+ }
+
+ // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
public void monitor() {
synchronized (mInputFilterLock) { }
- nativeMonitor();
+ nativeMonitor(mPtr);
}
- private final class InputFilterHost implements InputFilter.Host {
- private boolean mDisconnected;
+ // Native callback.
+ private void notifyConfigurationChanged(long whenNanos) {
+ mCallbacks.notifyConfigurationChanged();
+ }
- public void disconnectLocked() {
- mDisconnected = true;
- }
+ // Native callback.
+ private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+ mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+ }
- public void sendInputEvent(InputEvent event, int policyFlags) {
- if (event == null) {
- throw new IllegalArgumentException("event must not be null");
- }
+ // Native callback.
+ private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ mCallbacks.notifyInputChannelBroken(inputWindowHandle);
+ }
- synchronized (mInputFilterLock) {
- if (!mDisconnected) {
- nativeInjectInputEvent(event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0,
- policyFlags | WindowManagerPolicy.FLAG_FILTERED);
- }
+ // Native callback.
+ private long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
+ return mCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
+ }
+
+ // Native callback.
+ final boolean filterInputEvent(InputEvent event, int policyFlags) {
+ synchronized (mInputFilterLock) {
+ if (mInputFilter != null) {
+ mInputFilter.filterInputEvent(event, policyFlags);
+ return false;
}
}
+ event.recycle();
+ return true;
}
- /*
- * Callbacks from native.
- */
- private final class Callbacks {
- static final String TAG = "InputManager-Callbacks";
-
- private static final boolean DEBUG_VIRTUAL_KEYS = false;
- private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
- private static final String CALIBRATION_DIR_PATH = "usr/idc/";
-
- @SuppressWarnings("unused")
- public void notifyConfigurationChanged(long whenNanos) {
- mWindowManagerService.mInputMonitor.notifyConfigurationChanged();
- }
-
- @SuppressWarnings("unused")
- public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
- mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
- }
-
- @SuppressWarnings("unused")
- public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
- mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
- }
-
- @SuppressWarnings("unused")
- public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle) {
- return mWindowManagerService.mInputMonitor.notifyANR(
- inputApplicationHandle, inputWindowHandle);
- }
+ // Native callback.
+ private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+ return mCallbacks.interceptKeyBeforeQueueing(
+ event, policyFlags, isScreenOn);
+ }
- @SuppressWarnings("unused")
- final boolean filterInputEvent(InputEvent event, int policyFlags) {
- synchronized (mInputFilterLock) {
- if (mInputFilter != null) {
- mInputFilter.filterInputEvent(event, policyFlags);
- return false;
- }
- }
- event.recycle();
- return true;
- }
+ // Native callback.
+ private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ return mCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+ }
- @SuppressWarnings("unused")
- public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
- return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
- event, policyFlags, isScreenOn);
- }
+ // Native callback.
+ private long interceptKeyBeforeDispatching(InputWindowHandle focus,
+ KeyEvent event, int policyFlags) {
+ return mCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
+ }
- @SuppressWarnings("unused")
- public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
- return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
- policyFlags);
- }
+ // Native callback.
+ private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+ KeyEvent event, int policyFlags) {
+ return mCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
+ }
- @SuppressWarnings("unused")
- public long interceptKeyBeforeDispatching(InputWindowHandle focus,
- KeyEvent event, int policyFlags) {
- return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
- focus, event, policyFlags);
- }
-
- @SuppressWarnings("unused")
- public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
- KeyEvent event, int policyFlags) {
- return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
- focus, event, policyFlags);
- }
-
- @SuppressWarnings("unused")
- public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
- return mContext.checkPermission(
- android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
- == PackageManager.PERMISSION_GRANTED;
- }
+ // Native callback.
+ private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
+ return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
+ injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
+ }
- @SuppressWarnings("unused")
- public int getVirtualKeyQuietTimeMillis() {
- return mContext.getResources().getInteger(
- com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
- }
+ // Native callback.
+ private int getVirtualKeyQuietTimeMillis() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
+ }
- @SuppressWarnings("unused")
- public String[] getExcludedDeviceNames() {
- ArrayList<String> names = new ArrayList<String>();
-
- // Read partner-provided list of excluded input devices
- XmlPullParser parser = null;
- // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
- File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
- FileReader confreader = null;
- try {
- confreader = new FileReader(confFile);
- parser = Xml.newPullParser();
- parser.setInput(confreader);
- XmlUtils.beginDocument(parser, "devices");
-
- while (true) {
- XmlUtils.nextElement(parser);
- if (!"device".equals(parser.getName())) {
- break;
- }
- String name = parser.getAttributeValue(null, "name");
- if (name != null) {
- names.add(name);
- }
+ // Native callback.
+ private String[] getExcludedDeviceNames() {
+ ArrayList<String> names = new ArrayList<String>();
+
+ // Read partner-provided list of excluded input devices
+ XmlPullParser parser = null;
+ // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+ File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
+ FileReader confreader = null;
+ try {
+ confreader = new FileReader(confFile);
+ parser = Xml.newPullParser();
+ parser.setInput(confreader);
+ XmlUtils.beginDocument(parser, "devices");
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (!"device".equals(parser.getName())) {
+ break;
+ }
+ String name = parser.getAttributeValue(null, "name");
+ if (name != null) {
+ names.add(name);
}
- } catch (FileNotFoundException e) {
- // It's ok if the file does not exist.
- } catch (Exception e) {
- Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
- } finally {
- try { if (confreader != null) confreader.close(); } catch (IOException e) { }
}
-
- return names.toArray(new String[names.size()]);
+ } catch (FileNotFoundException e) {
+ // It's ok if the file does not exist.
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
+ } finally {
+ try { if (confreader != null) confreader.close(); } catch (IOException e) { }
}
- @SuppressWarnings("unused")
- public int getKeyRepeatTimeout() {
- return ViewConfiguration.getKeyRepeatTimeout();
- }
+ return names.toArray(new String[names.size()]);
+ }
- @SuppressWarnings("unused")
- public int getKeyRepeatDelay() {
- return ViewConfiguration.getKeyRepeatDelay();
- }
+ // Native callback.
+ private int getKeyRepeatTimeout() {
+ return ViewConfiguration.getKeyRepeatTimeout();
+ }
- @SuppressWarnings("unused")
- public int getHoverTapTimeout() {
- return ViewConfiguration.getHoverTapTimeout();
- }
+ // Native callback.
+ private int getKeyRepeatDelay() {
+ return ViewConfiguration.getKeyRepeatDelay();
+ }
- @SuppressWarnings("unused")
- public int getHoverTapSlop() {
- return ViewConfiguration.getHoverTapSlop();
- }
+ // Native callback.
+ private int getHoverTapTimeout() {
+ return ViewConfiguration.getHoverTapTimeout();
+ }
- @SuppressWarnings("unused")
- public int getDoubleTapTimeout() {
- return ViewConfiguration.getDoubleTapTimeout();
- }
+ // Native callback.
+ private int getHoverTapSlop() {
+ return ViewConfiguration.getHoverTapSlop();
+ }
- @SuppressWarnings("unused")
- public int getLongPressTimeout() {
- return ViewConfiguration.getLongPressTimeout();
- }
+ // Native callback.
+ private int getDoubleTapTimeout() {
+ return ViewConfiguration.getDoubleTapTimeout();
+ }
+
+ // Native callback.
+ private int getLongPressTimeout() {
+ return ViewConfiguration.getLongPressTimeout();
+ }
- @SuppressWarnings("unused")
- public int getPointerLayer() {
- return mWindowManagerService.mPolicy.windowTypeToLayerLw(
- WindowManager.LayoutParams.TYPE_POINTER)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
+ // Native callback.
+ private int getPointerLayer() {
+ return mCallbacks.getPointerLayer();
+ }
+
+ // Native callback.
+ private PointerIcon getPointerIcon() {
+ return PointerIcon.getDefaultIcon(mContext);
+ }
+
+ /**
+ * Callback interface implemented by the Window Manager.
+ */
+ public interface Callbacks {
+ public void notifyConfigurationChanged();
+
+ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
+
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
+
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle);
+
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
+
+ public long interceptKeyBeforeDispatching(InputWindowHandle focus,
+ KeyEvent event, int policyFlags);
+
+ public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+ KeyEvent event, int policyFlags);
+
+ public int getPointerLayer();
+ }
+
+ /**
+ * Hosting interface for input filters to call back into the input manager.
+ */
+ private final class InputFilterHost implements InputFilter.Host {
+ private boolean mDisconnected;
+
+ public void disconnectLocked() {
+ mDisconnected = true;
}
- @SuppressWarnings("unused")
- public PointerIcon getPointerIcon() {
- return PointerIcon.getDefaultIcon(mContext);
+ public void sendInputEvent(InputEvent event, int policyFlags) {
+ if (event == null) {
+ throw new IllegalArgumentException("event must not be null");
+ }
+
+ synchronized (mInputFilterLock) {
+ if (!mDisconnected) {
+ nativeInjectInputEvent(mPtr, event, 0, 0,
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
+ policyFlags | WindowManagerPolicy.FLAG_FILTERED);
+ }
+ }
}
}
}
diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/input/InputWindowHandle.java
index 264877c..03d66af 100644
--- a/services/java/com/android/server/wm/InputWindowHandle.java
+++ b/services/java/com/android/server/input/InputWindowHandle.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.server.wm;
+package com.android.server.input;
import android.graphics.Region;
import android.view.InputChannel;
-import android.view.WindowManagerPolicy;
/**
* Functions as a handle for a window that can receive input.
@@ -35,7 +34,7 @@ public final class InputWindowHandle {
public final InputApplicationHandle inputApplicationHandle;
// The window manager's window state.
- public final WindowManagerPolicy.WindowState windowState;
+ public final Object windowState;
// The input channel associated with the window.
public InputChannel inputChannel;
@@ -91,7 +90,7 @@ public final class InputWindowHandle {
private native void nativeDispose();
public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
- WindowManagerPolicy.WindowState windowState) {
+ Object windowState) {
this.inputApplicationHandle = inputApplicationHandle;
this.windowState = windowState;
}
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index 2d6a148..1026a0d 100755
--- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java
+++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
@@ -202,7 +202,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
if (mDebugLogs.size() >= MAX_LENGTH_DEBUG_LOGS) {
mDebugLogs.poll();
}
- if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (DEBUG) {
Slog.d(TAG, country.toString());
}
mDebugLogs.add(country);
@@ -394,7 +394,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
private void notifyIfCountryChanged(final Country country, final Country detectedCountry) {
if (detectedCountry != null && mListener != null
&& (country == null || !country.equals(detectedCountry))) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (DEBUG) {
Slog.d(TAG, "" + country + " --> " + detectedCountry);
}
notifyListener(detectedCountry);
diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/java/com/android/server/net/NetworkIdentitySet.java
index af03fb3..397f9f4 100644
--- a/services/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/java/com/android/server/net/NetworkIdentitySet.java
@@ -21,7 +21,6 @@ import android.net.NetworkIdentity;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.net.ProtocolException;
import java.util.HashSet;
/**
@@ -33,48 +32,46 @@ import java.util.HashSet;
public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_ROAMING = 2;
+ private static final int VERSION_ADD_NETWORK_ID = 3;
public NetworkIdentitySet() {
}
public NetworkIdentitySet(DataInputStream in) throws IOException {
final int version = in.readInt();
- switch (version) {
- case VERSION_INIT: {
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final int ignoredVersion = in.readInt();
- final int type = in.readInt();
- final int subType = in.readInt();
- final String subscriberId = readOptionalString(in);
- add(new NetworkIdentity(type, subType, subscriberId, false));
- }
- break;
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ if (version <= VERSION_INIT) {
+ final int ignored = in.readInt();
}
- case VERSION_ADD_ROAMING: {
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final int type = in.readInt();
- final int subType = in.readInt();
- final String subscriberId = readOptionalString(in);
- final boolean roaming = in.readBoolean();
- add(new NetworkIdentity(type, subType, subscriberId, roaming));
- }
- break;
+ final int type = in.readInt();
+ final int subType = in.readInt();
+ final String subscriberId = readOptionalString(in);
+ final String networkId;
+ if (version >= VERSION_ADD_NETWORK_ID) {
+ networkId = readOptionalString(in);
+ } else {
+ networkId = null;
}
- default: {
- throw new ProtocolException("unexpected version: " + version);
+ final boolean roaming;
+ if (version >= VERSION_ADD_ROAMING) {
+ roaming = in.readBoolean();
+ } else {
+ roaming = false;
}
+
+ add(new NetworkIdentity(type, subType, subscriberId, networkId, false));
}
}
public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_ADD_ROAMING);
+ out.writeInt(VERSION_ADD_NETWORK_ID);
out.writeInt(size());
for (NetworkIdentity ident : this) {
out.writeInt(ident.getType());
out.writeInt(ident.getSubType());
writeOptionalString(out, ident.getSubscriberId());
+ writeOptionalString(out, ident.getNetworkId());
out.writeBoolean(ident.getRoaming());
}
}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index a890068..77addd6 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;
@@ -49,6 +48,7 @@ import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.telephony.TelephonyManager.SIM_STATE_READY;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
@@ -74,6 +74,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 +97,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;
@@ -112,6 +114,7 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Objects;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -156,6 +159,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
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;
+ private static final int VERSION_ADDED_NETWORK_ID = 9;
+ private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID;
// @VisibleForTesting
public static final int TYPE_WARNING = 0x1;
@@ -165,19 +173,24 @@ 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";
private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
+ private static final String ATTR_NETWORK_ID = "networkId";
private static final String ATTR_CYCLE_DAY = "cycleDay";
+ private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
private static final String ATTR_WARNING_BYTES = "warningBytes";
private static final String ATTR_LIMIT_BYTES = "limitBytes";
private static final String ATTR_LAST_SNOOZE = "lastSnooze";
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";
@@ -219,8 +232,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();
@@ -375,18 +388,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();
}
}
@@ -475,6 +496,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// ignore policies that aren't relevant to user
if (!isTemplateRelevant(policy.template)) continue;
+ if (!policy.hasCycle()) continue;
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
@@ -512,16 +534,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Test if given {@link NetworkTemplate} is relevant to user based on
- * current device state, such as when {@link #getActiveSubscriberId()}
- * matches. This is regardless of data connection status.
+ * current device state, such as when
+ * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
+ * data connection status.
*/
private boolean isTemplateRelevant(NetworkTemplate template) {
+ final TelephonyManager tele = TelephonyManager.from(mContext);
+
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
- // mobile templates are relevant when subscriberid is active
- return Objects.equal(getActiveSubscriberId(), template.getSubscriberId());
+ // mobile templates are relevant when SIM is ready and
+ // subscriberId matches.
+ if (tele.getSimState() == SIM_STATE_READY) {
+ return Objects.equal(tele.getSubscriberId(), template.getSubscriberId());
+ } else {
+ return false;
+ }
}
return true;
}
@@ -740,7 +770,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long currentTime = currentTimeMillis();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// shortcut when policy has no limit
- if (policy.limitBytes == LIMIT_DISABLED) {
+ if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
setNetworkTemplateEnabled(policy.template, true);
continue;
}
@@ -763,13 +793,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* for the given {@link NetworkTemplate}.
*/
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
+ final TelephonyManager tele = TelephonyManager.from(mContext);
+
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
// TODO: offer more granular control over radio states once
// 4965893 is available.
- if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) {
+ if (tele.getSimState() == SIM_STATE_READY
+ && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) {
setPolicyDataEnable(TYPE_MOBILE, enabled);
setPolicyDataEnable(TYPE_WIMAX, enabled);
}
@@ -842,9 +875,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (NetworkPolicy policy : mNetworkRules.keySet()) {
final String[] ifaces = mNetworkRules.get(policy);
- final long start = computeLastCycleBoundary(currentTime, policy);
- final long end = currentTime;
- final long totalBytes = getTotalBytes(policy.template, start, end);
+ final long start;
+ final long totalBytes;
+ if (policy.hasCycle()) {
+ start = computeLastCycleBoundary(currentTime, policy);
+ totalBytes = getTotalBytes(policy.template, start, currentTime);
+ } else {
+ start = Long.MAX_VALUE;
+ totalBytes = 0;
+ }
if (LOGD) {
Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
@@ -902,9 +941,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
if (mSuppressDefaultPolicy) return;
- final String subscriberId = getActiveSubscriberId();
+ final TelephonyManager tele = TelephonyManager.from(mContext);
+
+ // avoid creating policy when SIM isn't ready
+ if (tele.getSimState() != SIM_STATE_READY) return;
+
+ final String subscriberId = tele.getSubscriberId();
final NetworkIdentity probeIdent = new NetworkIdentity(
- TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
+ TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
@@ -922,13 +966,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
com.android.internal.R.integer.config_networkPolicyDefaultWarning)
* MB_IN_BYTES;
- final Time time = new Time(Time.TIMEZONE_UTC);
+ final Time time = new Time();
time.setToNow();
+
final int cycleDay = time.monthDay;
+ final String cycleTimezone = time.timezone;
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
- mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, warningBytes,
- LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true));
+ mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, cycleTimezone,
+ warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true));
writePolicyLocked();
}
}
@@ -938,7 +984,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 {
@@ -963,7 +1009,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} else if (TAG_NETWORK_POLICY.equals(tag)) {
final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
+ final String networkId;
+ if (version >= VERSION_ADDED_NETWORK_ID) {
+ networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
+ } else {
+ networkId = null;
+ }
final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
+ final String cycleTimezone;
+ if (version >= VERSION_ADDED_TIMEZONE) {
+ cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
+ } else {
+ cycleTimezone = Time.TIMEZONE_UTC;
+ }
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
final long lastLimitSnooze;
@@ -994,22 +1052,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);
+ networkTemplate, subscriberId, networkId);
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
- warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze,
- metered));
+ cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
+ lastLimitSnooze, metered, inferred));
- } else if (TAG_UID_POLICY.equals(tag)) {
+ } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) {
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) && version >= VERSION_SWITCH_APP_ID) {
+ 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");
+ }
}
}
}
@@ -1054,7 +1128,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
out.startDocument(null, true);
out.startTag(null, TAG_POLICY_LIST);
- writeIntAttribute(out, ATTR_VERSION, VERSION_SPLIT_SNOOZE);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
// write all known network policies
@@ -1067,27 +1141,33 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (subscriberId != null) {
out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
}
+ final String networkId = template.getNetworkId();
+ if (networkId != null) {
+ out.attribute(null, ATTR_NETWORK_ID, networkId);
+ }
writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
+ out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
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);
@@ -1102,24 +1182,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();
}
@@ -1127,11 +1207,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);
}
}
@@ -1271,7 +1351,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
policy = findPolicyForNetworkLocked(ident);
}
- if (policy == null) {
+ if (policy == null || !policy.hasCycle()) {
// missing policy means we can't derive useful quota info
return null;
}
@@ -1293,9 +1373,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
- protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " ");
+
final HashSet<String> argSet = new HashSet<String>();
for (String arg : args) {
argSet.add(arg);
@@ -1318,31 +1400,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.print("Restrict background: "); fout.println(mRestrictBackground);
fout.println("Network policies:");
+ fout.increaseIndent();
for (NetworkPolicy policy : mNetworkPolicy.values()) {
- fout.print(" "); fout.println(policy.toString());
+ fout.println(policy.toString());
}
+ fout.decreaseIndent();
- fout.println("Policy status for known UIDs:");
+ fout.println("Policy for apps:");
+ fout.increaseIndent();
+ 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();
+ }
+ fout.decreaseIndent();
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:");
+ fout.increaseIndent();
+ size = knownUids.size();
for (int i = 0; i < size; i++) {
final int uid = knownUids.keyAt(i);
- fout.print(" UID=");
+ 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) {
@@ -1361,6 +1450,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.println();
}
+ fout.decreaseIndent();
}
}
@@ -1432,7 +1522,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
@@ -1451,13 +1542,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;
}
@@ -1639,15 +1738,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private String getActiveSubscriberId() {
- final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- return telephony.getSubscriberId();
- }
-
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
- return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
+ return mNetworkStats.getNetworkTotalBytes(template, start, end);
} catch (RuntimeException e) {
Slog.w(TAG, "problem reading network stats: " + e);
return 0;
@@ -1703,6 +1796,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/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java
index 290bd2c..540f606 100644
--- a/services/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/java/com/android/server/net/NetworkStatsRecorder.java
@@ -221,6 +221,11 @@ public class NetworkStatsRecorder {
if (mLastSnapshot != null) {
mLastSnapshot = mLastSnapshot.withoutUid(uid);
}
+
+ final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
+ if (complete != null) {
+ complete.removeUid(uid);
+ }
}
/**
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 13c0640..f7ba329 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -26,6 +26,7 @@ import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
+import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -33,7 +34,7 @@ import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkTemplate.buildTemplateWifi;
+import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
@@ -69,6 +70,7 @@ import android.content.IntentFilter;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
import android.net.LinkProperties;
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
@@ -212,6 +214,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final HandlerThread mHandlerThread;
private final Handler mHandler;
+ private boolean mSystemReady;
+
public NetworkStatsService(
Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
@@ -250,6 +254,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
public void systemReady() {
+ mSystemReady = true;
+
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
return;
@@ -300,7 +306,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// watch for networkType changes that aren't broadcast through
// CONNECTIVITY_ACTION_IMMEDIATE above.
- mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
+ if (!COMBINE_SUBTYPE_ENABLED) {
+ mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
+ }
registerPollAlarmLocked();
registerGlobalAlert();
@@ -321,7 +329,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
- mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+ if (!COMBINE_SUBTYPE_ENABLED) {
+ mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+ }
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
@@ -336,6 +346,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mUidTagRecorder = null;
mDevStatsCached = null;
+
+ mSystemReady = false;
}
private void maybeUpgradeLegacyStatsLocked() {
@@ -401,40 +413,75 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@Override
- public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
- }
+ public INetworkStatsSession openSession() {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
- @Override
- public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
- return mDevStatsCached.getSummary(template, start, end);
- }
+ // return an IBinder which holds strong references to any loaded stats
+ // for its lifetime; when caller closes only weak references remain.
- @Override
- public NetworkStatsHistory getHistoryForUid(
- NetworkTemplate template, int uid, int set, int tag, int fields) {
- // TODO: transition to stats sessions to avoid WeakReferences
- if (tag == TAG_NONE) {
- return mUidRecorder.getOrLoadCompleteLocked().getHistory(
- template, uid, set, tag, fields);
- } else {
- return mUidTagRecorder.getOrLoadCompleteLocked().getHistory(
- template, uid, set, tag, fields);
- }
+ return new INetworkStatsSession.Stub() {
+ private NetworkStatsCollection mUidComplete;
+ private NetworkStatsCollection mUidTagComplete;
+
+ private NetworkStatsCollection getUidComplete() {
+ if (mUidComplete == null) {
+ mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
+ }
+ return mUidComplete;
+ }
+
+ private NetworkStatsCollection getUidTagComplete() {
+ if (mUidTagComplete == null) {
+ mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
+ }
+ return mUidTagComplete;
+ }
+
+ @Override
+ public NetworkStats getSummaryForNetwork(
+ NetworkTemplate template, long start, long end) {
+ return mDevStatsCached.getSummary(template, start, end);
+ }
+
+ @Override
+ public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
+ return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
+ }
+
+ @Override
+ public NetworkStats getSummaryForAllUid(
+ NetworkTemplate template, long start, long end, boolean includeTags) {
+ final NetworkStats stats = getUidComplete().getSummary(template, start, end);
+ if (includeTags) {
+ final NetworkStats tagStats = getUidTagComplete()
+ .getSummary(template, start, end);
+ stats.combineAllValues(tagStats);
+ }
+ return stats;
+ }
+
+ @Override
+ public NetworkStatsHistory getHistoryForUid(
+ NetworkTemplate template, int uid, int set, int tag, int fields) {
+ if (tag == TAG_NONE) {
+ return getUidComplete().getHistory(template, uid, set, tag, fields);
+ } else {
+ return getUidTagComplete().getHistory(template, uid, set, tag, fields);
+ }
+ }
+
+ @Override
+ public void close() {
+ mUidComplete = null;
+ mUidTagComplete = null;
+ }
+ };
}
@Override
- public NetworkStats getSummaryForAllUid(
- NetworkTemplate template, long start, long end, boolean includeTags) {
- // TODO: transition to stats sessions to avoid WeakReferences
- final NetworkStats stats = mUidRecorder.getOrLoadCompleteLocked().getSummary(
- template, start, end);
- if (includeTags) {
- final NetworkStats tagStats = mUidTagRecorder.getOrLoadCompleteLocked().getSummary(
- template, start, end);
- stats.combineAllValues(tagStats);
- }
- return stats;
+ public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ return mDevStatsCached.getSummary(template, start, end).getTotalBytes();
}
@Override
@@ -649,6 +696,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* {@link NetworkIdentitySet}.
*/
private void updateIfacesLocked() {
+ if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
// take one last stats snapshot before updating iface mapping. this
@@ -737,7 +785,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* {@link NetworkStatsHistory}.
*/
private void performPollLocked(int flags) {
+ if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
+
final long startRealtime = SystemClock.elapsedRealtime();
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
@@ -822,7 +872,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
trustedTime);
// collect wifi sample
- template = buildTemplateWifi();
+ template = buildTemplateWifiWildcard();
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
xtTotal = new NetworkStats.Entry();
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index e471a3f..1593707 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -20,6 +20,10 @@ 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_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.ENFORCEMENT_DEFAULT;
+import static android.content.pm.PackageManager.ENFORCEMENT_YES;
+import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
import static libcore.io.OsConstants.S_ISLNK;
import com.android.internal.app.IMediaContainerService;
@@ -130,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;
@@ -391,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;
@@ -400,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();
@@ -625,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;
@@ -669,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
@@ -731,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;
@@ -807,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);
}
}
@@ -908,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,
@@ -1074,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);
}
}
}
@@ -1132,6 +1147,27 @@ public class PackageManagerService extends IPackageManager.Stub {
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
: 0));
+ // Verify that all of the preferred activity components actually
+ // exist. It is possible for applications to be updated and at
+ // that point remove a previously declared activity component that
+ // had been set as a preferred activity. We try to clean this up
+ // the next time we encounter that preferred activity, but it is
+ // possible for the user flow to never be able to return to that
+ // situation so here we do a sanity check to make sure we haven't
+ // left any junk around.
+ ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
+ for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
+ if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
+ removed.add(pa);
+ }
+ }
+ for (int i=0; i<removed.size(); i++) {
+ PreferredActivity pa = removed.get(i);
+ Slog.w(TAG, "Removing dangling preferred activity: "
+ + pa.mPref.mComponent);
+ mSettings.mPreferredActivities.removeFilter(pa);
+ }
+
// can downgrade to reader
mSettings.writeLPr();
@@ -1155,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;
@@ -1209,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()) {
@@ -1473,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;
@@ -1526,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;
}
}
@@ -1552,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.
@@ -1627,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;
@@ -1654,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);
@@ -1670,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;
@@ -1733,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;
@@ -1752,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;
@@ -1838,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);
@@ -1851,6 +1932,9 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
+ if (!isPermissionEnforcedLocked(permName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
}
return PackageManager.PERMISSION_DENIED;
}
@@ -1869,6 +1953,9 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
+ if (!isPermissionEnforcedLocked(permName)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
}
return PackageManager.PERMISSION_DENIED;
}
@@ -1966,7 +2053,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!async) {
mSettings.writeLPr();
} else {
- scheduleWriteSettingsLocked();
+ scheduleWriteSettingsLocked();
}
}
return added;
@@ -2201,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) {
@@ -2232,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;
}
@@ -2243,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) {
@@ -2252,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
@@ -2286,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) {
@@ -2295,31 +2385,40 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, " null");
}
}
- if (ai != null) {
- for (int j=0; j<N; j++) {
- final ResolveInfo ri = query.get(j);
- if (!ri.activityInfo.applicationInfo.packageName
- .equals(ai.applicationInfo.packageName)) {
- continue;
- }
- if (!ri.activityInfo.name.equals(ai.name)) {
- continue;
- }
-
- // Okay we found a previously set preferred app.
- // If the result set is different from when this
- // was created, we need to clear it and re-ask the
- // user their preference.
- if (!pa.mPref.sameSet(query, priority)) {
- Slog.i(TAG, "Result set changed, dropping preferred activity for "
- + intent + " type " + resolvedType);
- mSettings.mPreferredActivities.removeFilter(pa);
- return null;
- }
+ if (ai == null) {
+ // This previously registered preferred activity
+ // component is no longer known. Most likely an update
+ // to the app was installed and in the new version this
+ // component no longer exists. Clean it up by removing
+ // it from the preferred activities list, and skip it.
+ Slog.w(TAG, "Removing dangling preferred activity: "
+ + pa.mPref.mComponent);
+ mSettings.mPreferredActivities.removeFilter(pa);
+ continue;
+ }
+ for (int j=0; j<N; j++) {
+ final ResolveInfo ri = query.get(j);
+ if (!ri.activityInfo.applicationInfo.packageName
+ .equals(ai.applicationInfo.packageName)) {
+ continue;
+ }
+ if (!ri.activityInfo.name.equals(ai.name)) {
+ continue;
+ }
- // Yay!
- return ri;
+ // Okay we found a previously set preferred app.
+ // If the result set is different from when this
+ // was created, we need to clear it and re-ask the
+ // user their preference.
+ if (!pa.mPref.sameSet(query, priority)) {
+ Slog.i(TAG, "Result set changed, dropping preferred activity for "
+ + intent + " type " + resolvedType);
+ mSettings.mPreferredActivities.removeFilter(pa);
+ return null;
}
+
+ // Yay!
+ return ri;
}
}
}
@@ -2327,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) {
@@ -2339,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;
@@ -2352,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);
@@ -2412,7 +2515,7 @@ public class PackageManagerService extends IPackageManager.Stub {
ri = resolveIntent(
sintent,
specificTypes != null ? specificTypes[i] : null,
- flags);
+ flags, userId);
if (ri == null) {
continue;
}
@@ -2423,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;
}
@@ -2532,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) {
@@ -2542,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;
@@ -2555,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,
@@ -2577,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) {
@@ -2587,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;
@@ -2600,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;
}
@@ -2629,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) {
@@ -2649,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);
}
}
@@ -2671,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;
@@ -2688,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);
}
}
@@ -2725,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));
}
}
}
@@ -2739,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;
}
}
@@ -2762,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));
}
}
}
@@ -2784,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));
}
}
}
@@ -3442,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)) {
@@ -3549,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: "
@@ -3570,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) {
@@ -3612,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();
@@ -4036,8 +4171,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// writer
synchronized (mPackages) {
- clearPackagePreferredActivitiesLPw(pkg.packageName);
-
mPackages.remove(pkg.applicationInfo.packageName);
if (pkg.mPath != null) {
mAppDirs.remove(pkg.mPath);
@@ -4442,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;
}
@@ -4471,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) {
@@ -4536,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;
@@ -4544,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;
@@ -4557,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;
@@ -4567,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;
}
@@ -4622,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;
}
@@ -4651,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) {
@@ -4711,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;
@@ -4719,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;
@@ -4732,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;
@@ -4743,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;
}
@@ -4835,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) {
}
}
@@ -4994,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);
}
}
@@ -5597,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 "
@@ -7024,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.
@@ -7061,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));
}
}
}
@@ -7100,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);
}
@@ -7118,16 +7279,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
}
}
- }
- // remove from preferred activities.
- ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
- for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
- if (pa.mPref.mComponent.getPackageName().equals(deletedPs.name)) {
- removed.add(pa);
- }
- }
- for (PreferredActivity pa : removed) {
- mSettings.mPreferredActivities.removeFilter(pa);
+ clearPackagePreferredActivitiesLPw(deletedPs.name);
}
}
// can downgrade to reader
@@ -7287,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
@@ -7318,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;
@@ -7350,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);
@@ -7364,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 {
@@ -7382,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;
@@ -7400,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: "
@@ -7569,17 +7725,27 @@ public class PackageManagerService extends IPackageManager.Stub {
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
}
+ ArrayList<PreferredActivity> removed = null;
Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
String action = filter.getAction(0);
String category = filter.getCategory(0);
while (it.hasNext()) {
PreferredActivity pa = it.next();
if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
- it.remove();
- Log.i(TAG, "Removed preferred activity " + pa.mPref.mComponent + ":");
+ if (removed == null) {
+ removed = new ArrayList<PreferredActivity>();
+ }
+ removed.add(pa);
+ Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
}
}
+ if (removed != null) {
+ for (int i=0; i<removed.size(); i++) {
+ PreferredActivity pa = removed.get(i);
+ mSettings.mPreferredActivities.removeFilter(pa);
+ }
+ }
addPreferredActivity(filter, match, set, activity);
}
}
@@ -7611,16 +7777,25 @@ public class PackageManagerService extends IPackageManager.Stub {
}
boolean clearPackagePreferredActivitiesLPw(String packageName) {
- boolean changed = false;
+ ArrayList<PreferredActivity> removed = null;
Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
while (it.hasNext()) {
PreferredActivity pa = it.next();
if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
- it.remove();
- changed = true;
+ if (removed == null) {
+ removed = new ArrayList<PreferredActivity>();
+ }
+ removed.add(pa);
}
}
- return changed;
+ if (removed != null) {
+ for (int i=0; i<removed.size(); i++) {
+ PreferredActivity pa = removed.get(i);
+ mSettings.mPreferredActivities.removeFilter(pa);
+ }
+ return true;
+ }
+ return false;
}
public int getPreferredActivities(List<IntentFilter> outFilters,
@@ -7647,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
@@ -7671,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);
@@ -7690,35 +7870,47 @@ 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.
+ PackageParser.Package pkg = pkgSetting.pkg;
+ if (pkg == null || !pkg.hasComponentClassName(className)) {
+ if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
+ throw new IllegalArgumentException("Component class " + className
+ + " does not exist in " + packageName);
+ } else {
+ Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
+ + className + " does not exist in " + packageName);
+ }
+ }
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;
@@ -7727,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) {
@@ -7776,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);
}
}
}
@@ -7800,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);
}
}
@@ -8014,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(")");
}
@@ -8279,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;
}
@@ -8332,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);
}
}
@@ -8756,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;
}
@@ -8765,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(
@@ -8783,7 +9011,74 @@ 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
+ public void setPermissionEnforcement(String permission, int enforcement) {
+ mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
+ if (READ_EXTERNAL_STORAGE.equals(permission)) {
+ synchronized (mPackages) {
+ 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 {
+ throw new IllegalArgumentException("No selective enforcement for " + permission);
+ }
+ }
+
+ @Override
+ public int getPermissionEnforcement(String permission) {
+ mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
+ if (READ_EXTERNAL_STORAGE.equals(permission)) {
+ synchronized (mPackages) {
+ return mSettings.mReadExternalStorageEnforcement;
+ }
+ } else {
+ throw new IllegalArgumentException("No selective enforcement for " + permission);
+ }
+ }
+
+ private boolean isPermissionEnforcedLocked(String permission) {
+ if (READ_EXTERNAL_STORAGE.equals(permission)) {
+ switch (mSettings.mReadExternalStorageEnforcement) {
+ case ENFORCEMENT_DEFAULT:
+ return false;
+ case ENFORCEMENT_YES:
+ return true;
+ }
+ }
+
+ return true;
}
}
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 5da6ac9..bb7f4fc 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -20,6 +20,7 @@ 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_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.ENFORCEMENT_DEFAULT;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
@@ -31,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;
@@ -39,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;
@@ -62,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;
@@ -74,6 +80,20 @@ final class Settings {
private static final boolean DEBUG_STOPPED = false;
+ 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;
@@ -91,6 +111,8 @@ final class Settings {
int mInternalSdkPlatform;
int mExternalSdkPlatform;
+ int mReadExternalStorageEnforcement = ENFORCEMENT_DEFAULT;
+
/** Device identity for the purpose of package verification. */
private VerifierDeviceIdentity mVerifierDeviceIdentity;
@@ -147,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,
@@ -248,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;
}
@@ -257,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,
@@ -266,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;
@@ -317,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) {
@@ -329,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
@@ -372,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;
@@ -398,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);
@@ -414,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;
@@ -444,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
@@ -469,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);
}
@@ -496,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!");
@@ -506,7 +549,7 @@ final class Settings {
sharedUser.packages.add(p);
p.sharedUser = sharedUser;
- p.userId = sharedUser.userId;
+ p.appId = sharedUser.userId;
}
}
@@ -571,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;
@@ -585,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);
@@ -652,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();
@@ -705,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);
@@ -714,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
@@ -751,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;
}
@@ -790,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 {
@@ -811,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);
@@ -864,13 +1132,20 @@ final class Settings {
serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
serializer.endTag(null, "last-platform-version");
-
+
if (mVerifierDeviceIdentity != null) {
serializer.startTag(null, "verifier");
serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
serializer.endTag(null, "verifier");
}
+ if (mReadExternalStorageEnforcement != ENFORCEMENT_DEFAULT) {
+ serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
+ serializer.attribute(
+ null, ATTR_ENFORCEMENT, Integer.toString(mReadExternalStorageEnforcement));
+ serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
+ }
+
serializer.startTag(null, "permission-trees");
for (BasePermission bp : mPermissionTrees.values()) {
writePermissionLPr(serializer, bp);
@@ -893,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");
@@ -918,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");
}
}
@@ -1003,8 +1278,7 @@ final class Settings {
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
- writeStoppedLPr();
-
+ writeAllUsersPackageRestrictionsLPr();
return;
} catch(XmlPullParserException e) {
@@ -1017,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();
@@ -1026,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);
}
@@ -1042,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) {
@@ -1059,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);
}
}
}
@@ -1072,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);
}
@@ -1089,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");
}
@@ -1114,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");
}
@@ -1146,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));
@@ -1167,7 +1421,7 @@ final class Settings {
}
}
}
- serializer.endTag(null, "item");
+ serializer.endTag(null, TAG_ITEM);
}
}
@@ -1185,7 +1439,7 @@ final class Settings {
return ret;
}
- boolean readLPw() {
+ boolean readLPw(List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -1260,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);
}
@@ -1291,6 +1545,12 @@ final class Settings {
Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
+ e.getMessage());
}
+ } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
+ final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
+ try {
+ mReadExternalStorageEnforcement = Integer.parseInt(enforcement);
+ } catch (NumberFormatException e) {
+ }
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+ parser.getName());
@@ -1347,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");
@@ -1388,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) {
@@ -1425,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");
@@ -1478,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;
@@ -1522,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");
@@ -1653,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
@@ -1672,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")) {
@@ -1692,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")) {
@@ -1712,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
@@ -1723,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"
@@ -1740,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
@@ -1751,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"
@@ -1768,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"))) {
@@ -1840,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 {
@@ -1868,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);
@@ -1886,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...
@@ -1921,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;
@@ -1960,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) {
@@ -1997,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) {
@@ -2077,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);
@@ -2150,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) {
@@ -2215,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=");
@@ -2225,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..1bd15f6 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;
@@ -59,6 +60,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
+import java.util.Scanner;
/**
* UsbDeviceManager manages USB state in device mode.
@@ -80,6 +82,8 @@ public class UsbDeviceManager {
"/sys/class/android_usb/android0/f_mass_storage/lun/file";
private static final String RNDIS_ETH_ADDR_PATH =
"/sys/class/android_usb/android0/f_rndis/ethaddr";
+ private static final String AUDIO_SOURCE_PCM_PATH =
+ "/sys/class/android_usb/android0/f_audio_source/pcm";
private static final int MSG_UPDATE_STATE = 0;
private static final int MSG_ENABLE_ADB = 1;
@@ -104,6 +108,7 @@ public class UsbDeviceManager {
private final boolean mHasUsbAccessory;
private boolean mUseUsbNotification;
private boolean mAdbEnabled;
+ private boolean mAudioSourceEnabled;
private Map<String, List<Pair<String, String>>> mOemModeMap;
private class AdbSettingsObserver extends ContentObserver {
@@ -206,6 +211,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 +230,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];
@@ -284,6 +295,8 @@ public class UsbDeviceManager {
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
+ mAudioSourceEnabled = containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_AUDIO_SOURCE);
// Upgrade step for previous versions that used persist.service.adb.enable
String value = SystemProperties.get("persist.service.adb.enable", "");
@@ -365,11 +378,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;
@@ -501,6 +510,28 @@ public class UsbDeviceManager {
mContext.sendStickyBroadcast(intent);
}
+ private void updateAudioSourceFunction(boolean enabled) {
+ // send a sticky broadcast containing current USB state
+ Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra("state", (enabled ? 1 : 0));
+ if (enabled) {
+ try {
+ Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
+ int card = scanner.nextInt();
+ int device = scanner.nextInt();
+ intent.putExtra("card", card);
+ intent.putExtra("device", device);
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "could not open audio source PCM file", e);
+ }
+ }
+
+ mContext.sendStickyBroadcast(intent);
+ mAudioSourceEnabled = enabled;
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -520,6 +551,11 @@ public class UsbDeviceManager {
}
if (mBootCompleted) {
updateUsbState();
+ boolean audioSourceEnabled = containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ if (audioSourceEnabled != mAudioSourceEnabled) {
+ updateAudioSourceFunction(audioSourceEnabled);
+ }
}
break;
case MSG_ENABLE_ADB:
@@ -540,6 +576,7 @@ public class UsbDeviceManager {
if (mCurrentAccessory != null) {
mSettingsManager.accessoryAttached(mCurrentAccessory);
}
+ updateAudioSourceFunction(mAudioSourceEnabled);
break;
}
}
@@ -588,6 +625,7 @@ public class UsbDeviceManager {
notification.defaults = 0; // please be quiet
notification.sound = null;
notification.vibrate = null;
+ notification.priority = Notification.PRIORITY_MIN;
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
@@ -621,6 +659,7 @@ public class UsbDeviceManager {
notification.defaults = 0; // please be quiet
notification.sound = null;
notification.vibrate = null;
+ notification.priority = Notification.PRIORITY_MIN;
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
new file mode 100644
index 0000000..c3b5465
--- /dev/null
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -0,0 +1,301 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import android.graphics.Matrix;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+
+/**
+ *
+ */
+public class AppWindowAnimator {
+
+ final AppWindowToken mAppToken;
+ final WindowManagerService mService;
+ final WindowAnimator mAnimator;
+
+ boolean animating;
+ Animation animation;
+ boolean animInitialized;
+ boolean hasTransformation;
+ final Transformation transformation = new Transformation();
+
+ // Have we been asked to have this token keep the screen frozen?
+ // Protect with mAnimator.
+ boolean freezingScreen;
+
+ // Offset to the window of all layers in the token, for use by
+ // AppWindowToken animations.
+ int animLayerAdjustment;
+
+ // Special surface for thumbnail animation.
+ Surface thumbnail;
+ int thumbnailTransactionSeq;
+ int thumbnailX;
+ int thumbnailY;
+ int thumbnailLayer;
+ Animation thumbnailAnimation;
+ final Transformation thumbnailTransformation = new Transformation();
+
+ public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) {
+ mService = service;
+ mAppToken = atoken;
+ mAnimator = service.mAnimator;
+ }
+
+ 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(mService.mTransitionAnimationScale);
+ int zorder = anim.getZAdjustment();
+ int adj = 0;
+ if (zorder == Animation.ZORDER_TOP) {
+ adj = WindowManagerService.TYPE_LAYER_OFFSET;
+ } else if (zorder == Animation.ZORDER_BOTTOM) {
+ adj = -WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+
+ if (animLayerAdjustment != adj) {
+ animLayerAdjustment = adj;
+ updateLayers();
+ }
+ // Start out animation gone if window is gone, or visible if window is visible.
+ transformation.clear();
+ transformation.setAlpha(mAppToken.reportedVisible ? 1 : 0);
+ hasTransformation = true;
+ }
+
+ public void setDummyAnimation() {
+ if (animation == null) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Setting dummy animation in " + this);
+ animation = WindowManagerService.sDummyAnimation;
+ animInitialized = false;
+ }
+ }
+
+ public void clearAnimation() {
+ 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 = mAppToken.allAppWindows.size();
+ final int adj = animLayerAdjustment;
+ thumbnailLayer = -1;
+ for (int i=0; i<N; i++) {
+ final WindowState w = mAppToken.allAppWindows.get(i);
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ winAnimator.mAnimLayer = w.mLayer + adj;
+ if (winAnimator.mAnimLayer > thumbnailLayer) {
+ thumbnailLayer = winAnimator.mAnimLayer;
+ }
+ if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
+ + winAnimator.mAnimLayer);
+ if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
+ mService.setInputMethodAnimLayerAdjustment(adj);
+ }
+ if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
+ mService.setWallpaperAnimLayerAdjustmentLocked(adj);
+ }
+ }
+ }
+
+ private void stepThumbnailAnimation(long currentTime) {
+ thumbnailTransformation.clear();
+ thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
+ thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
+ final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null
+ && mAnimator.mScreenRotationAnimation.isAnimating();
+ if (screenAnimation) {
+ thumbnailTransformation.postCompose(
+ mAnimator.mScreenRotationAnimation.getEnterTransformation());
+ }
+ // cache often used attributes locally
+ final float tmpFloats[] = mService.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) {
+ return false;
+ }
+ transformation.clear();
+ final boolean more = animation.getTransformation(currentTime, transformation);
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Stepped animation in " + this +
+ ": more=" + more + ", xform=" + transformation);
+ if (!more) {
+ animation = null;
+ clearThumbnail();
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Finished animation in " + this +
+ " @ " + currentTime);
+ }
+ hasTransformation = more;
+ return more;
+ }
+
+ // This must be called while inside a transaction.
+ boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+ if (mService.okToDisplay()) {
+ // We will run animations as long as the display isn't frozen.
+
+ if (animation == WindowManagerService.sDummyAnimation) {
+ // This guy is going to animate, but not yet. For now count
+ // it as not animating for purposes of scheduling transactions;
+ // when it is really time to animate, this will be set to
+ // a real animation and the next call will execute normally.
+ return false;
+ }
+
+ if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
+ && animation != null) {
+ if (!animating) {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Starting animation in " + this +
+ " @ " + currentTime + ": dw=" + dw + " dh=" + dh
+ + " scale=" + mService.mTransitionAnimationScale
+ + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
+ if (!animInitialized) {
+ animation.initialize(dw, dh, dw, dh);
+ }
+ animation.setStartTime(currentTime);
+ animating = true;
+ if (thumbnail != null) {
+ thumbnail.show();
+ thumbnailAnimation.setStartTime(currentTime);
+ }
+ }
+ if (stepAnimation(currentTime)) {
+ // animation isn't over, step any thumbnail and that's
+ // it for now.
+ if (thumbnail != null) {
+ stepThumbnailAnimation(currentTime);
+ }
+ return true;
+ }
+ }
+ } else if (animation != null) {
+ // If the display is frozen, and there is a pending animation,
+ // clear it and make sure we run the cleanup code.
+ animating = true;
+ animation = null;
+ }
+
+ hasTransformation = false;
+
+ if (!animating && animation == null) {
+ return false;
+ }
+
+ mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges);
+ }
+
+ clearAnimation();
+ animating = false;
+ if (animLayerAdjustment != 0) {
+ animLayerAdjustment = 0;
+ updateLayers();
+ }
+ if (mService.mInputMethodTarget != null
+ && mService.mInputMethodTarget.mAppToken == mAppToken) {
+ mService.moveInputMethodWindowsIfNeededLocked(true);
+ }
+
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Animation done in " + this
+ + ": reportedVisible=" + mAppToken.reportedVisible);
+
+ transformation.clear();
+
+ final int N = mAppToken.windows.size();
+ for (int i=0; i<N; i++) {
+ mAppToken.windows.get(i).mWinAnimator.finishExit();
+ }
+ mAppToken.updateReportedVisibilityLocked();
+
+ return false;
+ }
+
+ boolean showAllWindowsLocked() {
+ boolean isAnimating = false;
+ final int NW = mAppToken.allAppWindows.size();
+ for (int i=0; i<NW; i++) {
+ WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+ "performing show on: " + winAnimator);
+ winAnimator.performShowLocked();
+ isAnimating |= winAnimator.isAnimating();
+ }
+ return isAnimating;
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ if (freezingScreen) {
+ pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
+ }
+ if (animating || animation != null) {
+ pw.print(prefix); pw.print("animating="); pw.print(animating);
+ pw.print(" animation="); pw.println(animation);
+ }
+ if (hasTransformation) {
+ pw.print(prefix); pw.print("XForm: ");
+ transformation.printShortString(pw);
+ pw.println();
+ }
+ if (animLayerAdjustment != 0) {
+ pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+ }
+ 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());
+ }
+ }
+}
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 0e3d20a..bf35154 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
import android.content.pm.ActivityInfo;
@@ -27,8 +28,6 @@ import android.util.Slog;
import android.view.IApplicationToken;
import android.view.View;
import android.view.WindowManager;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -44,18 +43,22 @@ class AppWindowToken extends WindowToken {
// All of the windows and child windows that are included in this
// application token. Note this list is NOT sorted!
final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
+ final AppWindowAnimator mAppAnimator;
+
+ final WindowAnimator mAnimator;
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;
@@ -83,18 +86,6 @@ class AppWindowToken extends WindowToken {
// Set to true when the token has been removed from the window mgr.
boolean removed;
- // Have we been asked to have this token keep the screen frozen?
- boolean freezingScreen;
-
- boolean animating;
- Animation animation;
- boolean hasTransformation;
- final Transformation transformation = new Transformation();
-
- // Offset to the window of all layers in the token, for use by
- // AppWindowToken animations.
- int animLayerAdjustment;
-
// Information about an application starting window if displayed.
StartingData startingData;
WindowState startingWindow;
@@ -112,60 +103,8 @@ class AppWindowToken extends WindowToken {
appWindowToken = this;
appToken = _token;
mInputApplicationHandle = new InputApplicationHandle(this);
- lastTransactionSequence = service.mTransactionSequence-1;
- }
-
- public void setAnimation(Animation anim) {
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
- animation = anim;
- animating = false;
- anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(service.mTransitionAnimationScale);
- int zorder = anim.getZAdjustment();
- int adj = 0;
- if (zorder == Animation.ZORDER_TOP) {
- adj = WindowManagerService.TYPE_LAYER_OFFSET;
- } else if (zorder == Animation.ZORDER_BOTTOM) {
- adj = -WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
- if (animLayerAdjustment != adj) {
- animLayerAdjustment = adj;
- updateLayers();
- }
- }
-
- public void setDummyAnimation() {
- if (animation == null) {
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Setting dummy animation in " + this);
- animation = WindowManagerService.sDummyAnimation;
- }
- }
-
- public void clearAnimation() {
- if (animation != null) {
- animation = null;
- animating = true;
- }
- }
-
- void updateLayers() {
- final int N = allAppWindows.size();
- final int adj = animLayerAdjustment;
- for (int i=0; i<N; i++) {
- WindowState w = allAppWindows.get(i);
- w.mAnimLayer = w.mLayer + adj;
- if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
- + w.mAnimLayer);
- if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
- service.setInputMethodAnimLayerAdjustment(adj);
- }
- if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
- service.setWallpaperAnimLayerAdjustmentLocked(adj);
- }
- }
+ mAnimator = service.mAnimator;
+ mAppAnimator = new AppWindowAnimator(_service, this);
}
void sendAppVisibilityToClients() {
@@ -185,94 +124,6 @@ class AppWindowToken extends WindowToken {
}
}
- void showAllWindowsLocked() {
- 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();
- }
- }
-
- // This must be called while inside a transaction.
- boolean stepAnimationLocked(long currentTime, int dw, int dh) {
- if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
- // We will run animations as long as the display isn't frozen.
-
- if (animation == WindowManagerService.sDummyAnimation) {
- // This guy is going to animate, but not yet. For now count
- // it as not animating for purposes of scheduling transactions;
- // when it is really time to animate, this will be set to
- // a real animation and the next call will execute normally.
- return false;
- }
-
- if ((allDrawn || animating || startingDisplayed) && animation != null) {
- if (!animating) {
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Starting animation in " + this +
- " @ " + currentTime + ": dw=" + dw + " dh=" + dh
- + " scale=" + service.mTransitionAnimationScale
- + " allDrawn=" + allDrawn + " animating=" + animating);
- animation.initialize(dw, dh, dw, dh);
- animation.setStartTime(currentTime);
- animating = true;
- }
- transformation.clear();
- final boolean more = animation.getTransformation(
- currentTime, transformation);
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Stepped animation in " + this +
- ": more=" + more + ", xform=" + transformation);
- if (more) {
- // we're done!
- hasTransformation = true;
- return true;
- }
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Finished animation in " + this +
- " @ " + currentTime);
- animation = null;
- }
- } else if (animation != null) {
- // If the display is frozen, and there is a pending animation,
- // clear it and make sure we run the cleanup code.
- animating = true;
- animation = null;
- }
-
- hasTransformation = false;
-
- if (!animating) {
- return false;
- }
-
- clearAnimation();
- animating = false;
- if (animLayerAdjustment != 0) {
- animLayerAdjustment = 0;
- updateLayers();
- }
- if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
- service.moveInputMethodWindowsIfNeededLocked(true);
- }
-
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Animation done in " + this
- + ": reportedVisible=" + reportedVisible);
-
- transformation.clear();
-
- final int N = windows.size();
- for (int i=0; i<N; i++) {
- windows.get(i).finishExit();
- }
- updateReportedVisibilityLocked();
-
- return false;
- }
-
void updateReportedVisibilityLocked() {
if (appToken == null) {
return;
@@ -283,7 +134,8 @@ class AppWindowToken extends WindowToken {
int numDrawn = 0;
boolean nowGone = true;
- if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+ "Update reported visibility: " + this);
final int N = allAppWindows.size();
for (int i=0; i<N; i++) {
WindowState win = allAppWindows.get(i);
@@ -296,27 +148,26 @@ 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
+ Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mWinAnimator.mSurface
+ " pv=" + win.mPolicyVisibility
- + " dp=" + win.mDrawPending
- + " cdp=" + win.mCommitDrawPending
+ + " mDrawState=" + win.mWinAnimator.mDrawState
+ " ah=" + win.mAttachedHidden
+ " 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;
}
}
@@ -369,6 +220,7 @@ class AppWindowToken extends WindowToken {
return null;
}
+ @Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
if (appToken != null) {
@@ -385,9 +237,8 @@ class AppWindowToken extends WindowToken {
pw.print(" willBeHidden="); pw.print(willBeHidden);
pw.print(" reportedDrawn="); pw.print(reportedDrawn);
pw.print(" reportedVisible="); pw.println(reportedVisible);
- if (paused || freezingScreen) {
- pw.print(prefix); pw.print("paused="); pw.print(paused);
- pw.print(" freezingScreen="); pw.println(freezingScreen);
+ if (paused) {
+ pw.print(prefix); pw.print("paused="); pw.println(paused);
}
if (numInterestingWindows != 0 || numDrawnWindows != 0
|| inPendingTransaction || allDrawn) {
@@ -397,18 +248,6 @@ class AppWindowToken extends WindowToken {
pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
pw.print(" allDrawn="); pw.println(allDrawn);
}
- if (animating || animation != null) {
- pw.print(prefix); pw.print("animating="); pw.print(animating);
- pw.print(" animation="); pw.println(animation);
- }
- if (hasTransformation) {
- pw.print(prefix); pw.print("XForm: ");
- transformation.printShortString(pw);
- pw.println();
- }
- if (animLayerAdjustment != 0) {
- pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
- }
if (startingData != null || removed || firstWindowDrawn) {
pw.print(prefix); pw.print("startingData="); pw.print(startingData);
pw.print(" removed="); pw.print(removed);
@@ -434,4 +273,4 @@ class AppWindowToken extends WindowToken {
}
return stringName;
}
-} \ No newline at end of file
+}
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 10e294b..c915932 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import java.io.PrintWriter;
+
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -30,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",
@@ -43,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) {
@@ -56,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] + ","
@@ -72,14 +76,31 @@ public class BlackFrame {
}
}
+ final Rect mOuterRect;
+ final Rect mInnerRect;
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
+ pw.print(" / Inner: "); mInnerRect.printShortString(pw);
+ pw.println();
+ for (int i=0; i<mBlackSurfaces.length; i++) {
+ BlackSurface bs = mBlackSurfaces[i];
+ pw.print(prefix); pw.print("#"); pw.print(i);
+ pw.print(": "); pw.print(bs.surface);
+ pw.print(" left="); pw.print(bs.left);
+ pw.print(" top="); pw.println(bs.top);
+ }
+ }
+
public BlackFrame(SurfaceSession session, Rect outer, Rect inner,
int layer) throws Surface.OutOfResourcesException {
boolean success = false;
+ mOuterRect = new Rect(outer);
+ mInnerRect = new Rect(inner);
try {
if (outer.top < inner.top) {
mBlackSurfaces[0] = new BlackSurface(session, layer,
@@ -138,6 +159,14 @@ public class BlackFrame {
}
}
+ public void setAlpha(float alpha) {
+ for (int i=0; i<mBlackSurfaces.length; i++) {
+ if (mBlackSurfaces[i] != null) {
+ mBlackSurfaces[i].surface.setAlpha(alpha);
+ }
+ }
+ }
+
public void clearMatrix() {
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index a9d4e01..b08c864 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -41,14 +41,14 @@ class DimAnimator {
DimAnimator (SurfaceSession session) {
if (mDimSurface == null) {
- if (WindowManagerService.SHOW_TRANSACTIONS ||
- WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " DIM " + mDimSurface + ": CREATE");
try {
mDimSurface = new Surface(session, 0,
"DimAnimator",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+ " DIM " + mDimSurface + ": CREATE");
mDimSurface.setAlpha(0.0f);
} catch (Exception e) {
Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
@@ -57,12 +57,17 @@ class DimAnimator {
}
/**
- * Show the dim surface.
+ * Set's the dim surface's layer and update dim parameters that will be used in
+ * {@link #updateSurface} after all windows are examined.
*/
- void show(int dw, int dh) {
+ void updateParameters(final Resources res, final Parameters params, final long currentTime) {
+ final int dw = params.mDimWidth;
+ final int dh = params.mDimHeight;
+ final WindowStateAnimator winAnimator = params.mDimWinAnimator;
+ final float target = params.mDimTarget;
if (!mDimShown) {
- if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
- dw + "x" + dh + ")");
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+ " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")");
mDimShown = true;
try {
mLastDimWidth = dw;
@@ -78,31 +83,24 @@ class DimAnimator {
mLastDimHeight = dh;
mDimSurface.setSize(dw, dh);
}
- }
- /**
- * Set's the dim surface's layer and update dim parameters that will be used in
- * {@link updateSurface} after all windows are examined.
- */
- void updateParameters(Resources res, WindowState w, long currentTime) {
- mDimSurface.setLayer(w.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
+ mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
- final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
- if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface
- + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target);
if (mDimTargetAlpha != target) {
// 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 = (winAnimator.mAnimating && winAnimator.mAnimation != null)
+ ? winAnimator.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 +128,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;
@@ -190,4 +186,18 @@ class DimAnimator {
pw.print(" delta="); pw.print(mDimDeltaPerMs);
pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
}
+
+ static class Parameters {
+ final WindowStateAnimator mDimWinAnimator;
+ final int mDimWidth;
+ final int mDimHeight;
+ final float mDimTarget;
+ Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth,
+ final int dimHeight, final float dimTarget) {
+ mDimWinAnimator = dimWinAnimator;
+ mDimWidth = dimWidth;
+ mDimHeight = dimHeight;
+ mDimTarget = dimTarget;
+ }
+ }
} \ No newline at end of file
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
index dc6cc0d..c1dbb36 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -32,14 +32,14 @@ class DimSurface {
DimSurface(SurfaceSession session) {
if (mDimSurface == null) {
- if (WindowManagerService.SHOW_TRANSACTIONS ||
- WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " DIM " + mDimSurface + ": CREATE");
try {
mDimSurface = new Surface(session, 0,
"DimSurface",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+ " DIM " + mDimSurface + ": CREATE");
mDimSurface.setAlpha(0.0f);
} catch (Exception e) {
Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index a19035a..b2cf3e0 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
import com.android.server.wm.WindowManagerService.H;
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java
index 121ce18..2527f46 100644
--- a/services/java/com/android/server/wm/FakeWindowImpl.java
+++ b/services/java/com/android/server/wm/FakeWindowImpl.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
+
import android.os.Looper;
import android.os.Process;
import android.util.Slog;
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index fb74d27..c28cfa2 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,10 @@
package com.android.server.wm;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
+
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
@@ -27,7 +31,7 @@ import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Arrays;
-final class InputMonitor {
+final class InputMonitor implements InputManagerService.Callbacks {
private final WindowManagerService mService;
// Current window with input focus for keys and other non-touch events. May be null.
@@ -93,7 +97,7 @@ final class InputMonitor {
}
if (appWindowToken == null && inputApplicationHandle != null) {
- appWindowToken = inputApplicationHandle.appWindowToken;
+ appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
if (appWindowToken != null) {
Slog.i(WindowManagerService.TAG,
"Input event dispatching timed out sending to application "
@@ -301,7 +305,14 @@ final class InputMonitor {
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
}
-
+
+ /* Callback to get pointer layer. */
+ public int getPointerLayer() {
+ return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_POINTER)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+
/* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 04a039f..e460f7f 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -33,15 +33,17 @@ class ScreenRotationAnimation {
static final String TAG = "ScreenRotationAnimation";
static final boolean DEBUG_STATE = false;
static final boolean DEBUG_TRANSFORMS = false;
+ static final boolean USE_CUSTOM_BLACK_FRAME = false;
static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
final Context mContext;
Surface mSurface;
- BlackFrame mBlackFrame;
+ BlackFrame mCustomBlackFrame;
+ BlackFrame mExitingBlackFrame;
+ BlackFrame mEnteringBlackFrame;
int mWidth, mHeight;
- int mSnapshotRotation;
int mSnapshotDeltaRotation;
int mOriginalRotation;
int mOriginalWidth, mOriginalHeight;
@@ -59,6 +61,8 @@ class ScreenRotationAnimation {
final Transformation mStartExitTransformation = new Transformation();
Animation mStartEnterAnimation;
final Transformation mStartEnterTransformation = new Transformation();
+ Animation mStartFrameAnimation;
+ final Transformation mStartFrameTransformation = new Transformation();
// The finishing animation for the exiting and entering elements. This
// animation needs to undo the transformation of the starting animation.
@@ -68,6 +72,8 @@ class ScreenRotationAnimation {
final Transformation mFinishExitTransformation = new Transformation();
Animation mFinishEnterAnimation;
final Transformation mFinishEnterTransformation = new Transformation();
+ Animation mFinishFrameAnimation;
+ final Transformation mFinishFrameTransformation = new Transformation();
// The current active animation to move from the old to the new rotated
// state. Which animation is run here will depend on the old and new
@@ -76,6 +82,8 @@ class ScreenRotationAnimation {
final Transformation mRotateExitTransformation = new Transformation();
Animation mRotateEnterAnimation;
final Transformation mRotateEnterTransformation = new Transformation();
+ Animation mRotateFrameAnimation;
+ final Transformation mRotateFrameTransformation = new Transformation();
// A previously running rotate animation. This will be used if we need
// to switch to a new rotation before finishing the previous one.
@@ -83,28 +91,54 @@ class ScreenRotationAnimation {
final Transformation mLastRotateExitTransformation = new Transformation();
Animation mLastRotateEnterAnimation;
final Transformation mLastRotateEnterTransformation = new Transformation();
+ Animation mLastRotateFrameAnimation;
+ final Transformation mLastRotateFrameTransformation = new Transformation();
// Complete transformations being applied.
final Transformation mExitTransformation = new Transformation();
final Transformation mEnterTransformation = new Transformation();
+ final Transformation mFrameTransformation = new Transformation();
boolean mStarted;
boolean mAnimRunning;
boolean mFinishAnimReady;
long mFinishAnimStartTime;
+ final Matrix mFrameInitialMatrix = new Matrix();
final Matrix mSnapshotInitialMatrix = new Matrix();
final Matrix mSnapshotFinalMatrix = new Matrix();
+ final Matrix mExitFrameFinalMatrix = new Matrix();
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
+ private boolean mMoreRotateEnter;
+ private boolean mMoreRotateExit;
+ private boolean mMoreRotateFrame;
+ private boolean mMoreFinishEnter;
+ private boolean mMoreFinishExit;
+ private boolean mMoreFinishFrame;
+ private boolean mMoreStartEnter;
+ private boolean mMoreStartExit;
+ private boolean mMoreStartFrame;
public void printTo(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
pw.print(" mWidth="); pw.print(mWidth);
pw.print(" mHeight="); pw.println(mHeight);
- pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
- pw.print(prefix); pw.print("mSnapshotRotation="); pw.print(mSnapshotRotation);
- pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ pw.print(prefix); pw.print("mCustomBlackFrame="); pw.println(mCustomBlackFrame);
+ if (mCustomBlackFrame != null) {
+ mCustomBlackFrame.printTo(prefix + " ", pw);
+ }
+ }
+ pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame);
+ if (mExitingBlackFrame != null) {
+ mExitingBlackFrame.printTo(prefix + " ", pw);
+ }
+ pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame);
+ if (mEnteringBlackFrame != null) {
+ mEnteringBlackFrame.printTo(prefix + " ", pw);
+ }
+ pw.print(prefix); pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
pw.print(" mCurRotation="); pw.println(mCurRotation);
pw.print(prefix); pw.print("mOriginalRotation="); pw.print(mOriginalRotation);
pw.print(" mOriginalWidth="); pw.print(mOriginalWidth);
@@ -117,25 +151,36 @@ class ScreenRotationAnimation {
pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mStartFrameAnimation="); pw.print(mStartFrameAnimation);
+ pw.print(" "); mStartFrameTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mFinishFrameAnimation="); pw.print(mFinishFrameAnimation);
+ pw.print(" "); mFinishFrameTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
- pw.print(prefix); pw.print("mLastRotateExitAnimation=");
- pw.print(mLastRotateExitAnimation);
- pw.print(" "); mLastRotateExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mRotateFrameAnimation="); pw.print(mRotateFrameAnimation);
+ pw.print(" "); mRotateFrameTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mExitTransformation=");
mExitTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mEnterTransformation=");
mEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mFrameTransformation=");
+ mEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mFrameInitialMatrix=");
+ mFrameInitialMatrix.printShortString(pw);
+ pw.println();
pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
mSnapshotInitialMatrix.printShortString(pw);
pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
pw.println();
+ pw.print(prefix); pw.print("mExitFrameFinalMatrix=");
+ mExitFrameFinalMatrix.printShortString(pw);
+ pw.println();
}
public ScreenRotationAnimation(Context context, SurfaceSession session,
@@ -143,7 +188,6 @@ class ScreenRotationAnimation {
mContext = context;
// Screenshot does NOT include rotation!
- mSnapshotRotation = 0;
if (originalRotation == Surface.ROTATION_90
|| originalRotation == Surface.ROTATION_270) {
mWidth = originalHeight;
@@ -167,7 +211,7 @@ class ScreenRotationAnimation {
try {
mSurface = new Surface(session, 0, "FreezeSurface",
-1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
- if (mSurface == null || !mSurface.isValid()) {
+ if (!mSurface.isValid()) {
// Screenshot failed, punt.
mSurface = null;
return;
@@ -251,7 +295,7 @@ class ScreenRotationAnimation {
// Compute the transformation matrix that must be applied
// to the snapshot to make it stay in the same original position
// with the current screen rotation.
- int delta = deltaRotation(rotation, mSnapshotRotation);
+ int delta = deltaRotation(rotation, Surface.ROTATION_0);
createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
@@ -293,10 +337,18 @@ class ScreenRotationAnimation {
com.android.internal.R.anim.screen_rotate_start_exit);
mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_start_enter);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mStartFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_start_frame);
+ }
mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_finish_exit);
mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_finish_enter);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_finish_frame);
+ }
}
if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
@@ -309,27 +361,47 @@ class ScreenRotationAnimation {
com.android.internal.R.anim.screen_rotate_0_exit);
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_0_enter);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_0_frame);
+ }
break;
case Surface.ROTATION_90:
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_plus_90_exit);
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_plus_90_enter);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_plus_90_frame);
+ }
break;
case Surface.ROTATION_180:
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_180_exit);
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_180_enter);
+ mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_180_frame);
break;
case Surface.ROTATION_270:
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_minus_90_exit);
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.screen_rotate_minus_90_enter);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+ com.android.internal.R.anim.screen_rotate_minus_90_frame);
+ }
break;
}
+ // Compute partial steps between original and final sizes. These
+ // are used for the dimensions of the exiting and entering elements,
+ // so they are never stretched too significantly.
+ final int halfWidth = (finalWidth + mOriginalWidth) / 2;
+ final int halfHeight = (finalHeight + mOriginalHeight) / 2;
+
// Initialize the animations. This is a hack, redefining what "parent"
// means to allow supplying the last and next size. In this definition
// "%p" is the original (let's call it "previous") size, and "%" is the
@@ -337,16 +409,26 @@ class ScreenRotationAnimation {
if (firstStart) {
if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
mStartEnterAnimation.initialize(finalWidth, finalHeight,
- mOriginalWidth, mOriginalHeight);
- mStartExitAnimation.initialize(finalWidth, finalHeight,
+ halfWidth, halfHeight);
+ mStartExitAnimation.initialize(halfWidth, halfHeight,
mOriginalWidth, mOriginalHeight);
mFinishEnterAnimation.initialize(finalWidth, finalHeight,
+ halfWidth, halfHeight);
+ mFinishExitAnimation.initialize(halfWidth, halfHeight,
mOriginalWidth, mOriginalHeight);
- mFinishExitAnimation.initialize(finalWidth, finalHeight,
- mOriginalWidth, mOriginalHeight);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mStartFrameAnimation.initialize(finalWidth, finalHeight,
+ mOriginalWidth, mOriginalHeight);
+ mFinishFrameAnimation.initialize(finalWidth, finalHeight,
+ mOriginalWidth, mOriginalHeight);
+ }
}
mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth,
+ mOriginalHeight);
+ }
mAnimRunning = false;
mFinishAnimReady = false;
mFinishAnimStartTime = -1;
@@ -360,22 +442,93 @@ class ScreenRotationAnimation {
mFinishExitAnimation.scaleCurrentDuration(animationScale);
mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
mFinishEnterAnimation.scaleCurrentDuration(animationScale);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mStartFrameAnimation.restrictDuration(maxAnimationDuration);
+ mStartFrameAnimation.scaleCurrentDuration(animationScale);
+ mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
+ mFinishFrameAnimation.scaleCurrentDuration(animationScale);
+ }
}
mRotateExitAnimation.restrictDuration(maxAnimationDuration);
mRotateExitAnimation.scaleCurrentDuration(animationScale);
mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
mRotateEnterAnimation.scaleCurrentDuration(animationScale);
+ if (USE_CUSTOM_BLACK_FRAME) {
+ mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
+ mRotateFrameAnimation.scaleCurrentDuration(animationScale);
+ }
+
+ if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
+ if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+ WindowManagerService.TAG,
+ ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
+ Surface.openTransaction();
+
+ // Compute the transformation matrix that must be applied
+ // the the black frame to make it stay in the initial position
+ // before the new screen rotation. This is different than the
+ // snapshot transformation because the snapshot is always based
+ // of the native orientation of the screen, not the orientation
+ // we were last in.
+ createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
+
+ try {
+ Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
+ mOriginalWidth*2, mOriginalHeight*2);
+ Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
+ mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3);
+ mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(TAG, "Unable to allocate black surface", e);
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+ WindowManagerService.TAG,
+ "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
+ }
+ }
+
+ if (mExitingBlackFrame == null) {
+ if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+ WindowManagerService.TAG,
+ ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
+ Surface.openTransaction();
+
+ // Compute the transformation matrix that must be applied
+ // the the black frame to make it stay in the initial position
+ // before the new screen rotation. This is different than the
+ // snapshot transformation because the snapshot is always based
+ // of the native orientation of the screen, not the orientation
+ // we were last in.
+ createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
+
+ try {
+ Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
+ mOriginalWidth*2, mOriginalHeight*2);
+ Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
+ mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2);
+ mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(TAG, "Unable to allocate black surface", e);
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+ WindowManagerService.TAG,
+ "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
+ }
+ }
- if (mBlackFrame == null) {
+ if (false && mEnteringBlackFrame == null) {
if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
WindowManagerService.TAG,
">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
Surface.openTransaction();
try {
- Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2);
+ Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
+ finalWidth*2, finalHeight*2);
Rect inner = new Rect(0, 0, finalWidth, finalHeight);
- mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
+ mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
@@ -420,9 +573,17 @@ class ScreenRotationAnimation {
mSurface.destroy();
mSurface = null;
}
- if (mBlackFrame != null) {
- mBlackFrame.kill();
- mBlackFrame = null;
+ if (mCustomBlackFrame != null) {
+ mCustomBlackFrame.kill();
+ mCustomBlackFrame = null;
+ }
+ if (mExitingBlackFrame != null) {
+ mExitingBlackFrame.kill();
+ mExitingBlackFrame = null;
+ }
+ if (mEnteringBlackFrame != null) {
+ mEnteringBlackFrame.kill();
+ mEnteringBlackFrame = null;
}
if (mStartExitAnimation != null) {
mStartExitAnimation.cancel();
@@ -432,13 +593,21 @@ class ScreenRotationAnimation {
mStartEnterAnimation.cancel();
mStartEnterAnimation = null;
}
+ if (mStartFrameAnimation != null) {
+ mStartFrameAnimation.cancel();
+ mStartFrameAnimation = null;
+ }
if (mFinishExitAnimation != null) {
mFinishExitAnimation.cancel();
mFinishExitAnimation = null;
}
- if (mStartEnterAnimation != null) {
- mStartEnterAnimation.cancel();
- mStartEnterAnimation = null;
+ if (mFinishEnterAnimation != null) {
+ mFinishEnterAnimation.cancel();
+ mFinishEnterAnimation = null;
+ }
+ if (mFinishFrameAnimation != null) {
+ mFinishFrameAnimation.cancel();
+ mFinishFrameAnimation = null;
}
if (mRotateExitAnimation != null) {
mRotateExitAnimation.cancel();
@@ -448,132 +617,146 @@ class ScreenRotationAnimation {
mRotateEnterAnimation.cancel();
mRotateEnterAnimation = null;
}
+ if (mRotateFrameAnimation != null) {
+ mRotateFrameAnimation.cancel();
+ mRotateFrameAnimation = null;
+ }
}
public boolean isAnimating() {
return mStartEnterAnimation != null || mStartExitAnimation != null
- && mFinishEnterAnimation != null || mFinishExitAnimation != null
- && mRotateEnterAnimation != null || mRotateExitAnimation != null;
+ || mStartFrameAnimation != null
+ || mFinishEnterAnimation != null || mFinishExitAnimation != null
+ || mFinishFrameAnimation != null
+ || mRotateEnterAnimation != null || mRotateExitAnimation != null
+ || mRotateFrameAnimation != null;
}
- public boolean stepAnimation(long now) {
- if (!isAnimating()) {
- if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
- return false;
- }
-
- if (!mAnimRunning) {
- if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
- if (mStartEnterAnimation != null) {
- mStartEnterAnimation.setStartTime(now);
- }
- if (mStartExitAnimation != null) {
- mStartExitAnimation.setStartTime(now);
- }
- if (mFinishEnterAnimation != null) {
- mFinishEnterAnimation.setStartTime(0);
- }
- if (mFinishExitAnimation != null) {
- mFinishExitAnimation.setStartTime(0);
- }
- if (mRotateEnterAnimation != null) {
- mRotateEnterAnimation.setStartTime(now);
- }
- if (mRotateExitAnimation != null) {
- mRotateExitAnimation.setStartTime(now);
- }
- mAnimRunning = true;
- }
+ private boolean stepAnimation(long now) {
if (mFinishAnimReady && mFinishAnimStartTime < 0) {
if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
mFinishAnimStartTime = now;
}
- // If the start animation is no longer running, we want to keep its
- // transformation intact until the finish animation also completes.
-
- boolean moreStartExit = false;
+ mMoreStartExit = false;
if (mStartExitAnimation != null) {
- mStartExitTransformation.clear();
- moreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
+ mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
- if (!moreStartExit) {
- if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
- mStartExitAnimation.cancel();
- mStartExitAnimation = null;
- }
}
- boolean moreStartEnter = false;
+ mMoreStartEnter = false;
if (mStartEnterAnimation != null) {
- mStartEnterTransformation.clear();
- moreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
+ mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
- if (!moreStartEnter) {
- if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
- mStartEnterAnimation.cancel();
- mStartEnterAnimation = null;
- }
+ }
+
+ mMoreStartFrame = false;
+ if (mStartFrameAnimation != null) {
+ mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation);
+ if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation);
}
long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
- mFinishExitTransformation.clear();
- boolean moreFinishExit = false;
+ mMoreFinishExit = false;
if (mFinishExitAnimation != null) {
- moreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
+ mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
- if (!moreStartExit && !moreFinishExit) {
- if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
- mStartExitTransformation.clear();
- mFinishExitAnimation.cancel();
- mFinishExitAnimation = null;
- mFinishExitTransformation.clear();
- }
}
- mFinishEnterTransformation.clear();
- boolean moreFinishEnter = false;
+ mMoreFinishEnter = false;
if (mFinishEnterAnimation != null) {
- moreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
+ mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
- if (!moreStartEnter && !moreFinishEnter) {
- if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
- mStartEnterTransformation.clear();
- mFinishEnterAnimation.cancel();
- mFinishEnterAnimation = null;
- mFinishEnterTransformation.clear();
- }
}
- mRotateExitTransformation.clear();
- boolean moreRotateExit = false;
- if (mRotateExitAnimation != null) {
- moreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
- if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
+ mMoreFinishFrame = false;
+ if (mFinishFrameAnimation != null) {
+ mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation);
+ if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation);
}
- if (!moreFinishExit && !moreRotateExit) {
- if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
- mRotateExitAnimation.cancel();
- mRotateExitAnimation = null;
- mRotateExitTransformation.clear();
+ mMoreRotateExit = false;
+ if (mRotateExitAnimation != null) {
+ mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
+ if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
}
- mRotateEnterTransformation.clear();
- boolean moreRotateEnter = false;
+ mMoreRotateEnter = false;
if (mRotateEnterAnimation != null) {
- moreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
+ mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
}
- if (!moreFinishEnter && !moreRotateEnter) {
- if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
- mRotateEnterAnimation.cancel();
- mRotateEnterAnimation = null;
- mRotateEnterTransformation.clear();
+ mMoreRotateFrame = false;
+ if (mRotateFrameAnimation != null) {
+ mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation);
+ if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation);
+ }
+
+ if (!mMoreStartExit && !mMoreRotateExit && !mMoreFinishExit) {
+ if (mStartExitAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!");
+ mStartExitAnimation.cancel();
+ mStartExitAnimation = null;
+ mStartExitTransformation.clear();
+ }
+ if (mFinishExitAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!");
+ mFinishExitAnimation.cancel();
+ mFinishExitAnimation = null;
+ mFinishExitTransformation.clear();
+ }
+ if (mRotateExitAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!");
+ mRotateExitAnimation.cancel();
+ mRotateExitAnimation = null;
+ mRotateExitTransformation.clear();
+ }
+ }
+
+ if (!mMoreStartEnter && !mMoreRotateEnter && !mMoreFinishEnter) {
+ if (mStartEnterAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!");
+ mStartEnterAnimation.cancel();
+ mStartEnterAnimation = null;
+ mStartEnterTransformation.clear();
+ }
+ if (mFinishEnterAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!");
+ mFinishEnterAnimation.cancel();
+ mFinishEnterAnimation = null;
+ mFinishEnterTransformation.clear();
+ }
+ if (mRotateEnterAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!");
+ mRotateEnterAnimation.cancel();
+ mRotateEnterAnimation = null;
+ mRotateEnterTransformation.clear();
+ }
+ }
+
+ if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) {
+ if (mStartFrameAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!");
+ mStartFrameAnimation.cancel();
+ mStartFrameAnimation = null;
+ mStartFrameTransformation.clear();
+ }
+ if (mFinishFrameAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!");
+ mFinishFrameAnimation.cancel();
+ mFinishFrameAnimation = null;
+ mFinishFrameTransformation.clear();
+ }
+ if (mRotateFrameAnimation != null) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!");
+ mRotateFrameAnimation.cancel();
+ mRotateFrameAnimation = null;
+ mRotateFrameTransformation.clear();
+ }
}
mExitTransformation.set(mRotateExitTransformation);
@@ -587,33 +770,109 @@ class ScreenRotationAnimation {
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
- if (!moreStartExit && !moreFinishExit && !moreRotateExit) {
- if (mSurface != null) {
+ if (USE_CUSTOM_BLACK_FRAME) {
+ //mFrameTransformation.set(mRotateExitTransformation);
+ //mFrameTransformation.compose(mStartExitTransformation);
+ //mFrameTransformation.compose(mFinishExitTransformation);
+ mFrameTransformation.set(mRotateFrameTransformation);
+ mFrameTransformation.compose(mStartFrameTransformation);
+ mFrameTransformation.compose(mFinishFrameTransformation);
+ mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix);
+ if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation);
+ }
+
+ final boolean more = mMoreStartEnter || mMoreStartExit || mMoreStartFrame
+ || mMoreFinishEnter || mMoreFinishExit || mMoreFinishFrame
+ || mMoreRotateEnter || mMoreRotateExit || mMoreRotateFrame
+ || !mFinishAnimReady;
+
+ mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
+
+ if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
+
+ return more;
+ }
+
+ void updateSurfaces() {
+ if (mSurface != null) {
+ if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
mSurface.hide();
}
}
- if (!moreStartEnter && !moreFinishEnter && !moreRotateEnter) {
- if (mBlackFrame != null) {
- if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
- mBlackFrame.hide();
+ if (mCustomBlackFrame != null) {
+ if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
+ mCustomBlackFrame.hide();
+ } else {
+ mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
}
- } else {
- if (mBlackFrame != null) {
- mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
+ }
+
+ if (mExitingBlackFrame != null) {
+ if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
+ mExitingBlackFrame.hide();
+ } else {
+ mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
+ mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
+ mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
}
}
- mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
- setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+ if (mEnteringBlackFrame != null) {
+ if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
+ if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
+ mEnteringBlackFrame.hide();
+ } else {
+ mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
+ }
+ }
- final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
- || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
+ setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+ }
+
+ public boolean stepAnimationLocked(long now) {
+ if (!isAnimating()) {
+ if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
+ mFinishAnimReady = false;
+ return false;
+ }
- if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
+ if (!mAnimRunning) {
+ if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
+ if (mStartEnterAnimation != null) {
+ mStartEnterAnimation.setStartTime(now);
+ }
+ if (mStartExitAnimation != null) {
+ mStartExitAnimation.setStartTime(now);
+ }
+ if (mStartFrameAnimation != null) {
+ mStartFrameAnimation.setStartTime(now);
+ }
+ if (mFinishEnterAnimation != null) {
+ mFinishEnterAnimation.setStartTime(0);
+ }
+ if (mFinishExitAnimation != null) {
+ mFinishExitAnimation.setStartTime(0);
+ }
+ if (mFinishFrameAnimation != null) {
+ mFinishFrameAnimation.setStartTime(0);
+ }
+ if (mRotateEnterAnimation != null) {
+ mRotateEnterAnimation.setStartTime(now);
+ }
+ if (mRotateExitAnimation != null) {
+ mRotateExitAnimation.setStartTime(now);
+ }
+ if (mRotateFrameAnimation != null) {
+ mRotateFrameAnimation.setStartTime(now);
+ }
+ mAnimRunning = true;
+ }
- return more;
+ return stepAnimation(now);
}
public Transformation getEnterTransformation() {
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..0d64b68
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -0,0 +1,535 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
+
+import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS;
+
+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.WindowManagerPolicy;
+import android.view.animation.Animation;
+
+import com.android.internal.policy.impl.PhoneWindowManager;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+
+/**
+ * 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;
+
+ HashSet<WindowStateAnimator> mWinAnimators = new HashSet<WindowStateAnimator>();
+ HashSet<WindowStateAnimator> mFinished = new HashSet<WindowStateAnimator>();
+
+ boolean mAnimating;
+ 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;
+
+ // Window currently running an animation that has requested it be detached
+ // from the wallpaper. This means we need to ensure the wallpaper is
+ // visible behind it in case it animates in a way that would allow it to be
+ // seen.
+ WindowState mWindowDetachedWallpaper = null;
+ WindowState mDetachedWallpaper = null;
+ DimSurface mWindowAnimationBackgroundSurface = null;
+
+ int mBulkUpdateParams = 0;
+
+ DimAnimator mDimAnimator = null;
+ DimAnimator.Parameters mDimParams = null;
+
+ WindowAnimator(final WindowManagerService service, final Context context,
+ final WindowManagerPolicy policy) {
+ mService = service;
+ mContext = context;
+ mPolicy = policy;
+ }
+
+ private void testWallpaperAndBackgroundLocked() {
+ if (mWindowDetachedWallpaper != mDetachedWallpaper) {
+ if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+ "Detached wallpaper changed from " + mWindowDetachedWallpaper
+ + " to " + mDetachedWallpaper);
+ mWindowDetachedWallpaper = mDetachedWallpaper;
+ mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+ }
+
+ if (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 = mWindowAnimationBackground;
+ if (mService.mWallpaperTarget == target
+ || mService.mLowerWallpaperTarget == target
+ || mService.mUpperWallpaperTarget == target) {
+ final int N = mService.mWindows.size();
+ for (int i = 0; i < N; i++) {
+ WindowState w = mService.mWindows.get(i);
+ if (w.mIsWallpaper) {
+ target = w;
+ break;
+ }
+ }
+ }
+ if (mWindowAnimationBackgroundSurface == null) {
+ mWindowAnimationBackgroundSurface = new DimSurface(mService.mFxSession);
+ }
+ final int dw = mDw;
+ final int dh = mDh;
+ mWindowAnimationBackgroundSurface.show(dw, dh,
+ target.mWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM,
+ mWindowAnimationBackgroundColor);
+ } else if (mWindowAnimationBackgroundSurface != null) {
+ mWindowAnimationBackgroundSurface.hide();
+ }
+ }
+
+ private void updateWindowsAppsAndRotationAnimationsLocked() {
+ int i;
+ final int NAT = mService.mAppTokens.size();
+ for (i=0; i<NAT; i++) {
+ final AppWindowAnimator appAnimator = mService.mAppTokens.get(i).mAppAnimator;
+ final boolean wasAnimating = appAnimator.animation != null
+ && appAnimator.animation != WindowManagerService.sDummyAnimation;
+ if (appAnimator.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 " + appAnimator.mAppToken + " done",
+ mPendingLayoutChanges);
+ }
+ }
+ }
+
+ final int NEAT = mService.mExitingAppTokens.size();
+ for (i=0; i<NEAT; i++) {
+ final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
+ final boolean wasAnimating = appAnimator.animation != null
+ && appAnimator.animation != WindowManagerService.sDummyAnimation;
+ if (appAnimator.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 " + appAnimator.mAppToken
+ + " done", mPendingLayoutChanges);
+ }
+ }
+ }
+
+ if (mScreenRotationAnimation != null &&
+ (mScreenRotationAnimation.isAnimating() ||
+ mScreenRotationAnimation.mFinishAnimReady)) {
+ if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+ mAnimating = true;
+ } else {
+ mBulkUpdateParams |= SET_UPDATE_ROTATION;
+ mScreenRotationAnimation.kill();
+ mScreenRotationAnimation = null;
+ }
+ }
+ }
+
+ private void updateWindowsAndWallpaperLocked() {
+ ++mTransactionSequence;
+
+ for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
+ WindowState win = mService.mWindows.get(i);
+ WindowStateAnimator winAnimator = win.mWinAnimator;
+ final int flags = winAnimator.mAttrFlags;
+
+ if (winAnimator.mSurface != null) {
+ final boolean wasAnimating = winAnimator.mWasAnimating;
+ final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
+
+ if (WindowManagerService.DEBUG_WALLPAPER) {
+ Slog.v(TAG, win + ": 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 ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && winAnimator.mAnimation.getDetachWallpaper()) {
+ mDetachedWallpaper = win;
+ }
+ final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
+ if (backgroundColor != 0) {
+ if (mWindowAnimationBackground == null
+ || (winAnimator.mAnimLayer <
+ mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
+ mWindowAnimationBackground = win;
+ mWindowAnimationBackgroundColor = backgroundColor;
+ }
+ }
+ }
+ 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.
+ final AppWindowAnimator appAnimator =
+ win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
+ if (appAnimator != null && appAnimator.animation != null
+ && appAnimator.animating) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && appAnimator.animation.getDetachWallpaper()) {
+ mDetachedWallpaper = win;
+ }
+ final int backgroundColor = appAnimator.animation.getBackgroundColor();
+ if (backgroundColor != 0) {
+ if (mWindowAnimationBackground == null
+ || (winAnimator.mAnimLayer <
+ mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
+ mWindowAnimationBackground = win;
+ mWindowAnimationBackgroundColor = backgroundColor;
+ }
+ }
+ }
+
+ if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+ mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
+ mPendingLayoutChanges);
+ }
+ }
+
+ if (mPolicy.doesForceHide(win, win.mAttrs)) {
+ if (!wasAnimating && nowAnimating) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ "Animation started that could impact force hide: "
+ + win);
+ mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
+ mPendingLayoutChanges);
+ }
+ mService.mFocusMayChange = true;
+ } else if (win.isReadyForDisplay() && winAnimator.mAnimation == null) {
+ mForceHiding = true;
+ }
+ } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
+ final boolean changed;
+ if (mForceHiding) {
+ changed = win.hideLw(false, false);
+ if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+ "Now policy hidden: " + win);
+ } else {
+ changed = win.showLw(false, false);
+ if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+ "Now policy shown: " + win);
+ if (changed) {
+ if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
+ && win.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 < win.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 && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+ mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
+ mPendingLayoutChanges);
+ }
+ }
+ }
+ }
+
+ final AppWindowToken atoken = win.mAppToken;
+ if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+ if (atoken.lastTransactionSequence != mTransactionSequence) {
+ atoken.lastTransactionSequence = mTransactionSequence;
+ atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+ atoken.startingDisplayed = false;
+ }
+ if ((win.isOnScreen() || winAnimator.mAttrType
+ == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
+ && !win.mExiting && !win.mDestroying) {
+ if (WindowManagerService.DEBUG_VISIBILITY ||
+ WindowManagerService.DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Eval win " + win + ": isDrawn=" + win.isDrawnLw()
+ + ", isAnimating=" + winAnimator.isAnimating());
+ if (!win.isDrawnLw()) {
+ Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
+ + " pv=" + win.mPolicyVisibility
+ + " mDrawState=" + winAnimator.mDrawState
+ + " ah=" + win.mAttachedHidden
+ + " th=" + atoken.hiddenRequested
+ + " a=" + winAnimator.mAnimating);
+ }
+ }
+ if (win != atoken.startingWindow) {
+ if (!atoken.mAppAnimator.freezingScreen || !win.mAppFreezing) {
+ atoken.numInterestingWindows++;
+ if (win.isDrawnLw()) {
+ atoken.numDrawnWindows++;
+ if (WindowManagerService.DEBUG_VISIBILITY ||
+ WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+ "tokenMayBeDrawn: " + atoken
+ + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
+ + " mAppFreezing=" + win.mAppFreezing);
+ mTokenMayBeDrawn = true;
+ }
+ }
+ } else if (win.isDrawnLw()) {
+ atoken.startingDisplayed = true;
+ }
+ }
+ } else if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
+ if (winAnimator.performShowLocked()) {
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
+ mPendingLayoutChanges);
+ }
+ }
+ }
+ final AppWindowAnimator appAnimator =
+ atoken == null ? null : atoken.mAppAnimator;
+ if (appAnimator != null && appAnimator.thumbnail != null) {
+ if (appAnimator.thumbnailTransactionSeq != mTransactionSequence) {
+ appAnimator.thumbnailTransactionSeq = mTransactionSequence;
+ appAnimator.thumbnailLayer = 0;
+ }
+ if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
+ appAnimator.thumbnailLayer = winAnimator.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.mAppAnimator.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.mAppAnimator.showAllWindowsLocked();
+ mService.unsetAppFreezingScreenLocked(wtoken, false, true);
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
+ "Setting mOrientationChangeComplete=true because wtoken "
+ + wtoken + " numInteresting=" + numInteresting
+ + " numDrawn=" + wtoken.numDrawnWindows);
+ }
+ } 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",
+ mPendingLayoutChanges);
+ }
+
+ // We can now show all of the drawn windows!
+ if (!mService.mOpeningApps.contains(wtoken)) {
+ mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+ }
+ }
+ }
+ }
+ }
+
+ private void performAnimationsLocked() {
+ mTokenMayBeDrawn = false;
+ mForceHiding = false;
+ mDetachedWallpaper = null;
+ mWindowAnimationBackground = null;
+ mWindowAnimationBackgroundColor = 0;
+
+ updateWindowsAndWallpaperLocked();
+
+ if (mTokenMayBeDrawn) {
+ testTokenMayBeDrawnLocked();
+ }
+ }
+
+ void animate() {
+ mPendingLayoutChanges = 0;
+ mCurrentTime = SystemClock.uptimeMillis();
+ mBulkUpdateParams = 0;
+
+ // Update animations of all applications, including those
+ // associated with exiting/removed apps
+ Surface.openTransaction();
+
+ try {
+ testWallpaperAndBackgroundLocked();
+ updateWindowsAppsAndRotationAnimationsLocked();
+ performAnimationsLocked();
+
+ // THIRD LOOP: Update the surfaces of all windows.
+
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.updateSurfaces();
+ }
+
+ mFinished.clear();
+ for (final WindowStateAnimator winAnimator : mWinAnimators) {
+ if (winAnimator.mSurface == null) {
+ mFinished.add(winAnimator);
+ } else {
+ winAnimator.prepareSurfaceLocked(true);
+ }
+ }
+ for (final WindowStateAnimator winAnimator : mFinished) {
+ mWinAnimators.remove(winAnimator);
+ }
+
+ if (mDimParams != null) {
+ mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
+ }
+ if (mDimAnimator != null && mDimAnimator.mDimShown) {
+ mAnimating |= mDimAnimator.updateSurface(mDimParams != null, 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();
+ }
+
+ if (mBulkUpdateParams != 0) {
+ mService.bulkSetParameters(mBulkUpdateParams);
+ }
+ }
+
+ WindowState mCurrentFocus;
+ void setCurrentFocus(final 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;
+ }
+
+ void startDimming(final WindowStateAnimator winAnimator, final float target,
+ final int width, final int height) {
+ if (mDimAnimator == null) {
+ mDimAnimator = new DimAnimator(mService.mFxSession);
+ }
+ mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS,
+ new DimAnimator.Parameters(winAnimator, width, height, target)));
+ }
+
+ // TODO(cmautner): Move into Handler
+ void stopDimming() {
+ mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
+ }
+
+ public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ if (mWindowDetachedWallpaper != null) {
+ pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
+ }
+ if (mWindowAnimationBackgroundSurface != null) {
+ pw.println(" mWindowAnimationBackgroundSurface:");
+ mWindowAnimationBackgroundSurface.printTo(" ", pw);
+ }
+ if (mDimAnimator != null) {
+ pw.println(" mDimAnimator:");
+ mDimAnimator.printTo(" ", pw);
+ } else {
+ pw.println( " no DimAnimator ");
+ }
+ }
+
+ static class SetAnimationParams {
+ final WindowStateAnimator mWinAnimator;
+ final Animation mAnimation;
+ final int mAnimDw;
+ final int mAnimDh;
+ public SetAnimationParams(final WindowStateAnimator winAnimator,
+ final Animation animation, final int animDw, final int animDh) {
+ mWinAnimator = winAnimator;
+ mAnimation = animation;
+ mAnimDw = animDw;
+ mAnimDh = animDh;
+ }
+ }
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 008793c..6f7852d 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;
@@ -45,6 +44,8 @@ import com.android.server.EventLogTags;
import com.android.server.PowerManagerService;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
+import com.android.server.input.InputFilter;
+import com.android.server.input.InputManagerService;
import android.Manifest;
import android.app.ActivityManagerNative;
@@ -90,6 +91,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 +120,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 +173,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 = true;
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 +208,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;
@@ -231,10 +245,6 @@ public class WindowManagerService extends IWindowManager.Stub
*/
static final boolean CUSTOM_SCREEN_ROTATION = true;
- // Maximum number of milliseconds to wait for input event injection.
- // FIXME is this value reasonable?
- private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
-
// Maximum number of milliseconds to wait for input devices to be enumerated before
// proceding with safe mode detection.
private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
@@ -415,17 +425,11 @@ public class WindowManagerService extends IWindowManager.Stub
IInputMethodManager mInputMethodManager;
SurfaceSession mFxSession;
- private DimAnimator mDimAnimator = null;
- Surface mBlurSurface;
- boolean mBlurShown;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
- ScreenRotationAnimation mScreenRotationAnimation;
BlackFrame mBlackFrame;
- int mTransactionSequence = 0;
-
final float[] mTmpFloats = new float[9];
boolean mSafeMode;
@@ -461,6 +465,7 @@ public class WindowManagerService extends IWindowManager.Stub
= new ArrayList<IRotationWatcher>();
int mDeferredRotationPauseCount;
+ int mPendingLayoutChanges = 0;
boolean mLayoutNeeded = true;
boolean mTraversalScheduled = false;
boolean mDisplayFrozen = false;
@@ -490,8 +495,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;
@@ -542,12 +551,6 @@ public class WindowManagerService extends IWindowManager.Stub
// If non-null, we are in the middle of animating from one wallpaper target
// to another, and this is the higher one in Z-order.
WindowState mUpperWallpaperTarget = null;
- // Window currently running an animation that has requested it be detached
- // from the wallpaper. This means we need to ensure the wallpaper is
- // visible behind it in case it animates in a way that would allow it to be
- // seen.
- WindowState mWindowDetachedWallpaper = null;
- DimSurface mWindowAnimationBackgroundSurface = null;
int mWallpaperAnimLayerAdjustment;
float mLastWallpaperX = -1;
float mLastWallpaperY = -1;
@@ -571,7 +574,7 @@ public class WindowManagerService extends IWindowManager.Stub
float mTransitionAnimationScale = 1.0f;
float mAnimatorDurationScale = 1.0f;
- final InputManager mInputManager;
+ final InputManagerService mInputManager;
// Who is holding the screen on.
Session mHoldingScreenOn;
@@ -583,27 +586,28 @@ 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;
- private int mAdjResult = 0;
+ class LayoutFields {
+ static final int SET_UPDATE_ROTATION = 1 << 0;
+ static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
+ static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
+ static final int CLEAR_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
+
+ boolean mWallpaperForceHidingChanged = false;
+ boolean mWallpaperMayChange = false;
+ boolean mOrientationChangeComplete = true;
+ 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();
+ LayoutFields mInnerFields = new LayoutFields();
+
+ /** Only do a maximum of 6 repeated layouts. After that quit */
+ private int mLayoutRepeatCount;
private final class AnimationRunnable implements Runnable {
@Override
@@ -616,6 +620,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) {
@@ -734,6 +740,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAllowBootMessages = allowBootMsgs;
}
+ @Override
public void run() {
Looper.prepare();
WindowManagerService s = new WindowManagerService(mContext, mPM,
@@ -773,6 +780,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPM = pm;
}
+ @Override
public void run() {
Looper.prepare();
WindowManagerPolicyThread.set(this, Looper.myLooper());
@@ -834,7 +842,8 @@ public class WindowManagerService extends IWindowManager.Stub
"KEEP_SCREEN_ON_FLAG");
mHoldingScreenWakeLock.setReferenceCounted(false);
- mInputManager = new InputManager(context, this);
+ mInputManager = new InputManagerService(context, mInputMonitor);
+ mAnimator = new WindowAnimator(this, context, mPolicy);
PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
thr.start();
@@ -854,6 +863,10 @@ public class WindowManagerService extends IWindowManager.Stub
Watchdog.getInstance().addMonitor(this);
}
+ public InputManagerService getInputManagerService() {
+ return mInputManager;
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -1118,7 +1131,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_INPUT_METHOD) {
Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
if (!w.isVisibleOrAdding()) {
- Slog.i(TAG, " mSurface=" + w.mSurface + " reportDestroy=" + w.mReportDestroySurface
+ Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurface + " reportDestroy="
+ + w.mWinAnimator.mReportDestroySurface
+ " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
+ " policyVis=" + w.mPolicyVisibility + " attachHid=" + w.mAttachedHidden
+ " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
@@ -1182,7 +1196,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mInputMethodTarget != null && w != null
&& mInputMethodTarget.isDisplayedLw()
&& mInputMethodTarget.mExiting) {
- if (mInputMethodTarget.mAnimLayer > w.mAnimLayer) {
+ if (mInputMethodTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
w = mInputMethodTarget;
i = localmWindows.indexOf(w);
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w);
@@ -1203,7 +1217,7 @@ public class WindowManagerService extends IWindowManager.Stub
AppWindowToken token = curTarget.mAppToken;
WindowState highestTarget = null;
int highestPos = 0;
- if (token.animating || token.animation != null) {
+ if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
int pos = localmWindows.indexOf(curTarget);
while (pos >= 0) {
WindowState win = localmWindows.get(pos);
@@ -1211,8 +1225,8 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
if (!win.mRemoved) {
- if (highestTarget == null || win.mAnimLayer >
- highestTarget.mAnimLayer) {
+ if (highestTarget == null || win.mWinAnimator.mAnimLayer >
+ highestTarget.mWinAnimator.mAnimLayer) {
highestTarget = win;
highestPos = pos;
}
@@ -1224,9 +1238,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (highestTarget != null) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
+ mNextAppTransition + " " + highestTarget
- + " animating=" + highestTarget.isAnimating()
- + " layer=" + highestTarget.mAnimLayer
- + " new layer=" + w.mAnimLayer);
+ + " animating=" + highestTarget.mWinAnimator.isAnimating()
+ + " layer=" + highestTarget.mWinAnimator.mAnimLayer
+ + " new layer=" + w.mWinAnimator.mAnimLayer);
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
// If we are currently setting up for an animation,
@@ -1234,8 +1248,8 @@ public class WindowManagerService extends IWindowManager.Stub
mInputMethodTargetWaitingAnim = true;
mInputMethodTarget = highestTarget;
return highestPos + 1;
- } else if (highestTarget.isAnimating() &&
- highestTarget.mAnimLayer > w.mAnimLayer) {
+ } else if (highestTarget.mWinAnimator.isAnimating() &&
+ highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
// If the window we are currently targeting is involved
// with an animation, and it is on top of the next target
// we will be over, then hold off on moving until
@@ -1263,7 +1277,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInputMethodTarget = w;
mInputMethodTargetWaitingAnim = false;
if (w.mAppToken != null) {
- setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
+ setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
} else {
setInputMethodAnimLayerAdjustment(0);
}
@@ -1307,25 +1321,25 @@ public class WindowManagerService extends IWindowManager.Stub
mInputMethodAnimLayerAdjustment = adj;
WindowState imw = mInputMethodWindow;
if (imw != null) {
- imw.mAnimLayer = imw.mLayer + adj;
+ imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
- + " anim layer: " + imw.mAnimLayer);
+ + " anim layer: " + imw.mWinAnimator.mAnimLayer);
int wi = imw.mChildWindows.size();
while (wi > 0) {
wi--;
WindowState cw = imw.mChildWindows.get(wi);
- cw.mAnimLayer = cw.mLayer + adj;
+ cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
- + " anim layer: " + cw.mAnimLayer);
+ + " anim layer: " + cw.mWinAnimator.mAnimLayer);
}
}
int di = mInputMethodDialogs.size();
while (di > 0) {
di --;
imw = mInputMethodDialogs.get(di);
- imw.mAnimLayer = imw.mLayer + adj;
+ imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
- + " anim layer: " + imw.mAnimLayer);
+ + " anim layer: " + imw.mWinAnimator.mAnimLayer);
}
}
@@ -1523,15 +1537,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
final boolean isWallpaperVisible(WindowState wallpaperTarget) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
- ? wallpaperTarget.mAppToken.animation : null)
+ ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
+ " upper=" + mUpperWallpaperTarget
+ " lower=" + mLowerWallpaperTarget);
return (wallpaperTarget != null
&& (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
- && wallpaperTarget.mAppToken.animation != null)))
+ && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
|| mUpperWallpaperTarget != null
|| mLowerWallpaperTarget != null;
}
@@ -1540,6 +1554,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
int adjustWallpaperWindowsLocked() {
+ mInnerFields.mWallpaperMayChange = false;
int changed = 0;
final int dw = mAppDisplayWidth;
@@ -1567,28 +1582,26 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
topCurW = null;
- if (w != mWindowDetachedWallpaper && w.mAppToken != null) {
+ if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
// If this window's app token is hidden and not animating,
// it is of no interest to us.
- if (w.mAppToken.hidden && w.mAppToken.animation == null) {
+ if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
"Skipping not hidden or animating token: " + w);
continue;
}
}
if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
- + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
- + " commitdrawpending=" + w.mCommitDrawPending);
+ + w.isReadyForDisplay() + " mDrawState=" + w.mWinAnimator.mDrawState);
if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
- && (mWallpaperTarget == w
- || (!w.mDrawPending && !w.mCommitDrawPending))) {
+ && (mWallpaperTarget == w || w.isDrawnLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
"Found wallpaper activity: #" + i + "=" + w);
foundW = w;
foundI = i;
if (w == mWallpaperTarget && ((w.mAppToken != null
- && w.mAppToken.animation != null)
- || w.mAnimation != null)) {
+ && w.mAppToken.mAppAnimator.animation != 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.
@@ -1597,7 +1610,7 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
break;
- } else if (w == mWindowDetachedWallpaper) {
+ } else if (w == mAnimator.mWindowDetachedWallpaper) {
windowDetachedI = i;
}
}
@@ -1645,10 +1658,12 @@ 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
- || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
- boolean foundAnim = foundW.mAnimation != null
- || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
+ boolean oldAnim = oldW.mWinAnimator.mAnimation != null
+ || (oldW.mAppToken != null
+ && oldW.mAppToken.mAppAnimator.animation != null);
+ boolean foundAnim = foundW.mWinAnimator.mAnimation != null
+ || (foundW.mAppToken != null &&
+ foundW.mAppToken.mAppAnimator.animation != null);
if (DEBUG_WALLPAPER) {
Slog.v(TAG, "New animation: " + foundAnim
+ " old animation: " + oldAnim);
@@ -1699,12 +1714,12 @@ 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
+ && mLowerWallpaperTarget.mAppToken.mAppAnimator.animation != null);
+ boolean upperAnimating = mUpperWallpaperTarget.mWinAnimator.mAnimation != null
|| (mUpperWallpaperTarget.mAppToken != null
- && mUpperWallpaperTarget.mAppToken.animation != null);
+ && mUpperWallpaperTarget.mAppToken.mAppAnimator.animation != null);
if (!lowerAnimating || !upperAnimating) {
if (DEBUG_WALLPAPER) {
Slog.v(TAG, "No longer animating wallpaper targets!");
@@ -1726,7 +1741,7 @@ public class WindowManagerService extends IWindowManager.Stub
// between two wallpaper targets.
mWallpaperAnimLayerAdjustment =
(mLowerWallpaperTarget == null && foundW.mAppToken != null)
- ? foundW.mAppToken.animLayerAdjustment : 0;
+ ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
final int maxLayer = mPolicy.getMaxWallpaperLayer()
* TYPE_LAYER_MULTIPLIER
@@ -1813,9 +1828,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
+ wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
- + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
+ + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
// First, if this window is at the current index, then all
// is well.
@@ -1867,9 +1882,9 @@ public class WindowManagerService extends IWindowManager.Stub
while (curWallpaperIndex > 0) {
curWallpaperIndex--;
WindowState wallpaper = token.windows.get(curWallpaperIndex);
- wallpaper.mAnimLayer = wallpaper.mLayer + adj;
+ wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
- + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
+ + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
}
}
}
@@ -1910,7 +1925,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 "
@@ -1961,6 +1976,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ // TODO(cmautner): Move to WindowAnimator.
+ void setWallpaperOffset(final WindowStateAnimator winAnimator, final int left, final int top) {
+ mH.sendMessage(mH.obtainMessage(H.SET_WALLPAPER_OFFSET, left, top, winAnimator));
+ }
+
void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
final int dw = mAppDisplayWidth;
final int dh = mAppDisplayHeight;
@@ -1988,20 +2008,20 @@ public class WindowManagerService extends IWindowManager.Stub
curWallpaperIndex--;
WindowState wallpaper = token.windows.get(curWallpaperIndex);
if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
- wallpaper.computeShownFrameLocked();
+ WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+ winAnimator.computeShownFrameLocked();
// No need to lay out the windows - we can just set the wallpaper position
// directly.
- if (wallpaper.mSurfaceX != wallpaper.mShownFrame.left
- || wallpaper.mSurfaceY != wallpaper.mShownFrame.top) {
+ // TODO(cmautner): Don't move this from here, just lock the WindowAnimator.
+ if (winAnimator.mSurfaceX != wallpaper.mShownFrame.left
+ || winAnimator.mSurfaceY != wallpaper.mShownFrame.top) {
Surface.openTransaction();
try {
if (SHOW_TRANSACTIONS) logSurface(wallpaper,
"POS " + wallpaper.mShownFrame.left
+ ", " + wallpaper.mShownFrame.top, null);
- wallpaper.mSurfaceX = wallpaper.mShownFrame.left;
- wallpaper.mSurfaceY = wallpaper.mShownFrame.top;
- wallpaper.mSurface.setPosition(wallpaper.mShownFrame.left,
- wallpaper.mShownFrame.top);
+ setWallpaperOffset(winAnimator, (int) wallpaper.mShownFrame.left,
+ (int) wallpaper.mShownFrame.top);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + wallpaper
+ " pos=(" + wallpaper.mShownFrame.left
@@ -2210,14 +2230,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- win.mEnterAnimationPending = true;
+ win.mWinAnimator.mEnterAnimationPending = true;
mPolicy.getContentInsetHintLw(attrs, outContentInsets);
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;
}
@@ -2281,18 +2301,18 @@ public class WindowManagerService extends IWindowManager.Stub
TAG, "Remove " + win + " client="
+ Integer.toHexString(System.identityHashCode(
win.mClient.asBinder()))
- + ", surface=" + win.mSurface);
+ + ", surface=" + win.mWinAnimator.mSurface);
final long origId = Binder.clearCallingIdentity();
-
+
win.disposeInputChannel();
if (DEBUG_APP_TRANSITIONS) Slog.v(
- TAG, "Remove " + win + ": mSurface=" + win.mSurface
+ TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurface
+ " mExiting=" + win.mExiting
- + " isAnimating=" + win.isAnimating()
+ + " isAnimating=" + win.mWinAnimator.isAnimating()
+ " app-animation="
- + (win.mAppToken != null ? win.mAppToken.animation : null)
+ + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
+ " inPendingTransaction="
+ (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
+ " mDisplayFrozen=" + mDisplayFrozen);
@@ -2302,22 +2322,22 @@ 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.mHasSurface && 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.
- if (applyAnimationLocked(win, transit, false)) {
+ if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
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;
@@ -2446,33 +2466,36 @@ public class WindowManagerService extends IWindowManager.Stub
}
static void logSurface(WindowState w, String msg, RuntimeException where) {
- String str = " SURFACE " + Integer.toHexString(w.hashCode())
- + ": " + msg + " / " + w.mAttrs.getTitle();
+ String str = " SURFACE " + msg + ": " + w;
if (where != null) {
Slog.i(TAG, str, where);
} else {
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);
+ }
+ }
+
+ // TODO(cmautner): Move to WindowStateAnimator.
+ void setTransparentRegionHint(final WindowStateAnimator winAnimator, final Region region) {
+ mH.sendMessage(mH.obtainMessage(H.SET_TRANSPARENT_REGION,
+ new Pair<WindowStateAnimator, Region>(winAnimator, region)));
+ }
+
void setTransparentRegionWindow(Session session, IWindow client, Region region) {
long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
WindowState w = windowForClientLocked(session, client, false);
- if ((w != null) && (w.mSurface != null)) {
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION setTransparentRegion");
- Surface.openTransaction();
- try {
- if (SHOW_TRANSACTIONS) logSurface(w,
- "transparentRegionHint=" + region, null);
- w.mSurface.setTransparentRegionHint(region);
- } finally {
- Surface.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION setTransparentRegion");
- }
+ if ((w != null) && w.mHasSurface) {
+ setTransparentRegionHint(w.mWinAnimator, region);
}
}
} finally {
@@ -2595,10 +2618,12 @@ public class WindowManagerService extends IWindowManager.Stub
long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
+ // TODO(cmautner): synchronize on mAnimator or win.mWinAnimator.
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return 0;
}
+ WindowStateAnimator winAnimator = win.mWinAnimator;
if (win.mRequestedWidth != requestedWidth
|| win.mRequestedHeight != requestedHeight) {
win.mLayoutNeeded = true;
@@ -2613,7 +2638,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.adjustWindowParamsLw(attrs);
}
- win.mSurfaceDestroyDeferred =
+ winAnimator.mSurfaceDestroyDeferred =
(flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
int attrChanges = 0;
@@ -2625,7 +2650,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
flagChanges = win.mAttrs.flags ^= attrs.flags;
attrChanges = win.mAttrs.copyFrom(attrs);
- if ((attrChanges&WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
+ if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
+ | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
win.mLayoutNeeded = true;
}
}
@@ -2635,7 +2661,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
- win.mAlpha = attrs.alpha;
+ winAnimator.mAlpha = attrs.alpha;
}
final boolean scaledWindow =
@@ -2677,20 +2703,19 @@ public class WindowManagerService extends IWindowManager.Stub
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
displayed = !win.isVisibleLw();
if (win.mExiting) {
- win.cancelExitAnimationForNextAnimationLocked();
+ winAnimator.cancelExitAnimationForNextAnimationLocked();
+ win.mExiting = false;
}
if (win.mDestroying) {
win.mDestroying = false;
mDestroySurface.remove(win);
}
if (oldVisibility == View.GONE) {
- win.mEnterAnimationPending = true;
+ winAnimator.mEnterAnimationPending = true;
}
if (displayed) {
- if (win.mSurface != null && !win.mDrawPending
- && !win.mCommitDrawPending && !mDisplayFrozen
- && mDisplayEnabled && mPolicy.isScreenOnFully()) {
- applyEnterAnimationLocked(win);
+ if (win.isDrawnLw() && okToDisplay()) {
+ winAnimator.applyEnterAnimationLocked();
}
if ((win.mAttrs.flags
& WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
@@ -2713,19 +2738,19 @@ public class WindowManagerService extends IWindowManager.Stub
}
if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
// To change the format, we need to re-build the surface.
- win.destroySurfaceLocked();
+ winAnimator.destroySurfaceLocked();
displayed = true;
surfaceChanged = true;
}
try {
- if (win.mSurface == null) {
+ if (!win.mHasSurface) {
surfaceChanged = true;
}
- Surface surface = win.createSurfaceLocked();
+ Surface surface = winAnimator.createSurfaceLocked();
if (surface != null) {
outSurface.copyFrom(surface);
- win.mReportDestroySurface = false;
- win.mSurfacePendingDestroy = false;
+ winAnimator.mReportDestroySurface = false;
+ winAnimator.mSurfacePendingDestroy = false;
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
@@ -2764,26 +2789,26 @@ public class WindowManagerService extends IWindowManager.Stub
sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
}
} else {
- win.mEnterAnimationPending = false;
- if (win.mSurface != null) {
+ winAnimator.mEnterAnimationPending = false;
+ if (winAnimator.mSurface != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
+ ": mExiting=" + win.mExiting
- + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
+ + " mSurfacePendingDestroy=" + winAnimator.mSurfacePendingDestroy);
// If we are not currently running the exit animation, we
// need to see about starting one.
- if (!win.mExiting || win.mSurfacePendingDestroy) {
+ if (!win.mExiting || winAnimator.mSurfacePendingDestroy) {
surfaceChanged = true;
// 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)) {
+ if (!winAnimator.mSurfacePendingDestroy && win.isWinVisibleLw() &&
+ winAnimator.applyAnimationLocked(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;
@@ -2792,31 +2817,31 @@ 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;
}
- win.destroySurfaceLocked();
+ winAnimator.destroySurfaceLocked();
}
}
}
- if (win.mSurface == null || (win.getAttrs().flags
+ if (winAnimator.mSurface == null || (win.getAttrs().flags
& WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
- || win.mSurfacePendingDestroy) {
+ || winAnimator.mSurfacePendingDestroy) {
// We could be called from a local process, which
// means outSurface holds its current surface. Ensure the
// surface object is cleared, but we don't necessarily want
// it actually destroyed at this point.
- win.mSurfacePendingDestroy = false;
+ winAnimator.mSurfacePendingDestroy = false;
outSurface.release();
if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
- } else if (win.mSurface != null) {
+ } else if (winAnimator.mSurface != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG,
"Keeping surface, will report destroy: " + win);
- win.mReportDestroySurface = true;
- outSurface.copyFrom(win.mSurface);
+ winAnimator.mReportDestroySurface = true;
+ outSurface.copyFrom(winAnimator.mSurface);
}
}
@@ -2901,7 +2926,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (win == null) {
return;
}
- win.destroyDeferredSurfaceLocked();
+ win.mWinAnimator.destroyDeferredSurfaceLocked();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -2917,7 +2942,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (win == null) {
return false;
}
- return reclaimSomeSurfaceMemoryLocked(win, "from-client", false);
+ return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -2928,7 +2953,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
- if (win != null && win.finishDrawingLocked()) {
+ if (win != null && win.mWinAnimator.finishDrawingLocked()) {
if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
adjustWallpaperWindowsLocked();
}
@@ -2982,77 +3007,7 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
- void applyEnterAnimationLocked(WindowState win) {
- int transit = WindowManagerPolicy.TRANSIT_SHOW;
- if (win.mEnterAnimationPending) {
- win.mEnterAnimationPending = false;
- transit = WindowManagerPolicy.TRANSIT_ENTER;
- }
-
- applyAnimationLocked(win, transit, true);
- }
-
- boolean applyAnimationLocked(WindowState win,
- int transit, boolean isEntrance) {
- if (win.mLocalAnimating && win.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;
- }
-
- // 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()) {
- int anim = mPolicy.selectAnimationLw(win, transit);
- int attr = -1;
- Animation a = null;
- if (anim != 0) {
- a = AnimationUtils.loadAnimation(mContext, anim);
- } else {
- switch (transit) {
- case WindowManagerPolicy.TRANSIT_ENTER:
- attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
- break;
- case WindowManagerPolicy.TRANSIT_EXIT:
- attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
- break;
- case WindowManagerPolicy.TRANSIT_SHOW:
- attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
- break;
- case WindowManagerPolicy.TRANSIT_HIDE:
- attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
- break;
- }
- if (attr >= 0) {
- a = loadAnimation(win.mAttrs, attr);
- }
- }
- if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
- + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
- + " mAnimation=" + win.mAnimation
- + " isEntrance=" + isEntrance);
- if (a != null) {
- if (DEBUG_ANIM) {
- RuntimeException e = null;
- if (!HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
- }
- win.setAnimation(a);
- win.mAnimationIsEntrance = isEntrance;
- }
- } else {
- win.clearAnimation();
- }
-
- return win.mAnimation != null;
- }
-
- private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
+ Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
int anim = 0;
Context context = mContext;
if (animAttr >= 0) {
@@ -3084,15 +3039,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 {
@@ -3164,13 +3180,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
}
- wtoken.setAnimation(a);
+ wtoken.mAppAnimator.setAnimation(a, initialized);
}
} else {
- wtoken.clearAnimation();
+ wtoken.mAppAnimator.clearAnimation();
}
- return wtoken.animation != null;
+ return wtoken.mAppAnimator.animation != null;
}
// -------------------------------------------------------------
@@ -3223,6 +3239,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);
@@ -3232,6 +3252,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()")) {
@@ -3272,13 +3293,12 @@ 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;
}
if (win.isVisibleNow()) {
- applyAnimationLocked(win,
- WindowManagerPolicy.TRANSIT_EXIT, false);
+ win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
changed = true;
}
}
@@ -3311,7 +3331,7 @@ public class WindowManagerService extends IWindowManager.Stub
"addAppToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
-
+
// Get the dispatching timeout here while we are not holding any locks so that it
// can be cached by the AppWindowToken. The timeout value is used later by the
// input dispatcher in code that does hold locks. If we did not cache the value
@@ -3399,15 +3419,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
public int getOrientationFromAppTokensLocked() {
- int pos = mAppTokens.size() - 1;
int curGroup = 0;
int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean findingBehind = false;
boolean haveGroup = false;
boolean lastFullscreen = false;
- while (pos >= 0) {
+ for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) {
AppWindowToken wtoken = mAppTokens.get(pos);
- pos--;
if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + wtoken);
@@ -3537,7 +3555,6 @@ public class WindowManagerService extends IWindowManager.Stub
* android.os.IBinder)
*/
boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
- boolean changed = false;
long ident = Binder.clearCallingIdentity();
try {
int req = computeForcedAppOrientationLocked();
@@ -3548,11 +3565,12 @@ public class WindowManagerService extends IWindowManager.Stub
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
if (updateRotationUncheckedLocked(inTransaction)) {
- changed = true;
+ // changed
+ return true;
}
}
- return changed;
+ return false;
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3654,7 +3672,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;
@@ -3688,11 +3706,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()")) {
@@ -3738,7 +3768,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;
}
@@ -3804,14 +3834,16 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.clientHidden = ttoken.clientHidden;
wtoken.sendAppVisibilityToClients();
}
- if (ttoken.animation != null) {
- wtoken.animation = ttoken.animation;
- wtoken.animating = ttoken.animating;
- wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
- ttoken.animation = null;
- ttoken.animLayerAdjustment = 0;
- wtoken.updateLayers();
- ttoken.updateLayers();
+ final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
+ final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
+ if (tAppAnimator.animation != null) {
+ wAppAnimator.animation = tAppAnimator.animation;
+ wAppAnimator.animating = tAppAnimator.animating;
+ wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
+ tAppAnimator.animation = null;
+ tAppAnimator.animLayerAdjustment = 0;
+ wAppAnimator.updateLayers();
+ tAppAnimator.updateLayers();
}
updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -3836,6 +3868,21 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendMessageAtFrontOfQueue(m);
return;
}
+ final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
+ final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
+ if (tAppAnimator.thumbnail != null) {
+ // The old token is animating with a thumbnail, transfer
+ // that to the new token.
+ if (wAppAnimator.thumbnail != null) {
+ wAppAnimator.thumbnail.destroy();
+ }
+ wAppAnimator.thumbnail = tAppAnimator.thumbnail;
+ wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
+ wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
+ wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
+ wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
+ tAppAnimator.thumbnail = null;
+ }
}
}
@@ -3924,12 +3971,12 @@ public class WindowManagerService extends IWindowManager.Stub
boolean runningAppAnimation = false;
if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
- if (wtoken.animation == sDummyAnimation) {
- wtoken.animation = null;
+ if (wtoken.mAppAnimator.animation == sDummyAnimation) {
+ wtoken.mAppAnimator.animation = null;
}
applyAnimationLocked(wtoken, lp, transit, visible);
changed = true;
- if (wtoken.animation != null) {
+ if (wtoken.mAppAnimator.animation != null) {
delayed = runningAppAnimation = true;
}
}
@@ -3940,7 +3987,7 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
- if (win.isAnimating()) {
+ if (win.mWinAnimator.isAnimating()) {
delayed = true;
}
@@ -3949,14 +3996,14 @@ public class WindowManagerService extends IWindowManager.Stub
if (visible) {
if (!win.isVisibleNow()) {
if (!runningAppAnimation) {
- applyAnimationLocked(win,
+ win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_ENTER, true);
}
changed = true;
}
} else if (win.isVisibleNow()) {
if (!runningAppAnimation) {
- applyAnimationLocked(win,
+ win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_EXIT, false);
}
changed = true;
@@ -3970,8 +4017,7 @@ public class WindowManagerService extends IWindowManager.Stub
// If we are being set visible, and the starting window is
// not yet displayed, then make sure it doesn't get displayed.
WindowState swin = wtoken.startingWindow;
- if (swin != null && (swin.mDrawPending
- || swin.mCommitDrawPending)) {
+ if (swin != null && !swin.isDrawnLw()) {
swin.mPolicyVisibility = false;
swin.mPolicyVisibilityAfterAnim = false;
}
@@ -3993,7 +4039,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (wtoken.animation != null) {
+ if (wtoken.mAppAnimator.animation != null) {
delayed = true;
}
@@ -4029,8 +4075,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;
@@ -4039,7 +4084,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Setting dummy animation on: " + wtoken);
- wtoken.setDummyAnimation();
+ wtoken.mAppAnimator.setDummyAnimation();
mOpeningApps.remove(wtoken);
mClosingApps.remove(wtoken);
wtoken.waitingToShow = wtoken.waitingToHide = false;
@@ -4089,7 +4134,7 @@ public class WindowManagerService extends IWindowManager.Stub
void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
boolean unfreezeSurfaceNow, boolean force) {
- if (wtoken.freezingScreen) {
+ if (wtoken.mAppAnimator.freezingScreen) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
+ " force=" + force);
final int N = wtoken.allAppWindows.size();
@@ -4098,7 +4143,7 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState w = wtoken.allAppWindows.get(i);
if (w.mAppFreezing) {
w.mAppFreezing = false;
- if (w.mSurface != null && !w.mOrientationChanging) {
+ if (w.mHasSurface && !w.mOrientationChanging) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
w.mOrientationChanging = true;
}
@@ -4107,7 +4152,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (force || unfrozeWindows) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
- wtoken.freezingScreen = false;
+ wtoken.mAppAnimator.freezingScreen = false;
mAppsFreezingScreen--;
}
if (unfreezeSurfaceNow) {
@@ -4130,11 +4175,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
Slog.i(TAG, "Set freezing of " + wtoken.appToken
+ ": hidden=" + wtoken.hidden + " freezing="
- + wtoken.freezingScreen, e);
+ + wtoken.mAppAnimator.freezingScreen, e);
}
if (!wtoken.hiddenRequested) {
- if (!wtoken.freezingScreen) {
- wtoken.freezingScreen = true;
+ if (!wtoken.mAppAnimator.freezingScreen) {
+ wtoken.mAppAnimator.freezingScreen = true;
mAppsFreezingScreen++;
if (mAppsFreezingScreen == 1) {
startFreezingDisplayLocked(false);
@@ -4158,7 +4203,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;
}
@@ -4187,7 +4232,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
final long origId = Binder.clearCallingIdentity();
if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
- + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
+ + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
unsetAppFreezingScreenLocked(wtoken, true, force);
Binder.restoreCallingIdentity(origId);
}
@@ -4222,8 +4267,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Removing app " + wtoken + " delayed=" + delayed
- + " animation=" + wtoken.animation
- + " animating=" + wtoken.animating);
+ + " animation=" + wtoken.mAppAnimator.animation
+ + " animating=" + wtoken.mAppAnimator.animating);
if (delayed) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -4233,8 +4278,8 @@ 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.animation = null;
- wtoken.animating = false;
+ wtoken.mAppAnimator.clearAnimation();
+ wtoken.mAppAnimator.animating = false;
}
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"removeAppToken: " + wtoken);
@@ -4685,7 +4730,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
- if (w.mSurface != null) {
+ if (w.mHasSurface) {
try {
w.mClient.closeSystemDialogs(reason);
} catch (RemoteException e) {
@@ -4756,90 +4801,22 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimatorDurationScale };
}
- public int getSwitchState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getSwitchState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getSwitchStateForDevice(int devid, int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getSwitchStateForDevice()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getScancodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getScancodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getScancodeStateForDevice(int devid, int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getScancodeStateForDevice()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getTrackballScancodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getTrackballScancodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
- }
-
- public int getDPadScancodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getDPadScancodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw);
- }
-
- public int getKeycodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getKeycodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getKeycodeStateForDevice(int devid, int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getKeycodeStateForDevice()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw);
- }
-
- public int getTrackballKeycodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getTrackballKeycodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
- }
- return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
- }
-
- public int getDPadKeycodeState(int sw) {
- if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
- "getDPadKeycodeState()")) {
- throw new SecurityException("Requires READ_INPUT_STATE permission");
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public int getLidState() {
+ final int SW_LID = 0x00;
+ int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LID);
+ if (sw > 0) {
+ return LID_OPEN;
+ } else if (sw == 0) {
+ return LID_CLOSED;
+ } else {
+ return LID_ABSENT;
}
- return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw);
- }
-
- public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
- return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists);
}
+ // Called by window manager policy. Not exposed externally.
+ @Override
public InputChannel monitorInput(String inputChannelName) {
if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
"monitorInput()")) {
@@ -4852,14 +4829,6 @@ public class WindowManagerService extends IWindowManager.Stub
mInputManager.setInputFilter(filter);
}
- public InputDevice getInputDevice(int deviceId) {
- return mInputManager.getInputDevice(deviceId);
- }
-
- public int[] getInputDeviceIds() {
- return mInputManager.getInputDeviceIds();
- }
-
public void enableScreenAfterBoot() {
synchronized(mWindowMap) {
if (DEBUG_BOOT) {
@@ -5016,7 +4985,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.enableScreenAfterBoot();
// Make sure the last requested orientation has been applied.
- updateRotationUnchecked(false);
+ updateRotationUnchecked(false, false);
}
public void showBootMessage(final CharSequence msg, final boolean always) {
@@ -5140,8 +5109,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
@@ -5157,7 +5126,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean including = false;
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState ws = mWindows.get(i);
- if (ws.mSurface == null) {
+ if (!ws.mHasSurface) {
continue;
}
if (ws.mLayer >= aboveAppLayer) {
@@ -5183,8 +5152,8 @@ public class WindowManagerService extends IWindowManager.Stub
// window.
including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
- if (maxLayer < ws.mAnimLayer) {
- maxLayer = ws.mAnimLayer;
+ if (maxLayer < ws.mWinAnimator.mAnimLayer) {
+ maxLayer = ws.mWinAnimator.mAnimLayer;
}
// Don't include wallpaper in bounds calculation
@@ -5245,8 +5214,8 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer);
for (int i=0; i<mWindows.size(); i++) {
Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer
- + " animLayer=" + mWindows.get(i).mAnimLayer
- + " surfaceLayer=" + mWindows.get(i).mSurfaceLayer);
+ + " animLayer=" + mWindows.get(i).mWinAnimator.mAnimLayer
+ + " surfaceLayer=" + mWindows.get(i).mWinAnimator.mSurfaceLayer);
}
}
rawss = Surface.screenshot(dw, dh, 0, maxLayer);
@@ -5261,7 +5230,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);
@@ -5290,7 +5259,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
rotation == -1 ? mRotation : rotation);
- updateRotationUnchecked(false);
+ updateRotationUnchecked(false, false);
}
/**
@@ -5306,7 +5275,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used
- updateRotationUnchecked(false);
+ updateRotationUnchecked(false, false);
}
/**
@@ -5316,8 +5285,8 @@ public class WindowManagerService extends IWindowManager.Stub
* such that the current rotation might need to be updated, such as when the
* device is docked or rotated into a new posture.
*/
- public void updateRotation(boolean alwaysSendConfiguration) {
- updateRotationUnchecked(alwaysSendConfiguration);
+ public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
+ updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
}
/**
@@ -5347,8 +5316,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- public void updateRotationUnchecked(
- boolean alwaysSendConfiguration) {
+ public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
+ "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
@@ -5356,6 +5324,10 @@ public class WindowManagerService extends IWindowManager.Stub
boolean changed;
synchronized(mWindowMap) {
changed = updateRotationUncheckedLocked(false);
+ if (!changed || forceRelayout) {
+ mLayoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ }
}
if (changed || alwaysSendConfiguration) {
@@ -5379,7 +5351,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.
@@ -5449,9 +5422,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();
@@ -5466,11 +5439,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- rebuildBlackFrame(inTransaction);
+ rebuildBlackFrame();
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
- if (w.mSurface != null) {
+ if (w.mHasSurface) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
w.mOrientationChanging = true;
}
@@ -6153,6 +6126,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
@@ -6335,164 +6310,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mWindowMap) {
mInputMonitor.setEventDispatchingLw(enabled);
}
- }
-
- /**
- * Injects a keystroke event into the UI.
- * Even when sync is false, this method may block while waiting for current
- * input events to be dispatched.
- *
- * @param ev A motion event describing the keystroke action. (Be sure to use
- * {@link SystemClock#uptimeMillis()} as the timebase.)
- * @param sync If true, wait for the event to be completed before returning to the caller.
- * @return Returns true if event was dispatched, false if it was dropped for any reason
- */
- public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
- long downTime = ev.getDownTime();
- long eventTime = ev.getEventTime();
-
- int action = ev.getAction();
- int code = ev.getKeyCode();
- int repeatCount = ev.getRepeatCount();
- int metaState = ev.getMetaState();
- int deviceId = ev.getDeviceId();
- int scancode = ev.getScanCode();
- int source = ev.getSource();
- int flags = ev.getFlags();
-
- if (source == InputDevice.SOURCE_UNKNOWN) {
- source = InputDevice.SOURCE_KEYBOARD;
- }
-
- if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
- if (downTime == 0) downTime = eventTime;
- KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
- deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
-
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
-
- final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
- sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
- : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
- INJECTION_TIMEOUT_MILLIS);
-
- Binder.restoreCallingIdentity(ident);
- return reportInjectionResult(result, pid);
- }
-
- /**
- * Inject a pointer (touch) event into the UI.
- * Even when sync is false, this method may block while waiting for current
- * input events to be dispatched.
- *
- * @param ev A motion event describing the pointer (touch) action. (As noted in
- * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
- * {@link SystemClock#uptimeMillis()} as the timebase.)
- * @param sync If true, wait for the event to be completed before returning to the caller.
- * @return Returns true if event was dispatched, false if it was dropped for any reason
- */
- public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
-
- MotionEvent newEvent = MotionEvent.obtain(ev);
- if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
- newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
- }
-
- final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
- sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
- : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
- INJECTION_TIMEOUT_MILLIS);
-
- Binder.restoreCallingIdentity(ident);
- return reportInjectionResult(result, pid);
- }
-
- /**
- * Inject a trackball (navigation device) event into the UI.
- * Even when sync is false, this method may block while waiting for current
- * input events to be dispatched.
- *
- * @param ev A motion event describing the trackball action. (As noted in
- * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
- * {@link SystemClock#uptimeMillis()} as the timebase.)
- * @param sync If true, wait for the event to be completed before returning to the caller.
- * @return Returns true if event was dispatched, false if it was dropped for any reason
- */
- public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
-
- MotionEvent newEvent = MotionEvent.obtain(ev);
- if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
- newEvent.setSource(InputDevice.SOURCE_TRACKBALL);
- }
-
- final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
- sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
- : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
- INJECTION_TIMEOUT_MILLIS);
-
- Binder.restoreCallingIdentity(ident);
- return reportInjectionResult(result, pid);
- }
-
- /**
- * Inject an input event into the UI without waiting for dispatch to commence.
- * This variant is useful for fire-and-forget input event injection. It does not
- * block any longer than it takes to enqueue the input event.
- *
- * @param ev An input event. (Be sure to set the input source correctly.)
- * @return Returns true if event was dispatched, false if it was dropped for any reason
- */
- public boolean injectInputEventNoWait(InputEvent ev) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
-
- final int result = mInputManager.injectInputEvent(ev, pid, uid,
- InputManager.INPUT_EVENT_INJECTION_SYNC_NONE,
- INJECTION_TIMEOUT_MILLIS);
-
- Binder.restoreCallingIdentity(ident);
- return reportInjectionResult(result, pid);
- }
-
- private boolean reportInjectionResult(int result, int pid) {
- switch (result) {
- case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED:
- Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
- throw new SecurityException(
- "Injecting to another application requires INJECT_EVENTS permission");
- case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED:
- return true;
- case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT:
- Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
- return false;
- case InputManager.INPUT_EVENT_INJECTION_FAILED:
- default:
- Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
- return false;
- }
- }
-
- /**
- * Temporarily set the pointer speed. Does not save the new setting.
- * Used by the settings application.
- */
- public void setPointerSpeed(int speed) {
- if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
- "setPointerSpeed()")) {
- throw new SecurityException("Requires SET_POINTER_SPEED permission");
- }
-
- mInputManager.setPointerSpeed(speed);
+ sendScreenStatusToClients();
}
private WindowState getFocusedWindow() {
@@ -6509,11 +6328,29 @@ public class WindowManagerService extends IWindowManager.Stub
if (!mInputMonitor.waitForInputDevicesReady(
INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
Slog.w(TAG, "Devices still not ready after waiting "
- + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
- + " milliseconds before attempting to detect safe mode.");
+ + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
+ + " milliseconds before attempting to detect safe mode.");
+ }
+
+ final int BTN_MOUSE = 0x110;
+ int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
+ KeyEvent.KEYCODE_MENU);
+ int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
+ int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
+ KeyEvent.KEYCODE_DPAD_CENTER);
+ int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
+ BTN_MOUSE);
+ int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
+ KeyEvent.KEYCODE_VOLUME_DOWN);
+ mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
+ || volumeDownState > 0;
+ if (mSafeMode) {
+ Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
+ + " dpad=" + dpadState + " trackball=" + trackballState + ")");
+ } else {
+ Log.i(TAG, "SAFE MODE not enabled");
}
-
- mSafeMode = mPolicy.detectSafeMode();
+ mPolicy.setSafeMode(mSafeMode);
return mSafeMode;
}
@@ -6537,11 +6374,13 @@ 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(),
mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
- mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight);
+ mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
}
try {
@@ -6558,6 +6397,20 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.systemReady();
}
+ private void sendScreenStatusToClients() {
+ final ArrayList<WindowState> windows = mWindows;
+ final int count = windows.size();
+ boolean on = mPowerManager.isScreenOn();
+ for (int i = count - 1; i >= 0; i--) {
+ WindowState win = mWindows.get(i);
+ try {
+ win.mClient.dispatchScreenState(on);
+ } catch (RemoteException e) {
+ // Ignored
+ }
+ }
+ }
+
// This is an animation that does nothing: it just immediately finishes
// itself every time it is called. It is used as a stub animation in cases
// where we want to synchronize multiple things that may be animating.
@@ -6595,6 +6448,13 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
public static final int BOOT_TIMEOUT = 23;
public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
+ public static final int BULK_UPDATE_PARAMETERS = 25;
+
+ public static final int ANIMATOR_WHAT_OFFSET = 100000;
+ public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
+ public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2;
+ public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3;
+ public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4;
private Session mLastReportedHold;
@@ -6918,14 +6778,16 @@ public class WindowManagerService extends IWindowManager.Stub
case APP_FREEZE_TIMEOUT: {
synchronized (mWindowMap) {
- Slog.w(TAG, "App freeze timeout expired.");
- int i = mAppTokens.size();
- while (i > 0) {
- i--;
- AppWindowToken tok = mAppTokens.get(i);
- if (tok.freezingScreen) {
- Slog.w(TAG, "Force clearing freeze: " + tok);
- unsetAppFreezingScreenLocked(tok, true, true);
+ synchronized (mAnimator) {
+ Slog.w(TAG, "App freeze timeout expired.");
+ int i = mAppTokens.size();
+ while (i > 0) {
+ i--;
+ AppWindowToken tok = mAppTokens.get(i);
+ if (tok.mAppAnimator.freezingScreen) {
+ Slog.w(TAG, "Force clearing freeze: " + tok);
+ unsetAppFreezingScreenLocked(tok, true, true);
+ }
}
}
}
@@ -7005,6 +6867,67 @@ public class WindowManagerService extends IWindowManager.Stub
}
break;
}
+
+ case BULK_UPDATE_PARAMETERS: {
+ // Used to send multiple changes from the animation side to the layout side.
+ synchronized (mWindowMap) {
+ // TODO(cmautner): As the number of bits grows, use masks of bit groups to
+ // eliminate unnecessary tests.
+ if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+ mInnerFields.mUpdateRotation = true;
+ }
+ if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+ mInnerFields.mWallpaperMayChange = true;
+ }
+ if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+ mInnerFields.mWallpaperForceHidingChanged = true;
+ }
+ if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) {
+ mInnerFields.mOrientationChangeComplete = false;
+ }
+
+ requestTraversalLocked();
+ }
+ break;
+ }
+
+ // Animation messages. Move to Window{State}Animator
+ case SET_TRANSPARENT_REGION: {
+ Pair<WindowStateAnimator, Region> pair =
+ (Pair<WindowStateAnimator, Region>) msg.obj;
+ final WindowStateAnimator winAnimator = pair.first;
+ winAnimator.setTransparentRegionHint(pair.second);
+
+ scheduleAnimationLocked();
+ break;
+ }
+
+ case SET_WALLPAPER_OFFSET: {
+ final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
+ winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
+
+ scheduleAnimationLocked();
+ break;
+ }
+
+ case SET_DIM_PARAMETERS: {
+ mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
+
+ scheduleAnimationLocked();
+ break;
+ }
+
+ case SET_MOVE_ANIMATION: {
+ WindowAnimator.SetAnimationParams params =
+ (WindowAnimator.SetAnimationParams) msg.obj;
+ WindowStateAnimator winAnimator = params.mWinAnimator;
+ winAnimator.setAnimation(params.mAnimation);
+ winAnimator.mAnimDw = params.mAnimDw;
+ winAnimator.mAnimDh = params.mAnimDh;
+
+ scheduleAnimationLocked();
+ break;
+ }
}
}
}
@@ -7125,45 +7048,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) {
}
}
}
@@ -7195,7 +7105,7 @@ public class WindowManagerService extends IWindowManager.Stub
mBaseDisplayWidth = width;
mBaseDisplayHeight = height;
}
- mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight);
+ mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight);
mLayoutNeeded = true;
@@ -7214,7 +7124,7 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
- rebuildBlackFrame(false);
+ rebuildBlackFrame();
performLayoutAndPlaceSurfacesLocked();
}
@@ -7227,8 +7137,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- public boolean canStatusBarHide() {
- return mPolicy.canStatusBarHide();
+ public boolean hasSystemNavBar() {
+ return mPolicy.hasSystemNavBar();
}
// -------------------------------------------------------------
@@ -7364,19 +7274,21 @@ public class WindowManagerService extends IWindowManager.Stub
w.mLayer = curLayer;
}
if (w.mTargetAppToken != null) {
- w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
+ w.mWinAnimator.mAnimLayer =
+ w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
} else if (w.mAppToken != null) {
- w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
+ w.mWinAnimator.mAnimLayer =
+ w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment;
} else {
- w.mAnimLayer = w.mLayer;
+ w.mWinAnimator.mAnimLayer = w.mLayer;
}
if (w.mIsImWindow) {
- w.mAnimLayer += mInputMethodAnimLayerAdjustment;
+ w.mWinAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
} else if (w.mIsWallpaper) {
- w.mAnimLayer += mWallpaperAnimLayerAdjustment;
+ w.mWinAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
}
if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
- + w.mAnimLayer);
+ + w.mWinAnimator.mAnimLayer);
//System.out.println(
// "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
}
@@ -7452,10 +7364,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));
@@ -7599,7 +7526,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;
@@ -7616,295 +7543,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.
- * @return true if rotation has stopped, false otherwise
- */
- private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
- int innerDw, int innerDh) {
- int i;
- for (i = mWindows.size() - 1; i >= 0; i--) {
- mInnerFields.mAnimating |= mWindows.get(i).stepAnimationLocked(currentTime);
- }
-
- final int NAT = mAppTokens.size();
- for (i=0; i<NAT; i++) {
- mInnerFields.mAnimating |=
- mAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
- }
- final int NEAT = mExitingAppTokens.size();
- for (i=0; i<NEAT; i++) {
- mInnerFields.mAnimating |=
- mExitingAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
- }
-
- if (mScreenRotationAnimation != null) {
- if (mScreenRotationAnimation.isAnimating()) {
- if (mScreenRotationAnimation.stepAnimation(currentTime)) {
- mInnerFields.mUpdateRotation = false;
- mInnerFields.mAnimating = true;
- } else {
- mInnerFields.mUpdateRotation = true;
- mScreenRotationAnimation.kill();
- mScreenRotationAnimation = null;
- }
- }
- }
- }
-
- /**
- * 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) {
-
- mPolicy.beginAnimationLw(dw, dh);
-
- 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;
- }
- }
-
- // 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.mLocalAnimating;
-
- 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;
- }
-
- 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;
- 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;
- }
- }
-
- mPolicy.animatingWindowLw(w, attrs);
- }
-
- 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();
- }
- } // end forall windows
-
- return mPolicy.finishAnimationLw();
- }
-
- /**
- * 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.
*/
@@ -8066,27 +7704,44 @@ public class WindowManagerService extends IWindowManager.Stub
animLp = null;
}
+ AppWindowToken topOpeningApp = null;
+ int topOpeningLayer = 0;
+
+ // TODO(cmautner): Move to animation side.
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);
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
+ wtoken.mAppAnimator.clearThumbnail();
wtoken.reportedVisible = false;
wtoken.inPendingTransaction = false;
- wtoken.animation = null;
- setTokenVisibilityLocked(wtoken, animLp, true,
- transit, false);
+ wtoken.mAppAnimator.animation = null;
+ setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
- wtoken.showAllWindowsLocked();
+ mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+ if (animLp != null) {
+ int layer = -1;
+ for (int j=0; j<wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topOpeningApp == null || layer > topOpeningLayer) {
+ topOpeningApp = wtoken;
+ topOpeningLayer = layer;
+ }
+ }
}
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.mAppAnimator.clearThumbnail();
wtoken.inPendingTransaction = false;
- wtoken.animation = null;
+ wtoken.mAppAnimator.animation = null;
setTokenVisibilityLocked(wtoken, animLp, false,
transit, false);
wtoken.updateReportedVisibilityLocked();
@@ -8097,7 +7752,47 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.allDrawn = true;
}
+ if (mNextAppTransitionThumbnail != null && topOpeningApp != null
+ && topOpeningApp.mAppAnimator.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.mAppAnimator.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.mAppAnimator.thumbnailLayer = topOpeningLayer;
+ Animation anim = createThumbnailAnimationLocked(transit, true, true);
+ topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
+ anim.restrictDuration(MAX_ANIMATION_DURATION);
+ anim.scaleCurrentDuration(mTransitionAnimationScale);
+ topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX;
+ topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY;
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
+ + " h=" + dirty.height(), e);
+ topOpeningApp.mAppAnimator.clearThumbnail();
+ }
+ }
+
mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = null;
+ if (mNextAppTransitionCallback != null) {
+ try {
+ mNextAppTransitionCallback.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
mOpeningApps.clear();
mClosingApps.clear();
@@ -8168,27 +7863,26 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
- mInnerFields.mWallpaperMayChange = false;
- mInnerFields.mWallpaperForceHidingChanged = false;
if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
+ " NEW: " + mWallpaperTarget
+ " LOWER: " + mLowerWallpaperTarget);
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) {
+ if (w.mHasSurface) {
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.
- w.clearAnimation();
+ // TODO(cmautner): We lose the enter animation when this occurs.
+ w.mWinAnimator.clearAnimation();
}
}
}
@@ -8197,163 +7891,8 @@ public class WindowManagerService extends IWindowManager.Stub
return changes;
}
- /**
- * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
- * @return bitmap indicating if another pass through layout must be made.
- */
- private int testWallpaperAndBackgroundLocked() {
- int changes = 0;
-
- if (mWindowDetachedWallpaper != mInnerFields.mDetachedWallpaper) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Detached wallpaper changed from " + mWindowDetachedWallpaper
- + " to " + mInnerFields.mDetachedWallpaper);
- mWindowDetachedWallpaper = mInnerFields.mDetachedWallpaper;
- mInnerFields.mWallpaperMayChange = true;
- }
-
- if (mInnerFields.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) {
- for (int i=0; i<mWindows.size(); i++) {
- WindowState w = mWindows.get(i);
- if (w.mIsWallpaper) {
- target = w;
- break;
- }
- }
- }
- if (mWindowAnimationBackgroundSurface == null) {
- mWindowAnimationBackgroundSurface = new DimSurface(mFxSession);
- }
- final int dw = mCurDisplayWidth;
- final int dh = mCurDisplayHeight;
- mWindowAnimationBackgroundSurface.show(dw, dh,
- target.mAnimLayer - LAYER_OFFSET_DIM,
- mInnerFields.mWindowAnimationBackgroundColor);
- } else if (mWindowAnimationBackgroundSurface != null) {
- mWindowAnimationBackgroundSurface.hide();
- }
-
- if (mInnerFields.mWallpaperMayChange) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Wallpaper may change! Adjusting");
- mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
- }
-
- if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Wallpaper layer changed: assigning layers + relayout");
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
- assignLayersLocked();
- } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Wallpaper visibility changed: relayout");
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
- }
-
- if (mFocusMayChange) {
- mFocusMayChange = false;
- if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
- false /*updateInputWindows*/)) {
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
- mInnerFields.mAdjResult = 0;
- }
- }
-
- return changes;
- }
-
- /**
- * 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.
- 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);
- }
- }
- }
-
+ private void updateResizingWindows(final WindowState w) {
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
w.mContentInsetsChanged |=
!w.mLastContentInsets.equals(w.mContentInsets);
@@ -8373,13 +7912,13 @@ public class WindowManagerService extends IWindowManager.Stub
w.mLastFrame.set(w.mFrame);
if (w.mContentInsetsChanged
|| w.mVisibleInsetsChanged
- || w.mSurfaceResized
+ || winAnimator.mSurfaceResized
|| configChanged) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG, "Resize reasons: "
+ " contentInsetsChanged=" + w.mContentInsetsChanged
+ " visibleInsetsChanged=" + w.mVisibleInsetsChanged
- + " surfaceResized=" + w.mSurfaceResized
+ + " surfaceResized=" + w.mWinAnimator.mSurfaceResized
+ " configChanged=" + configChanged);
}
@@ -8394,131 +7933,26 @@ public class WindowManagerService extends IWindowManager.Stub
if (w.mOrientationChanging) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation start waiting for draw in "
- + w + ", surface " + w.mSurface);
- w.mDrawPending = true;
- w.mCommitDrawPending = false;
- w.mReadyToShow = false;
+ + w + ", surface " + w.mWinAnimator.mSurface);
+ winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
if (w.mAppToken != null) {
w.mAppToken.allDrawn = false;
}
}
if (!mResizingWindows.contains(w)) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
- "Resizing window " + w + " to " + w.mSurfaceW
- + "x" + w.mSurfaceH);
+ "Resizing window " + w + " to " + w.mWinAnimator.mSurfaceW
+ + "x" + w.mWinAnimator.mSurfaceH);
mResizingWindows.add(w);
}
} else if (w.mOrientationChanging) {
- if (!w.mDrawPending && !w.mCommitDrawPending) {
+ if (w.isDrawnLw()) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation not waiting for draw in "
- + w + ", surface " + w.mSurface);
- w.mOrientationChanging = false;
- }
- }
- }
-
- 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.mDrawPending
- && !w.mCommitDrawPending
- && !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.mDrawPending || w.mCommitDrawPending) {
- mInnerFields.mOrientationChangeComplete = false;
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation continue waiting for draw in " + w);
- } else {
+ + w + ", surface " + w.mWinAnimator.mSurface);
w.mOrientationChanging = false;
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation change complete in " + w);
}
}
- w.mToken.hasVisible = true;
}
}
@@ -8536,7 +7970,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int attrFlags = attrs.flags;
final boolean canBeSeen = w.isDisplayedLw();
- if (w.mSurface != null) {
+ if (w.mHasSurface) {
if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
mInnerFields.mHoldScreen = w.mSession;
}
@@ -8559,68 +7993,24 @@ 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);
- }
- mDimAnimator.show(innerDw, innerDh);
- 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;
- }
- }
+ } 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;
+ final int width, height;
+ if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
+ width = mCurDisplayWidth;
+ height = mCurDisplayHeight;
+ } else {
+ width = innerDw;
+ height = innerDh;
}
+ mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount,
+ width, height);
}
}
}
@@ -8657,12 +8047,11 @@ public class WindowManagerService extends IWindowManager.Stub
mExitingAppTokens.get(i).hasVisible = false;
}
- mInnerFields.mOrientationChangeComplete = true;
mInnerFields.mHoldScreen = null;
mInnerFields.mScreenBrightness = -1;
mInnerFields.mButtonBrightness = -1;
boolean focusDisplayed = false;
- mInnerFields.mAnimating = false;
+ mAnimator.mAnimating = false;
boolean createWatermark = false;
if (mFxSession == null) {
@@ -8686,9 +8075,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
try {
- mInnerFields.mWallpaperForceHidingChanged = false;
int repeats = 0;
- int changes = 0;
do {
repeats++;
@@ -8698,20 +8085,25 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
+ mPendingLayoutChanges);
+
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
assignLayersLocked();
mLayoutNeeded = true;
}
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
+
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (updateOrientationFromAppTokensLocked(true)) {
mLayoutNeeded = true;
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
mLayoutNeeded = true;
}
@@ -8722,101 +8114,34 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG, "Layout repeat skipped after too many iterations");
}
- ++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;
-
- 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;
+ // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+ // it is animating.
+ mPendingLayoutChanges = 0;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount,
+ mPendingLayoutChanges);
+ mPolicy.beginAnimationLw(dw, dh);
+ for (i = mWindows.size() - 1; i >= 0; i--) {
+ WindowState w = mWindows.get(i);
+ if (w.mHasSurface) {
+ mPolicy.animatingWindowLw(w, w.mAttrs);
+ }
}
+ mPendingLayoutChanges |= mPolicy.finishAnimationLw();
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw",
+ mPendingLayoutChanges);
+ } while (mPendingLayoutChanges != 0);
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
- + Integer.toHexString(changes));
- } while (changes != 0);
-
- // Update animations of all applications, including those
- // associated with exiting/removed apps
- mInnerFields.mAnimating = false;
-
- updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
-
- // THIRD LOOP: Update the surfaces of all windows.
-
- final boolean someoneLosingFocus = mLosingFocus.size() != 0;
+ final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
mInnerFields.mObscured = false;
- mInnerFields.mBlurring = false;
mInnerFields.mDimming = false;
mInnerFields.mSyswin = false;
-
+
final int N = mWindows.size();
-
for (i=N-1; i>=0; i--) {
WindowState w = mWindows.get(i);
- if (w.mSurface != null) {
- prepareSurfaceLocked(w, recoveringMemory);
- } else if (w.mOrientationChanging) {
- if (DEBUG_ORIENTATION) {
- Slog.v(TAG, "Orientation change skips hidden " + w);
- }
- w.mOrientationChanging = false;
- }
-
- if (w.mContentChanged) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
- w.mContentChanged = false;
- }
-
- final boolean canBeSeen = w.isDisplayedLw();
-
- if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
+ if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) {
focusDisplayed = true;
}
@@ -8835,37 +8160,135 @@ public class WindowManagerService extends IWindowManager.Stub
updateWallpaperVisibilityLocked();
}
}
+ if (!mInnerFields.mDimming && mAnimator.mDimParams != null) {
+ mAnimator.stopDimming();
+ }
+ } catch (RuntimeException e) {
+ Log.wtf(TAG, "Unhandled exception in Window Manager", e);
+ } finally {
+ Surface.closeTransaction();
+ }
- if (mDimAnimator != null && mDimAnimator.mDimShown) {
- mInnerFields.mAnimating |=
- mDimAnimator.updateSurface(mInnerFields.mDimming, currentTime,
- mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully());
+ // 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",
+ mPendingLayoutChanges);
+ }
+
+ 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",
+ mPendingLayoutChanges);
+ }
+
+ 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);
+ }
+ mInnerFields.mWallpaperForceHidingChanged = false;
+
+ if (mInnerFields.mWallpaperMayChange) {
+ if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+ "Wallpaper may change! Adjusting");
+ mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
+ }
+
+ if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Wallpaper layer changed: assigning layers + relayout");
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+ assignLayersLocked();
+ } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Wallpaper visibility changed: relayout");
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+ }
+
+ if (mFocusMayChange) {
+ mFocusMayChange = false;
+ if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ false /*updateInputWindows*/)) {
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
+ mInnerFields.mAdjResult = 0;
}
+ }
- 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 (mLayoutNeeded) {
+ mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges);
+ }
+
+ final int N = mWindows.size();
+ for (i=N-1; i>=0; i--) {
+ final WindowState w = mWindows.get(i);
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+ // If the window has moved due to its containing
+ // content frame changing, then we'd like to animate
+ // it.
+ if (w.mHasSurface && 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);
+ winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
+ winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+ } else {
+ winAnimator.mAnimDw = innerDw;
+ winAnimator.mAnimDh = innerDh;
}
- if (mBlackFrame != null) {
- if (mScreenRotationAnimation != null) {
- mBlackFrame.setMatrix(
- mScreenRotationAnimation.getEnterTransformation().getMatrix());
- } else {
- mBlackFrame.clearMatrix();
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+ w.mContentChanged = false;
+
+ // TODO(cmautner): Can this move up to the loop at the end of try/catch above?
+ updateResizingWindows(w);
+
+ // Moved from updateWindowsAndWallpaperLocked().
+ if (w.mHasSurface) {
+ // Take care of the window being ready to display.
+ if (winAnimator.commitFinishDrawingLocked(currentTime)) {
+ 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);
+ mInnerFields.mWallpaperMayChange = true;
+ mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+ debugLayoutRepeats("updateWindowsAndWallpaperLocked 1",
+ mPendingLayoutChanges);
+ }
+ }
}
}
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Unhandled exception in Window Manager", e);
}
- Surface.closeTransaction();
+ // Update animations of all applications, including those
+ // associated with exiting/removed apps
+ mAnimator.animate();
+ mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges;
+ if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()", mPendingLayoutChanges);
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -8885,11 +8308,10 @@ public class WindowManagerService extends IWindowManager.Stub
stopFreezingDisplayLocked();
}
- i = mResizingWindows.size();
- if (i > 0) {
- do {
- i--;
+ if (!mResizingWindows.isEmpty()) {
+ for (i = mResizingWindows.size() - 1; i >= 0; i--) {
WindowState win = mResizingWindows.get(i);
+ final WindowStateAnimator winAnimator = win.mWinAnimator;
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
"Reporting new frame to " + win + ": " + win.mCompatFrame);
@@ -8901,23 +8323,26 @@ public class WindowManagerService extends IWindowManager.Stub
if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
&& configChanged) {
Slog.i(TAG, "Sending new config to window " + win + ": "
- + win.mSurfaceW + "x" + win.mSurfaceH
+ + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
+ " / " + mCurConfiguration + " / 0x"
+ Integer.toHexString(diff));
}
win.mConfiguration = mCurConfiguration;
- if (DEBUG_ORIENTATION && win.mDrawPending) Slog.i(
+ if (DEBUG_ORIENTATION &&
+ winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
TAG, "Resizing " + win + " WITH DRAW PENDING");
- win.mClient.resized((int)win.mSurfaceW, (int)win.mSurfaceH,
- win.mLastContentInsets, win.mLastVisibleInsets, win.mDrawPending,
+ win.mClient.resized((int)winAnimator.mSurfaceW,
+ (int)winAnimator.mSurfaceH,
+ win.mLastContentInsets, win.mLastVisibleInsets,
+ winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
configChanged ? win.mConfiguration : null);
win.mContentInsetsChanged = false;
win.mVisibleInsetsChanged = false;
- win.mSurfaceResized = false;
+ winAnimator.mSurfaceResized = false;
} catch (RemoteException e) {
win.mOrientationChanging = false;
}
- } while (i > 0);
+ }
mResizingWindows.clear();
}
@@ -8935,7 +8360,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (win == mWallpaperTarget) {
wallpaperDestroyed = true;
}
- win.destroySurfaceLocked();
+ win.mWinAnimator.destroySurfaceLocked();
} while (i > 0);
mDestroySurface.clear();
}
@@ -8958,8 +8383,8 @@ 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.animation = null;
- token.animating = false;
+ token.mAppAnimator.clearAnimation();
+ token.mAppAnimator.animating = false;
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"performLayout: App token exiting now removed" + token);
mAppTokens.remove(token);
@@ -8967,9 +8392,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
@@ -8977,7 +8400,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.
@@ -8988,12 +8411,10 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
}
if (wallpaperDestroyed) {
- needRelayout = adjustWallpaperWindowsLocked() != 0;
+ 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.
@@ -9036,10 +8457,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (mInnerFields.mOrientationChangeComplete && !needRelayout &&
+ if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
!mInnerFields.mUpdateRotation) {
checkDrawnWindowsLocked();
}
+ mInnerFields.mOrientationChangeComplete = true;
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
@@ -9064,7 +8486,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mWaitingForDrawn.remove(pair);
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- } else if (win.mSurfaceShown) {
+ } else if (win.mWinAnimator.mSurfaceShown) {
// Window is now drawn (and shown).
try {
pair.second.sendResult(null);
@@ -9116,48 +8538,19 @@ public class WindowManagerService extends IWindowManager.Stub
void scheduleAnimationLocked() {
if (!mAnimationScheduled) {
- mChoreographer.postAnimationCallback(mAnimationRunnable);
+ mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
mAnimationScheduled = true;
}
}
- /**
- * Have the surface flinger show a surface, robustly dealing with
- * error conditions. In particular, if there is not enough memory
- * to show the surface, then we will try to get rid of other surfaces
- * in order to succeed.
- *
- * @return Returns true if the surface was successfully shown.
- */
- boolean showSurfaceRobustlyLocked(WindowState win) {
- try {
- if (win.mSurface != null) {
- win.mSurfaceShown = true;
- win.mSurface.show();
- if (win.mTurnOnScreen) {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "Show surface turning screen on: " + win);
- win.mTurnOnScreen = false;
- mTurnOnScreen = true;
- }
- }
- return true;
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e);
- }
-
- reclaimSomeSurfaceMemoryLocked(win, "show", true);
-
- return false;
- }
-
- boolean reclaimSomeSurfaceMemoryLocked(WindowState win, String operation, boolean secure) {
- final Surface surface = win.mSurface;
+ boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
+ boolean secure) {
+ final Surface surface = winAnimator.mSurface;
boolean leakedSurface = false;
boolean killedApps = false;
- EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
- win.mSession.mPid, operation);
+ EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
+ winAnimator.mSession.mPid, operation);
if (mForceRemoves == null) {
mForceRemoves = new ArrayList<WindowState>();
@@ -9172,29 +8565,34 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
for (int i=0; i<N; i++) {
WindowState ws = mWindows.get(i);
- if (ws.mSurface != null) {
- if (!mSessions.contains(ws.mSession)) {
+ WindowStateAnimator wsa = ws.mWinAnimator;
+ if (wsa.mSurface != null) {
+ if (!mSessions.contains(wsa.mSession)) {
Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
- + ws + " surface=" + ws.mSurface
- + " token=" + win.mToken
+ + ws + " surface=" + wsa.mSurface
+ + " token=" + ws.mToken
+ " pid=" + ws.mSession.mPid
+ " uid=" + ws.mSession.mUid);
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
- ws.mSurface.destroy();
- ws.mSurfaceShown = false;
- ws.mSurface = null;
+ wsa.mSurface.destroy();
+ wsa.mSurfaceShown = false;
+ wsa.mSurface = null;
+ ws.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(wsa);
mForceRemoves.add(ws);
i--;
N--;
leakedSurface = true;
} else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
- + ws + " surface=" + ws.mSurface
- + " token=" + win.mAppToken);
+ + ws + " surface=" + wsa.mSurface
+ + " token=" + ws.mAppToken);
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
- ws.mSurface.destroy();
- ws.mSurfaceShown = false;
- ws.mSurface = null;
+ wsa.mSurface.destroy();
+ wsa.mSurfaceShown = false;
+ wsa.mSurface = null;
+ ws.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(wsa);
leakedSurface = true;
}
}
@@ -9204,9 +8602,9 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG, "No leaked surfaces; killing applicatons!");
SparseIntArray pidCandidates = new SparseIntArray();
for (int i=0; i<N; i++) {
- WindowState ws = mWindows.get(i);
- if (ws.mSurface != null) {
- pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
+ WindowStateAnimator wsa = mWindows.get(i).mWinAnimator;
+ if (wsa.mSurface != null) {
+ pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
}
}
if (pidCandidates.size() > 0) {
@@ -9228,15 +8626,17 @@ public class WindowManagerService extends IWindowManager.Stub
// surface and ask the app to request another one.
Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
if (surface != null) {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(win,
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
"RECOVER DESTROY", null);
surface.destroy();
- win.mSurfaceShown = false;
- win.mSurface = null;
+ winAnimator.mSurfaceShown = false;
+ winAnimator.mSurface = null;
+ winAnimator.mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(winAnimator);
}
try {
- win.mClient.dispatchGetNewSurface();
+ winAnimator.mWin.mClient.dispatchGetNewSurface();
} catch (RemoteException e) {
}
}
@@ -9258,6 +8658,7 @@ public class WindowManagerService extends IWindowManager.Stub
TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
final WindowState oldFocus = mCurrentFocus;
mCurrentFocus = newFocus;
+ mAnimator.setCurrentFocus(newFocus);
mLosingFocus.remove(newFocus);
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
@@ -9304,12 +8705,11 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState result = null;
WindowState win;
- int i = mWindows.size() - 1;
int nextAppIndex = mAppTokens.size()-1;
WindowToken nextApp = nextAppIndex >= 0
? mAppTokens.get(nextAppIndex) : null;
- while (i >= 0) {
+ for (int i = mWindows.size() - 1; i >= 0; i--) {
win = mWindows.get(i);
if (localLOGV || DEBUG_FOCUS) Slog.v(
@@ -9322,7 +8722,6 @@ public class WindowManagerService extends IWindowManager.Stub
// If this window's application has been removed, just skip it.
if (thisApp != null && thisApp.removed) {
- i--;
continue;
}
@@ -9362,8 +8761,6 @@ public class WindowManagerService extends IWindowManager.Stub
result = win;
break;
}
-
- i--;
}
return result;
@@ -9389,6 +8786,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = null;
mAppTransitionReady = true;
}
@@ -9398,16 +8796,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,
- mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
- mDisplay.getRotation());
- }
- if (!mScreenRotationAnimation.hasScreenshot()) {
+
+ mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+ mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+ mDisplay.getRotation());
+
+ if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
}
} else {
@@ -9421,6 +8819,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+ if (DEBUG_ORIENTATION) Slog.d(TAG,
+ "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
+ + ", mAppsFreezingScreen=" + mAppsFreezingScreen
+ + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen);
return;
}
@@ -9432,20 +8834,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;
}
@@ -9622,11 +9024,6 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.lockNow();
}
- void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
- pw.println("WINDOW MANAGER INPUT (dumpsys window input)");
- mInputManager.dump(pw);
- }
-
void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) {
pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
mPolicy.dump(" ", fd, pw, args);
@@ -9667,8 +9064,8 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println();
pw.println(" Application tokens in Z order:");
for (int i=mAppTokens.size()-1; i>=0; i--) {
- pw.print(" App #"); pw.print(i); pw.print(": ");
- pw.println(mAppTokens.get(i));
+ pw.print(" App #"); pw.print(i); pw.println(": ");
+ mAppTokens.get(i).dump(pw, " ");
}
}
if (mFinishedStarting.size() > 0) {
@@ -9894,9 +9291,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
}
- if (mWindowDetachedWallpaper != null) {
- pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
- }
pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
if (mInputMethodAnimLayerAdjustment != 0 ||
@@ -9906,20 +9300,9 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mWallpaperAnimLayerAdjustment=");
pw.println(mWallpaperAnimLayerAdjustment);
}
- if (mWindowAnimationBackgroundSurface != null) {
- pw.println(" mWindowAnimationBackgroundSurface:");
- mWindowAnimationBackgroundSurface.printTo(" ", pw);
- }
pw.print(" mSystemBooted="); pw.print(mSystemBooted);
pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
- pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
- pw.print(" mBlurShown="); pw.println(mBlurShown);
- if (mDimAnimator != null) {
- pw.println(" mDimAnimator:");
- mDimAnimator.printTo(" ", pw);
- } else {
- pw.println( " no DimAnimator ");
- }
+ pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
@@ -9929,9 +9312,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);
@@ -9950,6 +9333,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);
}
@@ -9962,7 +9351,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
- if (w.mSurfaceShown) {
+ if (w.mWinAnimator.mSurfaceShown) {
windows.add(w);
}
}
@@ -10024,7 +9413,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println("Window manager dump options:");
pw.println(" [-a] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
- pw.println(" i[input]: input subsystem state");
pw.println(" p[policy]: policy state");
pw.println(" s[essions]: active sessions");
pw.println(" t[okens]: token list");
@@ -10045,10 +9433,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (opti < args.length) {
String cmd = args[opti];
opti++;
- if ("input".equals(cmd) || "i".equals(cmd)) {
- dumpInput(fd, pw, true);
- return;
- } else if ("policy".equals(cmd) || "p".equals(cmd)) {
+ if ("policy".equals(cmd) || "p".equals(cmd)) {
synchronized(mWindowMap) {
dumpPolicyLocked(fd, pw, args, true);
}
@@ -10083,8 +9468,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- dumpInput(fd, pw, dumpAll);
-
synchronized(mWindowMap) {
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -10117,4 +9500,20 @@ public class WindowManagerService extends IWindowManager.Stub
public interface OnHardKeyboardStatusChangeListener {
public void onHardKeyboardStatusChange(boolean available, boolean enabled);
}
+
+ void notifyAnimationChangedLayout(final int pendingLayoutChanges) {
+ mPendingLayoutChanges |= pendingLayoutChanges;
+ requestTraversalLocked();
+ }
+
+ void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
+ if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
+ Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
+ Integer.toHexString(pendingLayoutChanges));
+ }
+ }
+
+ void bulkSetParameters(final int bulkUpdateParams) {
+ mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams, 0));
+ }
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index eeecad1..4de6425 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -19,13 +19,13 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import com.android.server.wm.WindowManagerService.H;
+import com.android.server.input.InputWindowHandle;
+import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -39,14 +39,10 @@ import android.view.Gravity;
import android.view.IApplicationToken;
import android.view.IWindow;
import android.view.InputChannel;
-import android.view.Surface;
import android.view.View;
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;
import java.util.ArrayList;
@@ -55,18 +51,25 @@ import java.util.ArrayList;
* A window in the window manager.
*/
final class WindowState implements WindowManagerPolicy.WindowState {
+ static final String TAG = "WindowState";
+
static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC;
final WindowManagerService mService;
+ final WindowManagerPolicy mPolicy;
+ final Context mContext;
final Session mSession;
final IWindow mClient;
WindowToken mToken;
WindowToken mRootToken;
AppWindowToken mAppToken;
AppWindowToken mTargetAppToken;
+
+ // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
+ // modified they will need to be locked.
final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
final DeathRecipient mDeathRecipient;
final WindowState mAttachedWindow;
@@ -84,14 +87,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mPolicyVisibility = true;
boolean mPolicyVisibilityAfterAnim = true;
boolean mAppFreezing;
- Surface mSurface;
- Surface mPendingDestroySurface;
- boolean mReportDestroySurface;
- boolean mSurfacePendingDestroy;
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
@@ -99,18 +96,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
int mRequestedWidth;
int mRequestedHeight;
+ int mLastRequestedWidth;
+ int mLastRequestedHeight;
int mLayer;
- int mAnimLayer;
- int mLastLayer;
boolean mHaveFrame;
boolean mObscured;
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
@@ -119,18 +116,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
final RectF mShownFrame = new RectF();
/**
- * Set when we have changed the size of the surface, to know that
- * we must tell them application to resize (and thus redraw itself).
- */
- boolean mSurfaceResized;
-
- /**
- * Set if the client has asked that the destroy of its surface be delayed
- * until it explicitly says it is okay.
- */
- boolean mSurfaceDestroyDeferred;
-
- /**
* Insets that determine the actually visible area. These are in the application's
* coordinate space (without compatibility scale applied).
*/
@@ -178,11 +163,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
// Current transformation being applied.
- boolean mHaveMatrix;
float mGlobalScale=1;
float mInvGlobalScale=1;
- float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
- float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
float mHScale=1, mVScale=1;
float mLastHScale=1, mLastVScale=1;
final Matrix mTmpMatrix = new Matrix();
@@ -202,23 +184,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mContentChanged;
- float mShownAlpha = 1;
- float mAlpha = 1;
- float mLastAlpha = 1;
-
- // Set to true if, when the window gets displayed, it should perform
- // 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;
@@ -245,24 +210,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// when in that case until the layout is done.
boolean mLayoutNeeded;
- // This is set after the Surface has been created but before the
- // window has been drawn. During this time the surface is hidden.
- boolean mDrawPending;
-
- // This is set after the window has finished drawing for the first
- // time but before its surface is shown. The surface will be
- // displayed when the next layout is run.
- boolean mCommitDrawPending;
-
- // This is set during the time after the window's drawing has been
- // committed, and before its surface is actually shown. It is used
- // to delay showing the surface until all windows in a token are ready
- // to be shown.
- boolean mReadyToShow;
-
- // Set when the window has been shown in the screen the first time.
- boolean mHasDrawn;
-
// Currently running an exit animation?
boolean mExiting;
@@ -283,12 +230,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// rebuilding window list.
boolean mRebuilding;
- // For debugging, this is the last information given to the surface flinger.
- boolean mSurfaceShown;
- float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
- int mSurfaceLayer;
- float mSurfaceAlpha;
-
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
@@ -298,10 +239,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
CharSequence mLastTitle;
boolean mWasPaused;
- // Used to save animation distances between the time they are calculated and when they are
- // used.
- int mAnimDw;
- int mAnimDh;
+ final WindowStateAnimator mWinAnimator;
+
+ boolean mHasSurface = false;
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
@@ -312,12 +252,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mToken = token;
mAttrs.copyFrom(a);
mViewVisibility = viewVisibility;
+ mPolicy = mService.mPolicy;
+ mContext = mService.mContext;
DeathRecipient deathRecipient = new DeathRecipient();
- mAlpha = a.alpha;
mSeq = seq;
mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+ TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")");
try {
c.asBinder().linkToDeath(deathRecipient, 0);
@@ -331,6 +272,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mBaseLayer = 0;
mSubLayer = 0;
mInputWindowHandle = null;
+ mWinAnimator = null;
return;
}
mDeathRecipient = deathRecipient;
@@ -339,12 +281,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mAttrs.type <= LAST_SUB_WINDOW)) {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
- mBaseLayer = mService.mPolicy.windowTypeToLayerLw(
+ mBaseLayer = mPolicy.windowTypeToLayerLw(
attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ WindowManagerService.TYPE_LAYER_OFFSET;
- mSubLayer = mService.mPolicy.subWindowTypeToLayerLw(a.type);
+ mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
mAttachedWindow = attachedWindow;
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
mAttachedWindow.mChildWindows.add(this);
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -355,7 +297,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
} else {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
- mBaseLayer = mService.mPolicy.windowTypeToLayerLw(a.type)
+ mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
+ WindowManagerService.TYPE_LAYER_OFFSET;
mSubLayer = 0;
@@ -367,9 +309,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mIsFloatingLayer = mIsImWindow || mIsWallpaper;
}
+ mWinAnimator = new WindowStateAnimator(service, this, mAttachedWindow);
+ mWinAnimator.mAlpha = a.alpha;
+
WindowState appWin = this;
while (appWin.mAttachedWindow != null) {
- appWin = mAttachedWindow;
+ appWin = appWin.mAttachedWindow;
}
WindowToken appToken = appWin.mToken;
while (appToken.appWindowToken == null) {
@@ -382,25 +327,25 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mRootToken = appToken;
mAppToken = appToken.appWindowToken;
- mSurface = null;
mRequestedWidth = 0;
mRequestedHeight = 0;
+ mLastRequestedWidth = 0;
+ mLastRequestedHeight = 0;
mXOffset = 0;
mYOffset = 0;
mLayer = 0;
- mAnimLayer = 0;
- mLastLayer = 0;
mInputWindowHandle = new InputWindowHandle(
mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
}
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+ TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
+ @Override
public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
mHaveFrame = true;
@@ -452,6 +397,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mParentFrame.set(pf);
mContentChanged = true;
}
+ if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
+ mLastRequestedWidth = mRequestedWidth;
+ mLastRequestedHeight = mRequestedHeight;
+ mContentChanged = true;
+ }
final Rect content = mContentFrame;
content.set(cf);
@@ -528,7 +478,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (WindowManagerService.localLOGV) {
//if ("com.google.android.youtube".equals(mAttrs.packageName)
// && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
+ Slog.v(TAG, "Resolving (mRequestedWidth="
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ "): frame=" + mFrame.toShortString()
@@ -538,38 +488,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;
}
@@ -623,542 +582,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;
- mSurfacePendingDestroy = false;
- if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(WindowManagerService.TAG,
- "createSurface " + this + ": DRAW NOW PENDING");
- mDrawPending = true;
- mCommitDrawPending = false;
- mReadyToShow = false;
- if (mAppToken != null) {
- mAppToken.allDrawn = false;
- }
-
- mService.makeWindowFreezingScreenIfNeededLocked(this);
-
- int flags = 0;
-
- if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
- flags |= Surface.SECURE;
- }
- if (DEBUG_VISIBILITY) Slog.v(
- WindowManagerService.TAG, "Creating surface in session "
- + mSession.mSurfaceSession + " window " + this
- + " w=" + mCompatFrame.width()
- + " h=" + mCompatFrame.height() + " format="
- + mAttrs.format + " flags=" + flags);
-
- int w = mCompatFrame.width();
- int h = mCompatFrame.height();
- if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
- // for a scaled surface, we always want the requested
- // size.
- w = mRequestedWidth;
- h = mRequestedHeight;
- }
-
- // Something is wrong and SurfaceFlinger will not like this,
- // try to revert to sane values
- if (w <= 0) w = 1;
- if (h <= 0) h = 1;
-
- mSurfaceShown = false;
- mSurfaceLayer = 0;
- mSurfaceAlpha = 1;
- mSurfaceX = 0;
- mSurfaceY = 0;
- mSurfaceW = w;
- mSurfaceH = h;
- try {
- final boolean isHwAccelerated = (mAttrs.flags &
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
- final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
- if (!PixelFormat.formatHasAlpha(mAttrs.format)) {
- flags |= Surface.OPAQUE;
- }
- mSurface = new Surface(
- mSession.mSurfaceSession, mSession.mPid,
- mAttrs.getTitle().toString(),
- 0, w, h, format, flags);
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " CREATE SURFACE "
- + mSurface + " IN SESSION "
- + mSession.mSurfaceSession
- + ": pid=" + mSession.mPid + " format="
- + mAttrs.format + " flags=0x"
- + Integer.toHexString(flags)
- + " / " + this);
- } catch (Surface.OutOfResourcesException e) {
- Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface");
- mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
- return null;
- } catch (Exception e) {
- Slog.e(WindowManagerService.TAG, "Exception creating surface", e);
- return null;
- }
-
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Got surface: " + mSurface
- + ", set left=" + mFrame.left + " top=" + mFrame.top
- + ", animLayer=" + mAnimLayer);
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
- WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left
- + "," + mFrame.top + ") (" +
- mCompatFrame.width() + "x" + mCompatFrame.height() + "), layer=" +
- mAnimLayer + " HIDE", null);
- }
- Surface.openTransaction();
- try {
- try {
- mSurfaceX = mFrame.left + mXOffset;
- mSurfaceY = mFrame.top + mYOffset;
- mSurface.setPosition(mSurfaceX, mSurfaceY);
- mSurfaceLayer = mAnimLayer;
- mSurface.setLayer(mAnimLayer);
- mSurfaceShown = false;
- mSurface.hide();
- if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
- if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DITHER", null);
- mSurface.setFlags(Surface.SURFACE_DITHER,
- Surface.SURFACE_DITHER);
- }
- } catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e);
- mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
- }
- mLastHidden = true;
- } finally {
- Surface.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
- "<<< CLOSE TRANSACTION createSurfaceLocked");
- }
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Created surface " + this);
- }
- return mSurface;
- }
-
- void destroySurfaceLocked() {
- if (mAppToken != null && this == mAppToken.startingWindow) {
- mAppToken.startingDisplayed = false;
- }
-
- if (mSurface != null) {
- mDrawPending = false;
- mCommitDrawPending = false;
- mReadyToShow = false;
-
- int i = mChildWindows.size();
- while (i > 0) {
- i--;
- WindowState c = mChildWindows.get(i);
- c.mAttachedHidden = true;
- }
-
- if (mReportDestroySurface) {
- mReportDestroySurface = false;
- mSurfacePendingDestroy = true;
- try {
- mClient.dispatchGetNewSurface();
- // We'll really destroy on the next time around.
- return;
- } catch (RemoteException e) {
- }
- }
-
- try {
- if (DEBUG_VISIBILITY) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface "
- + mSurface + ", session " + mSession, e);
- }
- if (mSurfaceDestroyDeferred) {
- if (mSurface != null && mPendingDestroySurface != mSurface) {
- if (mPendingDestroySurface != null) {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- WindowManagerService.logSurface(this, "DESTROY PENDING", e);
- }
- mPendingDestroySurface.destroy();
- }
- mPendingDestroySurface = mSurface;
- }
- } else {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- WindowManagerService.logSurface(this, "DESTROY", e);
- }
- mSurface.destroy();
- }
- } catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this
- + " surface " + mSurface + " session " + mSession
- + ": " + e.toString());
- }
-
- mSurfaceShown = false;
- mSurface = null;
- }
- }
-
- void destroyDeferredSurfaceLocked() {
- try {
- if (mPendingDestroySurface != null) {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- mService.logSurface(this, "DESTROY PENDING", e);
- }
- mPendingDestroySurface.destroy();
- }
- } catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window "
- + this + " surface " + mPendingDestroySurface
- + " session " + mSession + ": " + e.toString());
- }
- mSurfaceDestroyDeferred = false;
- mPendingDestroySurface = null;
- }
-
- boolean finishDrawingLocked() {
- if (mDrawPending) {
- if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
- WindowManagerService.TAG, "finishDrawingLocked: " + this + " in " + mSurface);
- mCommitDrawPending = true;
- mDrawPending = false;
- return true;
- }
- return false;
- }
-
- // This must be called while inside a transaction.
- boolean commitFinishDrawingLocked(long currentTime) {
- //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
- if (!mCommitDrawPending) {
- return false;
- }
- mCommitDrawPending = false;
- mReadyToShow = true;
- final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
- final AppWindowToken atoken = mAppToken;
- if (atoken == null || atoken.allDrawn || starting) {
- performShowLocked();
- }
- return true;
- }
-
- // This must be called while inside a transaction.
- boolean performShowLocked() {
- if (DEBUG_VISIBILITY) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.v(WindowManagerService.TAG, "performShow on " + this
- + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
- + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
- }
- if (mReadyToShow && isReadyForDisplay()) {
- if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) WindowManagerService.logSurface(this,
- "SHOW (performShowLocked)", null);
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
- + " during animation: policyVis=" + mPolicyVisibility
- + " attHidden=" + mAttachedHidden
- + " tok.hiddenRequested="
- + (mAppToken != null ? mAppToken.hiddenRequested : false)
- + " tok.hidden="
- + (mAppToken != null ? mAppToken.hidden : false)
- + " animating=" + mAnimating
- + " tok animating="
- + (mAppToken != null ? mAppToken.animating : false));
- if (!mService.showSurfaceRobustlyLocked(this)) {
- return false;
- }
- mLastAlpha = -1;
- mHasDrawn = true;
- mLastHidden = false;
- mReadyToShow = false;
- mService.enableScreenIfNeededLocked();
-
- mService.applyEnterAnimationLocked(this);
-
- int i = mChildWindows.size();
- while (i > 0) {
- i--;
- WindowState c = mChildWindows.get(i);
- if (c.mAttachedHidden) {
- c.mAttachedHidden = false;
- if (c.mSurface != null) {
- c.performShowLocked();
- // It hadn't been shown, which means layout not
- // performed on it, so now we want to make sure to
- // do a layout. If called from within the transaction
- // loop, this will cause it to restart with a new
- // layout.
- mService.mLayoutNeeded = true;
- }
- }
- }
-
- if (mAttrs.type != TYPE_APPLICATION_STARTING
- && mAppToken != null) {
- mAppToken.firstWindowDrawn = true;
-
- if (mAppToken.startingData != null) {
- if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
- "Finish starting " + mToken
- + ": first real window is shown, no animation");
- // If this initial window is animating, stop it -- we
- // 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;
- // Make sure we clean up the animation.
- mAnimating = true;
- }
- mService.mFinishedStarting.add(mAppToken);
- mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
- }
- mAppToken.updateReportedVisibilityLocked();
- }
- }
- return true;
- }
-
- // 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 (!mDrawPending && !mCommitDrawPending && 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;
- }
- 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);
- if (more) {
- // we're not done!
- return true;
- }
- if (WindowManagerService.DEBUG_ANIM) Slog.v(
- WindowManagerService.TAG, "Finished animation in " + this +
- " @ " + currentTime);
-
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- }
- //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) {
- 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();
-
- 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;
- }
- }
-
boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
if (dsdx < .99999f || dsdx > 1.00001f) return false;
if (dtdy < .99999f || dtdy > 1.00001f) return false;
@@ -1176,147 +599,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
- void computeShownFrameLocked() {
- final boolean selfTransformation = mHasLocalTransformation;
- Transformation attachedTransformation =
- (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
- ? mAttachedWindow.mTransformation : null;
- Transformation appTransformation =
- (mAppToken != null && mAppToken.hasTransformation)
- ? mAppToken.transformation : null;
-
- // Wallpapers are animated based on the "real" window they
- // 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 (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
- Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation);
- }
- }
- if (mService.mWallpaperTarget.mAppToken != null &&
- mService.mWallpaperTarget.mAppToken.hasTransformation &&
- mService.mWallpaperTarget.mAppToken.animation != null &&
- !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
- appTransformation = mService.mWallpaperTarget.mAppToken.transformation;
- if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
- Slog.v(WindowManagerService.TAG, "WP target app xform: " + appTransformation);
- }
- }
- }
-
- final boolean screenAnimation = mService.mScreenRotationAnimation != null
- && mService.mScreenRotationAnimation.isAnimating();
- if (selfTransformation || attachedTransformation != null
- || appTransformation != null || screenAnimation) {
- // cache often used attributes locally
- final Rect frame = mFrame;
- final float tmpFloats[] = mService.mTmpFloats;
- final Matrix tmpMatrix = mTmpMatrix;
-
- // Compute the desired transformation.
- if (screenAnimation) {
- // If we are doing a screen animation, the global rotation
- // applied to windows can result in windows that are carefully
- // aligned with each other to slightly separate, allowing you
- // to see what is behind them. An unsightly mess. This...
- // thing... magically makes it call good: scale each window
- // slightly (two pixels larger in each dimension, from the
- // window's center).
- final float w = frame.width();
- final float h = frame.height();
- if (w>=1 && h>=1) {
- tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
- } else {
- tmpMatrix.reset();
- }
- } else {
- tmpMatrix.reset();
- }
- tmpMatrix.postScale(mGlobalScale, mGlobalScale);
- if (selfTransformation) {
- tmpMatrix.postConcat(mTransformation.getMatrix());
- }
- tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
- if (attachedTransformation != null) {
- tmpMatrix.postConcat(attachedTransformation.getMatrix());
- }
- if (appTransformation != null) {
- tmpMatrix.postConcat(appTransformation.getMatrix());
- }
- if (screenAnimation) {
- tmpMatrix.postConcat(
- mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
- }
-
- // "convert" it into SurfaceFlinger's format
- // (a 2x2 matrix + an offset)
- // Here we must not transform the position of the surface
- // since it is already included in the transformation.
- //Slog.i(TAG, "Transform: " + matrix);
-
- mHaveMatrix = true;
- tmpMatrix.getValues(tmpFloats);
- mDsDx = tmpFloats[Matrix.MSCALE_X];
- mDtDx = tmpFloats[Matrix.MSKEW_Y];
- mDsDy = tmpFloats[Matrix.MSKEW_X];
- mDtDy = tmpFloats[Matrix.MSCALE_Y];
- float x = tmpFloats[Matrix.MTRANS_X];
- float y = tmpFloats[Matrix.MTRANS_Y];
- int w = frame.width();
- int h = frame.height();
- mShownFrame.set(x, y, x+w, y+h);
-
- // Now set the alpha... but because our current hardware
- // can't do alpha transformation on a non-opaque surface,
- // turn it off if we are running an animation that is also
- // transforming since it is more important to have that
- // animation be smooth.
- mShownAlpha = mAlpha;
- if (!mService.mLimitedAlphaCompositing
- || (!PixelFormat.formatHasAlpha(mAttrs.format)
- || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
- && x == frame.left && y == frame.top))) {
- //Slog.i(TAG, "Applying alpha transform");
- if (selfTransformation) {
- mShownAlpha *= mTransformation.getAlpha();
- }
- if (attachedTransformation != null) {
- mShownAlpha *= attachedTransformation.getAlpha();
- }
- if (appTransformation != null) {
- mShownAlpha *= appTransformation.getAlpha();
- }
- if (screenAnimation) {
- mShownAlpha *=
- mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
- }
- } else {
- //Slog.i(TAG, "Not applying alpha transform");
- }
-
- if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Continuing animation in " + this +
- ": " + mShownFrame +
- ", alpha=" + mTransformation.getAlpha());
- return;
- }
-
- mShownFrame.set(mFrame);
- if (mXOffset != 0 || mYOffset != 0) {
- mShownFrame.offset(mXOffset, mYOffset);
- }
- mShownAlpha = mAlpha;
- mHaveMatrix = false;
- mDsDx = mGlobalScale;
- mDtDx = 0;
- mDsDy = 0;
- mDtDy = mGlobalScale;
- }
-
/**
* Is this window visible? It is not visible if there is no
* surface, or we are in the process of running an exit animation
@@ -1324,7 +606,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
public boolean isVisibleLw() {
final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
+ return mHasSurface && mPolicyVisibility && !mAttachedHidden
&& (atoken == null || !atoken.hiddenRequested)
&& !mExiting && !mDestroying;
}
@@ -1344,12 +626,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
final AppWindowToken atoken = mAppToken;
final boolean animating = atoken != null
- ? (atoken.animation != null) : false;
- return mSurface != null && !mDestroying && !mExiting
+ ? (atoken.mAppAnimator.animation != null) : false;
+ return mHasSurface && !mDestroying && !mExiting
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
&& !mRootToken.hidden)
- || mAnimation != null || animating);
+ || mWinAnimator.mAnimation != null || animating);
}
/**
@@ -1359,8 +641,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
public boolean isWinVisibleLw() {
final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
- && (atoken == null || !atoken.hiddenRequested || atoken.animating)
+ return mHasSurface && mPolicyVisibility && !mAttachedHidden
+ && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating)
&& !mExiting && !mDestroying;
}
@@ -1369,7 +651,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* the associated app token, not the pending requested hidden state.
*/
boolean isVisibleNow() {
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
+ return mHasSurface && mPolicyVisibility && !mAttachedHidden
&& !mRootToken.hidden && !mExiting && !mDestroying;
}
@@ -1389,7 +671,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
boolean isVisibleOrAdding() {
final AppWindowToken atoken = mAppToken;
- return ((mSurface != null && !mReportDestroySurface)
+ return ((mHasSurface && !mWinAnimator.mReportDestroySurface)
|| (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
&& mPolicyVisibility && !mAttachedHidden
&& (atoken == null || !atoken.hiddenRequested)
@@ -1402,15 +684,15 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* being visible.
*/
boolean isOnScreen() {
+ if (!mHasSurface || !mPolicyVisibility || mDestroying) {
+ return false;
+ }
final AppWindowToken atoken = mAppToken;
if (atoken != null) {
- return mSurface != null && mPolicyVisibility && !mDestroying
- && ((!mAttachedHidden && !atoken.hiddenRequested)
- || mAnimation != null || atoken.animation != null);
- } else {
- return mSurface != null && mPolicyVisibility && !mDestroying
- && (!mAttachedHidden || mAnimation != null);
+ return ((!mAttachedHidden && !atoken.hiddenRequested)
+ || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null);
}
+ return !mAttachedHidden || mWinAnimator.mAnimation != null;
}
/**
@@ -1422,29 +704,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
return false;
}
- final AppWindowToken atoken = mAppToken;
- final boolean animating = atoken != null
- ? (atoken.animation != null) : false;
- return mSurface != null && mPolicyVisibility && !mDestroying
+ return mHasSurface && mPolicyVisibility && !mDestroying
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
&& !mRootToken.hidden)
- || mAnimation != null || animating);
- }
-
- /** 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;
+ || mWinAnimator.mAnimation != null
+ || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
}
/**
@@ -1453,11 +717,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
public boolean isDisplayedLw() {
final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mDestroying
- && !mDrawPending && !mCommitDrawPending
+ return isDrawnLw() && mPolicyVisibility
&& ((!mAttachedHidden &&
(atoken == null || !atoken.hiddenRequested))
- || mAnimating);
+ || mWinAnimator.mAnimating);
}
public boolean isGoneForLayoutLw() {
@@ -1475,9 +738,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* complete UI in to.
*/
public boolean isDrawnLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && !mDestroying
- && !mDrawPending && !mCommitDrawPending;
+ return mHasSurface && !mDestroying &&
+ (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW
+ || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN);
}
/**
@@ -1487,9 +750,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean isOpaqueDrawn() {
return (mAttrs.format == PixelFormat.OPAQUE
|| mAttrs.type == TYPE_WALLPAPER)
- && mSurface != null && mAnimation == null
- && (mAppToken == null || mAppToken.animation == null)
- && !mDrawPending && !mCommitDrawPending;
+ && isDrawnLw() && mWinAnimator.mAnimation == null
+ && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
}
/**
@@ -1498,11 +760,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
* sense to call from performLayoutAndPlaceSurfacesLockedInner().)
*/
boolean shouldAnimateMove() {
- return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen
+ return mContentChanged && !mExiting && !mWinAnimator.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) {
@@ -1514,11 +775,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
disposeInputChannel();
if (mAttachedWindow != null) {
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
mAttachedWindow.mChildWindows.remove(this);
}
- destroyDeferredSurfaceLocked();
- destroySurfaceLocked();
+ mWinAnimator.destroyDeferredSurfaceLocked();
+ mWinAnimator.destroySurfaceLocked();
mSession.windowRemovedLocked();
try {
mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
@@ -1553,7 +814,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
try {
synchronized(mService.mWindowMap) {
WindowState win = mService.windowForClientLocked(mSession, mClient, false);
- Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
+ Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
mService.removeWindowLocked(mSession, win);
}
@@ -1572,25 +833,28 @@ final class WindowState implements WindowManagerPolicy.WindowState {
&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
}
+ @Override
public boolean hasDrawnLw() {
- return mHasDrawn;
+ return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
}
+ @Override
public boolean showLw(boolean doAnimation) {
return showLw(doAnimation, true);
}
boolean showLw(boolean doAnimation, boolean requestAnim) {
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
+ // Already showing.
return false;
}
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(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()) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
+ + 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.
@@ -1600,7 +864,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mPolicyVisibility = true;
mPolicyVisibilityAfterAnim = true;
if (doAnimation) {
- mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
+ mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
}
if (requestAnim) {
mService.scheduleAnimationLocked();
@@ -1608,31 +872,33 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true;
}
+ @Override
public boolean hideLw(boolean doAnimation) {
return hideLw(doAnimation, true);
}
boolean hideLw(boolean doAnimation, boolean requestAnim) {
if (doAnimation) {
- if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
+ if (!mService.okToDisplay()) {
doAnimation = false;
}
}
boolean current = doAnimation ? mPolicyVisibilityAfterAnim
: mPolicyVisibility;
if (!current) {
+ // Already hiding.
return false;
}
if (doAnimation) {
- mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
- if (mAnimation == null) {
+ mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
+ if (mWinAnimator.mAnimation == null) {
doAnimation = false;
}
}
if (doAnimation) {
mPolicyVisibilityAfterAnim = false;
} else {
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
mPolicyVisibilityAfterAnim = false;
mPolicyVisibility = false;
// Window is no longer visible -- make sure if we were waiting
@@ -1649,6 +915,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true;
}
+ @Override
+ public boolean isAlive() {
+ return mClient.asBinder().isBinderAlive();
+ }
+
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
outRegion.set(
frame.left + inset.left, frame.top + inset.top,
@@ -1684,6 +955,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
pw.print(" h="); pw.print(mRequestedHeight);
pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+ if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
+ pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
+ pw.print(" h="); pw.println(mLastRequestedHeight);
+ }
if (mAttachedWindow != null || mLayoutAttached) {
pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
@@ -1698,26 +973,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
pw.print(" mSubLayer="); pw.print(mSubLayer);
pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
- pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
- : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
- pw.print("="); pw.print(mAnimLayer);
- pw.print(" mLastLayer="); pw.println(mLastLayer);
- }
- if (mSurface != null) {
- if (dumpAll) {
- pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
- }
- pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
- pw.print(" layer="); pw.print(mSurfaceLayer);
- pw.print(" alpha="); pw.print(mSurfaceAlpha);
- pw.print(" rect=("); pw.print(mSurfaceX);
- pw.print(","); pw.print(mSurfaceY);
- pw.print(") "); pw.print(mSurfaceW);
- pw.print(" x "); pw.println(mSurfaceH);
- }
- if (mPendingDestroySurface != null) {
- pw.print(prefix); pw.print("mPendingDestroySurface=");
- pw.println(mPendingDestroySurface);
+ pw.print((mTargetAppToken != null ?
+ mTargetAppToken.mAppAnimator.animLayerAdjustment
+ : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0)));
+ pw.print("="); pw.print(mWinAnimator.mAnimLayer);
+ pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
}
if (dumpAll) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
@@ -1730,7 +990,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
pw.print(prefix); pw.print("mViewVisibility=0x");
pw.print(Integer.toHexString(mViewVisibility));
- pw.print(" mLastHidden="); pw.print(mLastHidden);
pw.print(" mHaveFrame="); pw.print(mHaveFrame);
pw.print(" mObscured="); pw.println(mObscured);
pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
@@ -1748,10 +1007,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
}
- if (mSurfaceResized || mSurfaceDestroyDeferred) {
- pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
- pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
- }
if (mXOffset != 0 || mYOffset != 0) {
pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
pw.print(" y="); pw.println(mYOffset);
@@ -1768,8 +1023,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
}
- pw.print(prefix); pw.print("mShownFrame=");
- mShownFrame.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
+ pw.print(" mShownFrame="); mShownFrame.printShortString(pw); pw.println();
if (dumpAll) {
pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
pw.print(" last="); mLastFrame.printShortString(pw);
@@ -1796,38 +1051,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();
- }
- if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
- pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
- pw.print(" mAlpha="); pw.print(mAlpha);
- pw.print(" mLastAlpha="); pw.println(mLastAlpha);
- }
- if (mHaveMatrix || mGlobalScale != 1) {
- pw.print(prefix); pw.print("mGlobalScale="); pw.print(mGlobalScale);
- pw.print(" mDsDx="); pw.print(mDsDx);
- pw.print(" mDtDx="); pw.print(mDtDx);
- pw.print(" mDsDy="); pw.print(mDsDy);
- pw.print(" mDtDy="); pw.println(mDtDy);
- }
- if (dumpAll) {
- pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
- pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
- pw.print(" mReadyToShow="); pw.print(mReadyToShow);
- pw.print(" mHasDrawn="); pw.println(mHasDrawn);
- }
+ mWinAnimator.dump(pw, prefix, dumpAll);
if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
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..220f5e0
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -0,0 +1,1231 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+
+import static com.android.server.wm.WindowManagerService.LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Transformation;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import java.io.PrintWriter;
+
+/**
+ * Keep track of animations and surface operations for a single WindowState.
+ **/
+class WindowStateAnimator {
+ static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
+ static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
+ static final boolean DEBUG_LAYERS = WindowManagerService.DEBUG_LAYERS;
+ static final boolean DEBUG_STARTING_WINDOW = WindowManagerService.DEBUG_STARTING_WINDOW;
+ static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
+ static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
+ static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC;
+ static final boolean localLOGV = WindowManagerService.localLOGV;
+ static final boolean DEBUG_ORIENTATION = WindowManagerService.DEBUG_ORIENTATION;
+
+ static final String TAG = "WindowStateAnimator";
+
+ final WindowManagerService mService;
+ final WindowState mWin;
+ final WindowState mAttachedWindow;
+ final WindowAnimator mAnimator;
+ final Session mSession;
+ final WindowManagerPolicy mPolicy;
+ final Context mContext;
+
+ // 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?
+ int mAnimLayer;
+ int mLastLayer;
+
+ Surface mSurface;
+ Surface mPendingDestroySurface;
+ boolean mReportDestroySurface;
+ boolean mSurfacePendingDestroy;
+
+ /**
+ * Set when we have changed the size of the surface, to know that
+ * we must tell them application to resize (and thus redraw itself).
+ */
+ boolean mSurfaceResized;
+
+ /**
+ * Set if the client has asked that the destroy of its surface be delayed
+ * until it explicitly says it is okay.
+ */
+ boolean mSurfaceDestroyDeferred;
+
+ float mShownAlpha = 1;
+ float mAlpha = 1;
+ float mLastAlpha = 1;
+
+ // Used to save animation distances between the time they are calculated and when they are
+ // used.
+ int mAnimDw;
+ int mAnimDh;
+ float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
+ float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
+
+ boolean mHaveMatrix;
+
+ // For debugging, this is the last information given to the surface flinger.
+ boolean mSurfaceShown;
+ float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
+ int mSurfaceLayer;
+ float mSurfaceAlpha;
+
+ // Set to true if, when the window gets displayed, it should perform
+ // an enter animation.
+ boolean mEnterAnimationPending;
+
+ /** This is set when there is no Surface */
+ static final int NO_SURFACE = 0;
+ /** This is set after the Surface has been created but before the window has been drawn. During
+ * this time the surface is hidden. */
+ static final int DRAW_PENDING = 1;
+ /** This is set after the window has finished drawing for the first time but before its surface
+ * is shown. The surface will be displayed when the next layout is run. */
+ static final int COMMIT_DRAW_PENDING = 2;
+ /** This is set during the time after the window's drawing has been committed, and before its
+ * surface is actually shown. It is used to delay showing the surface until all windows in a
+ * token are ready to be shown. */
+ static final int READY_TO_SHOW = 3;
+ /** Set when the window has been shown in the screen the first time. */
+ static final int HAS_DRAWN = 4;
+ int mDrawState;
+
+ /** Was this window last hidden? */
+ boolean mLastHidden;
+
+ int mAttrFlags;
+ int mAttrType;
+
+ public WindowStateAnimator(final WindowManagerService service, final WindowState win,
+ final WindowState attachedWindow) {
+ mService = service;
+ mWin = win;
+ mAttachedWindow = attachedWindow;
+ mAnimator = mService.mAnimator;
+ mSession = win.mSession;
+ mPolicy = mService.mPolicy;
+ mContext = mService.mContext;
+ mAttrFlags = win.mAttrs.flags;
+ mAttrType = win.mAttrs.type;
+ }
+
+ public void setAnimation(Animation anim) {
+ if (localLOGV) Slog.v(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(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.mAppAnimator.animation != null
+ || atoken.inPendingTransaction));
+ }
+
+ /** Is this window currently animating? */
+ boolean isWindowAnimating() {
+ return mAnimation != null;
+ }
+
+ void cancelExitAnimationForNextAnimationLocked() {
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ destroySurfaceLocked();
+ }
+ }
+
+ private boolean stepAnimation(long currentTime) {
+ if ((mAnimation == null) || !mLocalAnimating) {
+ return false;
+ }
+ mTransformation.clear();
+ final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
+ if (DEBUG_ANIM) Slog.v(
+ 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 (DEBUG_ANIM) Slog.v(
+ TAG, "Starting animation in " + this +
+ " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
+ " wh=" + mWin.mFrame.height() +
+ " dw=" + mAnimDw + " dh=" + mAnimDh +
+ " scale=" + mService.mWindowAnimationScale);
+ mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
+ mAnimDw, mAnimDh);
+ mAnimation.setStartTime(currentTime);
+ mLocalAnimating = true;
+ mAnimating = true;
+ }
+ if ((mAnimation != null) && mLocalAnimating) {
+ if (stepAnimation(currentTime)) {
+ return true;
+ }
+ }
+ if (DEBUG_ANIM) Slog.v(
+ TAG, "Finished animation in " + this +
+ " @ " + currentTime);
+ //WindowManagerService.this.dump();
+ }
+ mHasLocalTransformation = false;
+ if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null
+ && mWin.mAppToken.mAppAnimator.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;
+ }
+
+ // Done animating, clean up.
+ if (DEBUG_ANIM) Slog.v(
+ 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 (mAnimator.mWindowDetachedWallpaper == mWin) {
+ mAnimator.mWindowDetachedWallpaper = null;
+ }
+ mAnimLayer = mWin.mLayer;
+ if (mWin.mIsImWindow) {
+ mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
+ } else if (mWin.mIsWallpaper) {
+ mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+ }
+ if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
+ + " anim layer: " + mAnimLayer);
+ mHasTransformation = false;
+ mHasLocalTransformation = false;
+ if (mWin.mPolicyVisibility != mWin.mPolicyVisibilityAfterAnim) {
+ if (WindowState.DEBUG_VISIBILITY) {
+ Slog.v(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 (mDrawState == HAS_DRAWN
+ && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
+ && mWin.mAppToken != null
+ && mWin.mAppToken.firstWindowDrawn
+ && mWin.mAppToken.startingData != null) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
+ + mWin.mToken + ": first real window done animating");
+ mService.mFinishedStarting.add(mWin.mAppToken);
+ mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+
+ finishExit();
+ mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+ if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats(
+ "WindowStateAnimator", mAnimator.mPendingLayoutChanges);
+
+ if (mWin.mAppToken != null) {
+ mWin.mAppToken.updateReportedVisibilityLocked();
+ }
+
+ return false;
+ }
+
+ void finishExit() {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ 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(
+ TAG, "Exit animation finished in " + this
+ + ": remove=" + mWin.mRemoveOnExit);
+ if (mSurface != null) {
+ mService.mDestroySurface.add(mWin);
+ mWin.mDestroying = true;
+ if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface(
+ mWin, "HIDE (finishExit)", null);
+ mSurfaceShown = false;
+ try {
+ mSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error hiding surface in " + this, e);
+ }
+ mLastHidden = true;
+ }
+ mWin.mExiting = false;
+ if (mWin.mRemoveOnExit) {
+ mService.mPendingRemove.add(mWin);
+ mWin.mRemoveOnExit = false;
+ }
+ }
+
+ boolean finishDrawingLocked() {
+ if (mDrawState == DRAW_PENDING) {
+ if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
+ TAG, "finishDrawingLocked: " + this + " in " + mSurface);
+ mDrawState = COMMIT_DRAW_PENDING;
+ return true;
+ }
+ return false;
+ }
+
+ // This must be called while inside a transaction.
+ boolean commitFinishDrawingLocked(long currentTime) {
+ //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
+ if (mDrawState != COMMIT_DRAW_PENDING) {
+ return false;
+ }
+ mDrawState = READY_TO_SHOW;
+ final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING;
+ final AppWindowToken atoken = mWin.mAppToken;
+ if (atoken == null || atoken.allDrawn || starting) {
+ performShowLocked();
+ }
+ return true;
+ }
+
+ Surface createSurfaceLocked() {
+ if (mSurface == null) {
+ mReportDestroySurface = false;
+ mSurfacePendingDestroy = false;
+ if (DEBUG_ORIENTATION) Slog.i(TAG,
+ "createSurface " + this + ": DRAW NOW PENDING");
+ mDrawState = DRAW_PENDING;
+ if (mWin.mAppToken != null) {
+ mWin.mAppToken.allDrawn = false;
+ }
+
+ mService.makeWindowFreezingScreenIfNeededLocked(mWin);
+
+ int flags = 0;
+ final WindowManager.LayoutParams attrs = mWin.mAttrs;
+
+ if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ flags |= Surface.SECURE;
+ }
+ if (WindowState.DEBUG_VISIBILITY) Slog.v(
+ TAG, "Creating surface in session "
+ + mSession.mSurfaceSession + " window " + this
+ + " w=" + mWin.mCompatFrame.width()
+ + " h=" + mWin.mCompatFrame.height() + " format="
+ + attrs.format + " flags=" + flags);
+
+ int w = mWin.mCompatFrame.width();
+ int h = mWin.mCompatFrame.height();
+ if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+ // for a scaled surface, we always want the requested
+ // size.
+ w = mWin.mRequestedWidth;
+ h = mWin.mRequestedHeight;
+ }
+
+ // Something is wrong and SurfaceFlinger will not like this,
+ // try to revert to sane values
+ if (w <= 0) w = 1;
+ if (h <= 0) h = 1;
+
+ mSurfaceShown = false;
+ mSurfaceLayer = 0;
+ mSurfaceAlpha = 1;
+ mSurfaceX = 0;
+ mSurfaceY = 0;
+ mSurfaceW = w;
+ mSurfaceH = h;
+ try {
+ final boolean isHwAccelerated = (attrs.flags &
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+ final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
+ if (!PixelFormat.formatHasAlpha(attrs.format)) {
+ flags |= Surface.OPAQUE;
+ }
+ mSurface = new Surface(
+ mSession.mSurfaceSession, mSession.mPid,
+ attrs.getTitle().toString(),
+ 0, w, h, format, flags);
+ mWin.mHasSurface = true;
+ mAnimator.mWinAnimators.add(this);
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
+ " CREATE SURFACE "
+ + mSurface + " IN SESSION "
+ + mSession.mSurfaceSession
+ + ": pid=" + mSession.mPid + " format="
+ + attrs.format + " flags=0x"
+ + Integer.toHexString(flags)
+ + " / " + this);
+ } catch (Surface.OutOfResourcesException e) {
+ mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(this);
+ Slog.w(TAG, "OutOfResourcesException creating surface");
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
+ mDrawState = NO_SURFACE;
+ return null;
+ } catch (Exception e) {
+ mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(this);
+ Slog.e(TAG, "Exception creating surface", e);
+ mDrawState = NO_SURFACE;
+ return null;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ TAG, "Got surface: " + mSurface
+ + ", set left=" + mWin.mFrame.left + " top=" + mWin.mFrame.top
+ + ", animLayer=" + mAnimLayer);
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+ WindowManagerService.logSurface(mWin, "CREATE pos=("
+ + mWin.mFrame.left + "," + mWin.mFrame.top + ") ("
+ + mWin.mCompatFrame.width() + "x" + mWin.mCompatFrame.height()
+ + "), layer=" + mAnimLayer + " HIDE", null);
+ }
+ Surface.openTransaction();
+ try {
+ try {
+ mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
+ mSurfaceY = mWin.mFrame.top + mWin.mYOffset;
+ mSurface.setPosition(mSurfaceX, mSurfaceY);
+ mSurfaceLayer = mAnimLayer;
+ mSurface.setLayer(mAnimLayer);
+ mSurfaceShown = false;
+ mSurface.hide();
+ if ((mWin.mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
+ if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "DITHER", null);
+ mSurface.setFlags(Surface.SURFACE_DITHER, Surface.SURFACE_DITHER);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error creating surface in " + w, e);
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
+ }
+ mLastHidden = true;
+ } finally {
+ Surface.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION createSurfaceLocked");
+ }
+ if (WindowManagerService.localLOGV) Slog.v(
+ TAG, "Created surface " + this);
+ }
+ return mSurface;
+ }
+
+ void destroySurfaceLocked() {
+ if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) {
+ mWin.mAppToken.startingDisplayed = false;
+ }
+
+ mDrawState = NO_SURFACE;
+ if (mSurface != null) {
+
+ int i = mWin.mChildWindows.size();
+ while (i > 0) {
+ i--;
+ WindowState c = mWin.mChildWindows.get(i);
+ c.mAttachedHidden = true;
+ }
+
+ if (mReportDestroySurface) {
+ mReportDestroySurface = false;
+ mSurfacePendingDestroy = true;
+ try {
+ mWin.mClient.dispatchGetNewSurface();
+ // We'll really destroy on the next time around.
+ return;
+ } catch (RemoteException e) {
+ }
+ }
+
+ try {
+ if (DEBUG_VISIBILITY) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ Slog.w(TAG, "Window " + this + " destroying surface "
+ + mSurface + ", session " + mSession, e);
+ }
+ if (mSurfaceDestroyDeferred) {
+ if (mSurface != null && mPendingDestroySurface != mSurface) {
+ if (mPendingDestroySurface != null) {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
+ }
+ mPendingDestroySurface.destroy();
+ }
+ mPendingDestroySurface = mSurface;
+ }
+ } else {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ WindowManagerService.logSurface(mWin, "DESTROY", e);
+ }
+ mSurface.destroy();
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Exception thrown when destroying Window " + this
+ + " surface " + mSurface + " session " + mSession
+ + ": " + e.toString());
+ }
+
+ mSurfaceShown = false;
+ mSurface = null;
+ mWin.mHasSurface =false;
+ mAnimator.mWinAnimators.remove(this);
+ }
+ }
+
+ void destroyDeferredSurfaceLocked() {
+ try {
+ if (mPendingDestroySurface != null) {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
+ }
+ mPendingDestroySurface.destroy();
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Exception thrown when destroying Window "
+ + this + " surface " + mPendingDestroySurface
+ + " session " + mSession + ": " + e.toString());
+ }
+ mSurfaceDestroyDeferred = false;
+ mPendingDestroySurface = null;
+ }
+
+ void computeShownFrameLocked() {
+ final boolean selfTransformation = mHasLocalTransformation;
+ Transformation attachedTransformation =
+ (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation)
+ ? mAttachedWindow.mWinAnimator.mTransformation : null;
+ final AppWindowAnimator appAnimator =
+ mWin.mAppToken == null ? null : mWin.mAppToken.mAppAnimator;
+ Transformation appTransformation = (appAnimator != null && appAnimator.hasTransformation)
+ ? appAnimator.transformation : null;
+
+ // Wallpapers are animated based on the "real" window they
+ // are currently targeting.
+ if (mWin.mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
+ && mService.mWallpaperTarget != null) {
+ 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(TAG, "WP target attached xform: " + attachedTransformation);
+ }
+ }
+ final AppWindowAnimator wpAppAnimator = mService.mWallpaperTarget.mAppToken == null
+ ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
+ if (wpAppAnimator != null &&
+ wpAppAnimator.hasTransformation &&
+ wpAppAnimator.animation != null &&
+ !wpAppAnimator.animation.getDetachWallpaper()) {
+ appTransformation = wpAppAnimator.transformation;
+ if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
+ Slog.v(TAG, "WP target app xform: " + appTransformation);
+ }
+ }
+ }
+
+ final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null
+ && mService.mAnimator.mScreenRotationAnimation.isAnimating();
+ if (selfTransformation || attachedTransformation != null
+ || appTransformation != null || screenAnimation) {
+ // cache often used attributes locally
+ final Rect frame = mWin.mFrame;
+ final float tmpFloats[] = mService.mTmpFloats;
+ final Matrix tmpMatrix = mWin.mTmpMatrix;
+
+ // Compute the desired transformation.
+ if (screenAnimation) {
+ // If we are doing a screen animation, the global rotation
+ // applied to windows can result in windows that are carefully
+ // aligned with each other to slightly separate, allowing you
+ // to see what is behind them. An unsightly mess. This...
+ // thing... magically makes it call good: scale each window
+ // slightly (two pixels larger in each dimension, from the
+ // window's center).
+ final float w = frame.width();
+ final float h = frame.height();
+ if (w>=1 && h>=1) {
+ tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
+ } else {
+ tmpMatrix.reset();
+ }
+ } else {
+ tmpMatrix.reset();
+ }
+ tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
+ if (selfTransformation) {
+ tmpMatrix.postConcat(mTransformation.getMatrix());
+ }
+ tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
+ if (attachedTransformation != null) {
+ tmpMatrix.postConcat(attachedTransformation.getMatrix());
+ }
+ if (appTransformation != null) {
+ tmpMatrix.postConcat(appTransformation.getMatrix());
+ }
+ if (screenAnimation) {
+ tmpMatrix.postConcat(
+ mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+ }
+
+ // "convert" it into SurfaceFlinger's format
+ // (a 2x2 matrix + an offset)
+ // Here we must not transform the position of the surface
+ // since it is already included in the transformation.
+ //Slog.i(TAG, "Transform: " + matrix);
+
+ mHaveMatrix = true;
+ tmpMatrix.getValues(tmpFloats);
+ mDsDx = tmpFloats[Matrix.MSCALE_X];
+ mDtDx = tmpFloats[Matrix.MSKEW_Y];
+ mDsDy = tmpFloats[Matrix.MSKEW_X];
+ mDtDy = tmpFloats[Matrix.MSCALE_Y];
+ float x = tmpFloats[Matrix.MTRANS_X];
+ float y = tmpFloats[Matrix.MTRANS_Y];
+ int w = frame.width();
+ int h = frame.height();
+ mWin.mShownFrame.set(x, y, x+w, y+h);
+
+ // Now set the alpha... but because our current hardware
+ // can't do alpha transformation on a non-opaque surface,
+ // turn it off if we are running an animation that is also
+ // transforming since it is more important to have that
+ // animation be smooth.
+ mShownAlpha = mAlpha;
+ if (!mService.mLimitedAlphaCompositing
+ || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
+ || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
+ && x == frame.left && y == frame.top))) {
+ //Slog.i(TAG, "Applying alpha transform");
+ if (selfTransformation) {
+ mShownAlpha *= mTransformation.getAlpha();
+ }
+ if (attachedTransformation != null) {
+ mShownAlpha *= attachedTransformation.getAlpha();
+ }
+ if (appTransformation != null) {
+ mShownAlpha *= appTransformation.getAlpha();
+ }
+ if (screenAnimation) {
+ mShownAlpha *=
+ mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+ }
+ } else {
+ //Slog.i(TAG, "Not applying alpha transform");
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ TAG, "computeShownFrameLocked: Animating " + this +
+ ": " + mWin.mShownFrame +
+ ", alpha=" + mTransformation.getAlpha() + ", mShownAlpha=" + mShownAlpha);
+ return;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ TAG, "computeShownFrameLocked: " + this +
+ " not attached, mAlpha=" + mAlpha);
+ mWin.mShownFrame.set(mWin.mFrame);
+ if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
+ mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+ }
+ mShownAlpha = mAlpha;
+ mHaveMatrix = false;
+ mDsDx = mWin.mGlobalScale;
+ mDtDx = 0;
+ mDsDy = 0;
+ mDtDy = mWin.mGlobalScale;
+ }
+
+ public void prepareSurfaceLocked(final boolean recoveringMemory) {
+ final WindowState w = mWin;
+ if (mSurface == null) {
+ if (w.mOrientationChanging) {
+ if (DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Orientation change skips hidden " + w);
+ }
+ w.mOrientationChanging = false;
+ }
+ return;
+ }
+
+ boolean displayed = false;
+
+ 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 = mSurfaceW != width || mSurfaceH != height;
+ if (surfaceResized) {
+ mSurfaceW = width;
+ mSurfaceH = height;
+ }
+
+ if (mSurfaceX != w.mShownFrame.left
+ || mSurfaceY != w.mShownFrame.top) {
+ try {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "POS " + w.mShownFrame.left
+ + ", " + w.mShownFrame.top, null);
+ mSurfaceX = w.mShownFrame.left;
+ mSurfaceY = w.mShownFrame.top;
+ 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(this, "position", true);
+ }
+ }
+ }
+
+ if (surfaceResized) {
+ try {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "SIZE " + width + "x" + height, null);
+ mSurfaceResized = true;
+ 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(this, "size", true);
+ }
+ }
+ }
+
+ if (w.mAttachedHidden || !w.isReadyForDisplay()) {
+ if (!mLastHidden) {
+ //dump();
+ mLastHidden = true;
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "HIDE (performLayout)", null);
+ if (mSurface != null) {
+ mSurfaceShown = false;
+ try {
+ 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 (mLastLayer != mAnimLayer
+ || mLastAlpha != mShownAlpha
+ || mLastDsDx != mDsDx
+ || mLastDtDx != mDtDx
+ || mLastDsDy != mDsDy
+ || mLastDtDy != mDtDy
+ || w.mLastHScale != w.mHScale
+ || w.mLastVScale != w.mVScale
+ || mLastHidden) {
+ displayed = true;
+ mLastAlpha = mShownAlpha;
+ mLastLayer = mAnimLayer;
+ mLastDsDx = mDsDx;
+ mLastDtDx = mDtDx;
+ mLastDsDy = mDsDy;
+ mLastDtDy = mDtDy;
+ w.mLastHScale = w.mHScale;
+ w.mLastVScale = w.mVScale;
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "alpha=" + mShownAlpha + " layer=" + mAnimLayer
+ + " matrix=[" + (mDsDx*w.mHScale)
+ + "," + (mDtDx*w.mVScale)
+ + "][" + (mDsDy*w.mHScale)
+ + "," + (mDtDy*w.mVScale) + "]", null);
+ if (mSurface != null) {
+ try {
+ mSurfaceAlpha = mShownAlpha;
+ mSurface.setAlpha(mShownAlpha);
+ mSurfaceLayer = w.mWinAnimator.mAnimLayer;
+ mSurface.setLayer(w.mWinAnimator.mAnimLayer);
+ mSurface.setMatrix(
+ mDsDx*w.mHScale, mDtDx*w.mVScale,
+ mDsDy*w.mHScale, mDtDy*w.mVScale);
+
+ if (mLastHidden && mDrawState == HAS_DRAWN) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "SHOW (performLayout)", null);
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
+ + " during relayout");
+ if (showSurfaceRobustlyLocked()) {
+ mLastHidden = false;
+ } else {
+ w.mOrientationChanging = false;
+ }
+ }
+ if (mSurface != null) {
+ w.mToken.hasVisible = true;
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error updating surface in " + w, e);
+ if (!recoveringMemory) {
+ mService.reclaimSomeSurfaceMemoryLocked(this, "update", true);
+ }
+ }
+ }
+ } else {
+ displayed = true;
+ }
+
+ if (displayed) {
+ if (w.mOrientationChanging) {
+ if (!w.isDrawnLw()) {
+ mAnimator.mBulkUpdateParams |= CLEAR_ORIENTATION_CHANGE_COMPLETE;
+ 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;
+ }
+ }
+
+ void setTransparentRegionHint(final Region region) {
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION setTransparentRegion");
+ Surface.openTransaction();
+ try {
+ if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
+ "transparentRegionHint=" + region, null);
+ mSurface.setTransparentRegionHint(region);
+ } finally {
+ Surface.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION setTransparentRegion");
+ }
+ }
+
+ void setWallpaperOffset(int left, int top) {
+ Surface.openTransaction();
+ try {
+ mSurfaceX = left;
+ mSurfaceY = top;
+ mSurface.setPosition(left, top);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error positioning surface of " + mWin
+ + " pos=(" + left + "," + top + ")", e);
+ }
+ Surface.closeTransaction();
+ }
+
+ // This must be called while inside a transaction.
+ boolean performShowLocked() {
+ if (DEBUG_VISIBILITY) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ Slog.v(TAG, "performShow on " + this
+ + ": mDrawState=" + mDrawState + " readyForDisplay="
+ + mWin.isReadyForDisplay()
+ + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING), e);
+ }
+ if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplay()) {
+ if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
+ WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ + " during animation: policyVis=" + mWin.mPolicyVisibility
+ + " attHidden=" + mWin.mAttachedHidden
+ + " tok.hiddenRequested="
+ + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
+ + " tok.hidden="
+ + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
+ + " animating=" + mAnimating
+ + " tok animating="
+ + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false));
+ if (!showSurfaceRobustlyLocked()) {
+ return false;
+ }
+
+ mService.enableScreenIfNeededLocked();
+
+ applyEnterAnimationLocked();
+
+ mLastAlpha = -1;
+ mLastHidden = false;
+ mDrawState = HAS_DRAWN;
+
+ int i = mWin.mChildWindows.size();
+ while (i > 0) {
+ i--;
+ WindowState c = mWin.mChildWindows.get(i);
+ if (c.mAttachedHidden) {
+ c.mAttachedHidden = false;
+ if (c.mWinAnimator.mSurface != null) {
+ c.mWinAnimator.performShowLocked();
+ // It hadn't been shown, which means layout not
+ // performed on it, so now we want to make sure to
+ // do a layout. If called from within the transaction
+ // loop, this will cause it to restart with a new
+ // layout.
+ mService.mLayoutNeeded = true;
+ }
+ }
+ }
+
+ if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING
+ && mWin.mAppToken != null) {
+ mWin.mAppToken.firstWindowDrawn = true;
+
+ if (mWin.mAppToken.startingData != null) {
+ if (WindowManagerService.DEBUG_STARTING_WINDOW ||
+ WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
+ "Finish starting " + mWin.mToken
+ + ": first real window is shown, no animation");
+ // If this initial window is animating, stop it -- we
+ // 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;
+ // Make sure we clean up the animation.
+ mAnimating = true;
+ }
+ mService.mFinishedStarting.add(mWin.mAppToken);
+ mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+ mWin.mAppToken.updateReportedVisibilityLocked();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Have the surface flinger show a surface, robustly dealing with
+ * error conditions. In particular, if there is not enough memory
+ * to show the surface, then we will try to get rid of other surfaces
+ * in order to succeed.
+ *
+ * @return Returns true if the surface was successfully shown.
+ */
+ boolean showSurfaceRobustlyLocked() {
+ try {
+ if (mSurface != null) {
+ mSurfaceShown = true;
+ mSurface.show();
+ if (mWin.mTurnOnScreen) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG,
+ "Show surface turning screen on: " + mWin);
+ mWin.mTurnOnScreen = false;
+ mService.mTurnOnScreen = true;
+ }
+ }
+ return true;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure showing surface " + mSurface + " in " + mWin, e);
+ }
+
+ mService.reclaimSomeSurfaceMemoryLocked(this, "show", true);
+
+ return false;
+ }
+
+ void applyEnterAnimationLocked() {
+ final int transit;
+ if (mEnterAnimationPending) {
+ mEnterAnimationPending = false;
+ transit = WindowManagerPolicy.TRANSIT_ENTER;
+ } else {
+ transit = WindowManagerPolicy.TRANSIT_SHOW;
+ }
+
+ applyAnimationLocked(transit, true);
+ }
+
+ // TODO(cmautner): Move back to WindowState?
+ /**
+ * Choose the correct animation and set it to the passed WindowState.
+ * @param transit If WindowManagerPolicy.TRANSIT_PREVIEW_DONE and the app window has been drawn
+ * then the animation will be app_starting_exit. Any other value loads the animation from
+ * the switch statement below.
+ * @param isEntrance The animation type the last time this was called. Used to keep from
+ * loading the same animation twice.
+ * @return true if an animation has been loaded.
+ */
+ boolean applyAnimationLocked(int transit, boolean isEntrance) {
+ if (mLocalAnimating && 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;
+ }
+
+ // 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 (mService.okToDisplay()) {
+ int anim = mPolicy.selectAnimationLw(mWin, transit);
+ int attr = -1;
+ Animation a = null;
+ if (anim != 0) {
+ a = AnimationUtils.loadAnimation(mContext, anim);
+ } else {
+ switch (transit) {
+ case WindowManagerPolicy.TRANSIT_ENTER:
+ attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
+ break;
+ case WindowManagerPolicy.TRANSIT_EXIT:
+ attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
+ break;
+ case WindowManagerPolicy.TRANSIT_SHOW:
+ attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
+ break;
+ case WindowManagerPolicy.TRANSIT_HIDE:
+ attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
+ break;
+ }
+ if (attr >= 0) {
+ a = mService.loadAnimation(mWin.mAttrs, attr);
+ }
+ }
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
+ "applyAnimation: win=" + this
+ + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ + " mAnimation=" + mAnimation
+ + " isEntrance=" + isEntrance);
+ if (a != null) {
+ if (WindowManagerService.DEBUG_ANIM) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
+ }
+ setAnimation(a);
+ mAnimationIsEntrance = isEntrance;
+ }
+ } else {
+ clearAnimation();
+ }
+
+ return mAnimation != null;
+ }
+
+ 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();
+ }
+ if (mSurface != null) {
+ if (dumpAll) {
+ pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+ pw.print(prefix); pw.print("mDrawState="); pw.print(mDrawState);
+ pw.print(" mLastHidden="); pw.println(mLastHidden);
+ }
+ pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
+ pw.print(" layer="); pw.print(mSurfaceLayer);
+ pw.print(" alpha="); pw.print(mSurfaceAlpha);
+ pw.print(" rect=("); pw.print(mSurfaceX);
+ pw.print(","); pw.print(mSurfaceY);
+ pw.print(") "); pw.print(mSurfaceW);
+ pw.print(" x "); pw.println(mSurfaceH);
+ }
+ if (mPendingDestroySurface != null) {
+ pw.print(prefix); pw.print("mPendingDestroySurface=");
+ pw.println(mPendingDestroySurface);
+ }
+ if (mSurfaceResized || mSurfaceDestroyDeferred) {
+ pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
+ pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
+ }
+ if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
+ pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
+ pw.print(" mAlpha="); pw.print(mAlpha);
+ pw.print(" mLastAlpha="); pw.println(mLastAlpha);
+ }
+ if (mHaveMatrix || mWin.mGlobalScale != 1) {
+ pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
+ pw.print(" mDsDx="); pw.print(mDsDx);
+ pw.print(" mDtDx="); pw.print(mDtDx);
+ pw.print(" mDsDy="); pw.print(mDsDy);
+ pw.print(" mDtDy="); pw.println(mDtDy);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer("WindowStateAnimator (");
+ sb.append(mWin.mLastTitle + "): ");
+ sb.append("mSurface " + mSurface);
+ sb.append(", mAnimation " + mAnimation);
+ return sb.toString();
+ }
+}