diff options
10 files changed, 112 insertions, 49 deletions
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java index eeb6cba7c68e..4af0f51a41e2 100644 --- a/core/java/android/transition/TransitionInflater.java +++ b/core/java/android/transition/TransitionInflater.java @@ -169,7 +169,7 @@ public class TransitionInflater { } else if ("recolor".equals(name)) { transition = new Recolor(); newTransition = true; - } else if ("set".equals(name)) { + } else if ("transitionSet".equals(name)) { transition = new TransitionSet(); TypedArray a = mContext.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TransitionSet); diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index 79cd8b693df2..4545e3b51fc9 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -30,6 +30,22 @@ import java.util.ArrayList; * others play {@link #ORDERING_SEQUENTIAL}. For example, {@link AutoTransition} * uses a TransitionSet to sequentially play a Fade(Fade.OUT), followed by * a {@link ChangeBounds}, followed by a Fade(Fade.OUT) transition. + * + * <p>A TransitionSet can be described in a resource file by using the + * tag <code>transitionSet</code>, along with the standard + * attributes of {@link android.R.styleable#TransitionSet} and + * {@link android.R.styleable#Transition}. Child transitions of the + * TransitionSet object can be loaded by adding those child tags inside the + * enclosing <code>transitionSet</code> tag. For example, the following xml + * describes a TransitionSet that plays a Fade and then a ChangeBounds + * transition on the affected view targets:</p> + * <pre> + * <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" + * android:ordering="sequential"> + * <fade/> + * <changeBounds/> + * </transitionSet> + * </pre> */ public class TransitionSet extends Transition { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 04885f0b076f..6e5336384d44 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -391,7 +391,7 @@ public class NavigationBarView extends LinearLayout { final AccessibilityManager accessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - if (accessibilityManager.isEnabled()) { + if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) { // In accessibility mode, we add a simple click handler since swipe is tough to // trigger near screen edges. View camera = getCameraButton(); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index f23bcba6f04a..b3fe8f6d47eb 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3193,6 +3193,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (task.userId == tr.userId && ((task.affinity != null && task.affinity.equals(tr.affinity)) || (task.intent != null && task.intent.filterEquals(tr.intent)))) { + tr.disposeThumbnail(); mRecentTasks.remove(i); i--; N--; @@ -3204,7 +3205,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (N >= MAX_RECENT_TASKS) { - mRecentTasks.remove(N-1); + mRecentTasks.remove(N-1).disposeThumbnail(); } mRecentTasks.add(0, task); } @@ -6738,6 +6739,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) { + tr.disposeThumbnail(); mRecentTasks.remove(tr); mStackSupervisor.removeTask(tr); final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0; @@ -15818,9 +15820,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } - boolean haveActivities = mStackSupervisor.switchUserLocked(userId, uss); - if (!haveActivities) { + boolean homeInFront = mStackSupervisor.switchUserLocked(userId, uss); + if (homeInFront) { startHomeActivityLocked(userId); + } else { + mStackSupervisor.resumeTopActivitiesLocked(); } EventLogTags.writeAmSwitchUser(userId); @@ -16146,6 +16150,8 @@ public final class ActivityManagerService extends ActivityManagerNative } catch (RemoteException e) { } } + + mStackSupervisor.removeUserLocked(userId); } @Override diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 2c0b83bef0b8..cf686672a2a3 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -572,8 +572,8 @@ final class ActivityRecord { } boolean isRootActivity() { - ArrayList<ActivityRecord> activities = task.mActivities; - return activities.size() == 0 || this == task.mActivities.get(0); + final ArrayList<ActivityRecord> activities = task.mActivities; + return activities.size() == 0 || this == activities.get(0); } UriPermissionOwner getUriPermissionsLocked() { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 45b30f1cf60a..422e2b180a06 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -549,31 +549,26 @@ final class ActivityStack { /* * Move the activities around in the stack to bring a user to the foreground. - * @return whether there are any activities for the specified user. */ - final boolean switchUserLocked(int userId) { + final void switchUserLocked(int userId) { if (VALIDATE_TOKENS) { validateAppTokensLocked(); } if (mCurrentUser == userId) { - return true; + return; } mCurrentUser = userId; // Move userId's tasks to the top. - boolean haveActivities = false; int index = mTaskHistory.size(); for (int i = 0; i < index; ++i) { TaskRecord task = mTaskHistory.get(i); if (task.userId == userId) { - haveActivities = true; mTaskHistory.remove(i); mTaskHistory.add(task); --index; } } - - return haveActivities; } void minimalResumeActivityLocked(ActivityRecord r) { @@ -678,6 +673,14 @@ final class ActivityStack { return null; } + TaskRecord tr = who.task; + if (tr.intent != null && (tr.intent.getFlags() + &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0) { + // If this task is being excluded from recents, we don't want to take + // the expense of capturing a thumbnail, since we will never show it. + return null; + } + Resources res = mService.mContext.getResources(); int w = mThumbnailWidth; int h = mThumbnailHeight; @@ -690,6 +693,7 @@ final class ActivityStack { if (w > 0) { if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null + || mLastScreenshotActivity.state == ActivityState.RESUMED || mLastScreenshotBitmap.getWidth() != w || mLastScreenshotBitmap.getHeight() != h) { mLastScreenshotActivity = who; @@ -1623,6 +1627,12 @@ final class ActivityStack { } private void insertTaskAtTop(TaskRecord task) { + // If this is being moved to the top by another activity or being launched from the home + // activity, set mOnTopOfHome accordingly. + final boolean fromHome = mStackSupervisor.getLastStack().isHomeStack(); + if (!isHomeStack() && (fromHome || topTask() != task)) { + task.mOnTopOfHome = fromHome; + } mTaskHistory.remove(task); // Now put task at top. int stackNdx = mTaskHistory.size(); diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 2b69a4e16978..dc9036f16745 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -70,6 +70,7 @@ import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.os.TransferPipe; import com.android.server.am.ActivityManagerService.PendingActivityLaunch; @@ -203,6 +204,9 @@ public final class ActivityStackSupervisor { */ final PowerManager.WakeLock mGoingToSleep; + /** State of the stacks when user switched, indexed by userId. */ + SparseBooleanArray mUserHomeInFront = new SparseBooleanArray(2); + public ActivityStackSupervisor(ActivityManagerService service, Context context, Looper looper) { mService = service; @@ -288,22 +292,6 @@ public final class ActivityStackSupervisor { return mService.startHomeActivityLocked(mCurrentUser); } - final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r, - ActivityStack stack) { - if (stack == mHomeStack) { - return; - } - if ((sourceRecord == null && getLastStack() == mHomeStack) || - (sourceRecord != null && sourceRecord.isHomeActivity())) { - if (r == null) { - r = stack.topRunningActivityLocked(null); - } - if (r != null && !r.isHomeActivity() && r.isRootActivity()) { - r.task.mOnTopOfHome = true; - } - } - } - void setDismissKeyguard(boolean dismiss) { if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss); mDismissKeyguardOnNextActivity = dismiss; @@ -1479,7 +1467,6 @@ public final class ActivityStackSupervisor { // is the case, so this is it! And for paranoia, make // sure we have correctly resumed the top activity. if (doResume) { - setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); resumeTopActivitiesLocked(targetStack, null, options); } else { ActivityOptions.abort(options); @@ -1575,9 +1562,6 @@ public final class ActivityStackSupervisor { // don't use that intent!) And for paranoia, make // sure we have correctly resumed the top activity. if (doResume) { - // Reset flag so it gets correctly reevaluated. - intentActivity.task.mOnTopOfHome = false; - setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack); targetStack.resumeTopActivityLocked(null, options); } else { ActivityOptions.abort(options); @@ -1615,7 +1599,6 @@ public final class ActivityStackSupervisor { // resumed the top activity. topStack.mLastPausedActivity = null; if (doResume) { - setLaunchHomeTaskNextFlag(sourceRecord, null, topStack); resumeTopActivitiesLocked(); } ActivityOptions.abort(options); @@ -1694,7 +1677,6 @@ public final class ActivityStackSupervisor { // resumed the top activity. targetStack.mLastPausedActivity = null; if (doResume) { - setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); targetStack.resumeTopActivityLocked(null); } ActivityOptions.abort(options); @@ -1717,7 +1699,6 @@ public final class ActivityStackSupervisor { top.deliverNewIntentLocked(callingUid, r.intent); targetStack.mLastPausedActivity = null; if (doResume) { - setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); targetStack.resumeTopActivityLocked(null); } return ActivityManager.START_DELIVERED_TO_TOP; @@ -1751,7 +1732,6 @@ public final class ActivityStackSupervisor { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); } ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); - setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack); targetStack.mLastPausedActivity = null; targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); mService.setFocusedActivityLocked(r); @@ -1960,6 +1940,10 @@ public final class ActivityStackSupervisor { } } + void removeUserLocked(int userId) { + mUserHomeInFront.delete(userId); + } + /** * @return true if some activity was finished (or would have finished if doit were true). */ @@ -2278,17 +2262,17 @@ public final class ActivityStackSupervisor { } boolean switchUserLocked(int userId, UserStartedState uss) { + mUserHomeInFront.put(mCurrentUser, isFrontStack(mHomeStack)); + final boolean homeInFront = mUserHomeInFront.get(userId, true); mCurrentUser = userId; mStartingUsers.add(uss); - boolean haveActivities = false; for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - haveActivities |= mStacks.get(stackNdx).switchUserLocked(userId); + mStacks.get(stackNdx).switchUserLocked(userId); } - resumeTopActivitiesLocked(); - - return haveActivities; + moveHomeStack(homeInFront); + return homeInFront; } final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) { @@ -2381,6 +2365,7 @@ public final class ActivityStackSupervisor { pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState)); pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout); pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId); + pw.print(prefix); pw.println("mUserHomeInFront: " + mUserHomeInFront); } ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index 385253ef5bce..3d568ffb8e07 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -128,6 +128,16 @@ final class TaskRecord extends ThumbnailHolder { } } + void disposeThumbnail() { + super.disposeThumbnail(); + for (int i=mActivities.size()-1; i>=0; i--) { + ThumbnailHolder thumb = mActivities.get(i).thumbHolder; + if (thumb != this) { + thumb.disposeThumbnail(); + } + } + } + ActivityRecord getTopActivity() { for (int i = mActivities.size() - 1; i >= 0; --i) { final ActivityRecord r = mActivities.get(i); diff --git a/services/java/com/android/server/am/ThumbnailHolder.java b/services/java/com/android/server/am/ThumbnailHolder.java index 02f4fcbf1a7c..a6974f56356d 100644 --- a/services/java/com/android/server/am/ThumbnailHolder.java +++ b/services/java/com/android/server/am/ThumbnailHolder.java @@ -21,4 +21,9 @@ import android.graphics.Bitmap; public class ThumbnailHolder { Bitmap lastThumbnail; // Last thumbnail captured for this item. CharSequence lastDescription; // Last description captured for this item. + + void disposeThumbnail() { + lastThumbnail = null; + lastDescription = null; + } } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 1c54245e050a..e84f90ec4b5c 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -850,6 +850,19 @@ public class PackageManagerService extends IPackageManager.Stub { sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, res.pkg.applicationInfo.packageName, null, updateUsers); + + // treat asec-hosted packages like removable media on upgrade + if (isForwardLocked(res.pkg) || isExternal(res.pkg)) { + if (DEBUG_INSTALL) { + Slog.i(TAG, "upgrading pkg " + res.pkg + + " is ASEC-hosted -> AVAILABLE"); + } + int[] uidArray = new int[] { res.pkg.applicationInfo.uid }; + ArrayList<String> pkgList = new ArrayList<String>(1); + pkgList.add(res.pkg.applicationInfo.packageName); + sendResourcesChangedBroadcast(true, false, + pkgList,uidArray, null); + } } if (res.removedInfo.args != null) { // Remove the replaced package's older resources safely now @@ -4643,6 +4656,20 @@ public class PackageManagerService extends IPackageManager.Stub { // so that we do not end up in a confused state while the user is still using the older // version of the application while the new one gets installed. if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { + // If the package lives in an asec, tell everyone that the container is going + // away so they can clean up any references to its resources (which would prevent + // vold from being able to unmount the asec) + if (isForwardLocked(pkg) || isExternal(pkg)) { + if (DEBUG_INSTALL) { + Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE"); + } + final int[] uidArray = new int[] { pkg.applicationInfo.uid }; + final ArrayList<String> pkgList = new ArrayList<String>(1); + pkgList.add(pkg.applicationInfo.packageName); + sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null); + } + + // Post the request that it be killed now that the going-away broadcast is en route killApplication(pkg.applicationInfo.packageName, pkg.applicationInfo.uid, "update pkg"); } @@ -10745,8 +10772,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList, - int uidArr[], IIntentReceiver finishedReceiver) { + private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing, + ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) { int size = pkgList.size(); if (size > 0) { // Send broadcasts here @@ -10756,6 +10783,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (uidArr != null) { extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); } + if (replacing && !mediaStatus) { + extras.putBoolean(Intent.EXTRA_REPLACING, replacing); + } String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; sendPackageBroadcast(action, null, extras, null, finishedReceiver, null); @@ -10858,7 +10888,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Send a broadcast to let everyone know we are done processing if (pkgList.size() > 0) { - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null); } // Force gc to avoid any stale parser references that we might have. if (doGc) { @@ -10935,7 +10965,8 @@ public class PackageManagerService extends IPackageManager.Stub { // broadcast when packages get disabled, force a gc to clean things up. // and unload all the containers. if (pkgList.size() > 0) { - sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { + sendResourcesChangedBroadcast(false, false, pkgList, uidArr, + new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { @@ -11055,7 +11086,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (returnCode == PackageManager.MOVE_SUCCEEDED) { // Send resources unavailable broadcast - sendResourcesChangedBroadcast(false, pkgList, uidArr, null); + sendResourcesChangedBroadcast(false, true, pkgList, uidArr, null); // Update package code and resource paths synchronized (mInstallLock) { synchronized (mPackages) { @@ -11133,7 +11164,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } // Send resources available broadcast - sendResourcesChangedBroadcast(true, pkgList, uidArr, null); + sendResourcesChangedBroadcast(true, false, pkgList, uidArr, null); } } if (returnCode != PackageManager.MOVE_SUCCEEDED) { |