diff options
15 files changed, 191 insertions, 64 deletions
@@ -69,6 +69,7 @@ LOCAL_SRC_FILES += \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IAlarmManager.aidl \ core/java/android/app/IAppTask.aidl \ + core/java/android/app/ITaskStackListener.aidl \ core/java/android/app/IBackupAgent.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 6ec48e5..06a26ec 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -774,6 +774,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case REGISTER_TASK_STACK_LISTENER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + registerTaskStackListener(ITaskStackListener.Stub.asInterface(token)); + reply.writeNoException(); + return true; + } + case GET_TASK_FOR_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -3266,6 +3274,18 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } + @Override + public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(listener.asBinder()); + mRemote.transact(REGISTER_TASK_STACK_LISTENER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 5362303..1ccbd27 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -139,6 +139,7 @@ public interface IActivityManager extends IInterface { public StackInfo getStackInfo(int stackId) throws RemoteException; public boolean isInHomeStack(int taskId) throws RemoteException; public void setFocusedStack(int stackId) throws RemoteException; + public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException; public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException; public ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable) throws RemoteException; @@ -788,4 +789,5 @@ public interface IActivityManager extends IInterface { int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239; int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240; int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241; + int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242; } diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl new file mode 100644 index 0000000..4b0935c --- /dev/null +++ b/core/java/android/app/ITaskStackListener.aidl @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2014, 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 android.app; + +/** @hide */ +oneway interface ITaskStackListener { + void onTaskStackChanged(); +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 29f291d..4f0700e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -19,6 +19,7 @@ package com.android.systemui.recents; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.ITaskStackListener; import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; @@ -56,6 +57,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; + /** A proxy implementation for the recents component */ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener { @@ -79,6 +81,28 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta final static String sRecentsPackage = "com.android.systemui"; final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity"; + /** + * An implementation of ITaskStackListener, that allows us to listen for changes to the system + * task stacks and update recents accordingly. + */ + class TaskStackListenerImpl extends ITaskStackListener.Stub { + @Override + public void onTaskStackChanged() { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { + // Load the next task only if we aren't svelte + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); + loader.preloadTasks(plan, true /* isTopTaskHome */); + RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); + launchOpts.numVisibleTasks = 1; + launchOpts.numVisibleTaskThumbnails = 1; + launchOpts.onlyLoadForCache = true; + loader.loadTasks(mContext, plan, launchOpts); + } + } + } + static RecentsComponent.Callbacks sRecentsComponentCallbacks; static RecentsTaskLoadPlan sInstanceLoadPlan; @@ -86,6 +110,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta LayoutInflater mInflater; SystemServicesProxy mSystemServicesProxy; Handler mHandler; + TaskStackListenerImpl mTaskStackListener; boolean mBootCompleted; boolean mStartAnimationTriggered; boolean mCanReuseTaskStackViews = true; @@ -116,6 +141,10 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mSystemServicesProxy = new SystemServicesProxy(context); mHandler = new Handler(); mTaskStackBounds = new Rect(); + + // Register the task stack listener + mTaskStackListener = new TaskStackListenerImpl(); + mSystemServicesProxy.registerTaskStackListener(mTaskStackListener); } public void onStart() { diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 6dc2edb..a37bc54 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -167,10 +167,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView if (action.equals(Intent.ACTION_SCREEN_OFF)) { // When the screen turns off, dismiss Recents to Home dismissRecentsToHome(false); - // Preload the metadata for all tasks in the background - RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); - RecentsTaskLoadPlan plan = loader.createLoadPlan(context); - loader.preloadTasks(plan, true /* isTopTaskHome */); } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) { // When the search activity changes, update the Search widget refreshSearchWidget(); @@ -437,22 +433,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView onEnterAnimationTriggered(); } - // Start listening for widget package changes if there is one bound, post it since we don't - // want it stalling the startup - if (mConfig.searchBarAppWidgetId >= 0) { - final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> callback = - new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(this); - mRecentsView.post(new Runnable() { - @Override - public void run() { - RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = callback.get(); - if (cb != null) { - mAppWidgetHost.startListening(cb); - } - } - }); - } - mStatusBar = ((SystemUIApplication) getApplication()) .getComponent(PhoneStatusBar.class); } @@ -539,15 +519,29 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView unregisterReceiver(mSystemBroadcastReceiver); // Stop listening for widget package changes if there was one bound - if (mAppWidgetHost.isListening()) { - mAppWidgetHost.stopListening(); - } + mAppWidgetHost.stopListening(); } public void onEnterAnimationTriggered() { // Try and start the enter animation (or restart it on configuration changed) ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null); - mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t)); + ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t); + mRecentsView.startEnterRecentsAnimation(ctx); + if (mConfig.searchBarAppWidgetId >= 0) { + final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> cbRef = + new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>( + RecentsActivity.this); + ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() { + @Override + public void run() { + // Start listening for widget package changes if there is one bound + RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = cbRef.get(); + if (cb != null) { + mAppWidgetHost.startListening(cb); + } + } + }); + } // Animate the SystemUI scrim views mScrimViews.startEnterRecentsAnimation(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java index a63e167..5bae37a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java @@ -43,23 +43,23 @@ public class RecentsAppWidgetHost extends AppWidgetHost { public void startListening(RecentsAppWidgetHostCallbacks cb) { mCb = cb; - mIsListening = true; - super.startListening(); + if (!mIsListening) { + mIsListening = true; + super.startListening(); + } } @Override public void stopListening() { - super.stopListening(); + if (mIsListening) { + super.stopListening(); + } // Ensure that we release any references to the callbacks mCb = null; mContext = null; mIsListening = false; } - public boolean isListening() { - return mIsListening; - } - @Override protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) { if (mCb == null) return; diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 9a4bd08..3fbd5a6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -21,6 +21,7 @@ import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.AppGlobals; import android.app.IActivityManager; +import android.app.ITaskStackListener; import android.app.SearchManager; import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetManager; @@ -536,4 +537,15 @@ public class SystemServicesProxy { e.printStackTrace(); } } + + /** Registers a task stack listener with the system. */ + public void registerTaskStackListener(ITaskStackListener listener) { + if (mIam == null) return; + + try { + mIam.registerTaskStackListener(listener); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 46a5d8d..746a7df 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -204,6 +204,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV /** Requests all task stacks to start their enter-recents animation */ public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) { + // We have to increment/decrement the post animation trigger in case there are no children + // to ensure that it runs + ctx.postAnimationTrigger.increment(); + int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); @@ -212,6 +216,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV stackView.startEnterRecentsAnimation(ctx); } } + ctx.postAnimationTrigger.decrement(); } /** Requests all task stacks to start their exit-recents animation */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java index 4586f12..e1d80fd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java @@ -27,7 +27,7 @@ public class ViewAnimation { public static class TaskViewEnterContext { // A trigger to run some logic when all the animations complete. This works around the fact // that it is difficult to coordinate ViewPropertyAnimators - ReferenceCountedTrigger postAnimationTrigger; + public ReferenceCountedTrigger postAnimationTrigger; // An update listener to notify as the enter animation progresses (used for the home transition) ValueAnimator.AnimatorUpdateListener updateListener; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 7e17043..6823119 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -37,6 +37,7 @@ import android.app.ApplicationThreadNative; import android.app.IActivityContainer; import android.app.IActivityContainerCallback; import android.app.IAppTask; +import android.app.ITaskStackListener; import android.app.ProfilerInfo; import android.app.admin.DevicePolicyManager; import android.app.usage.UsageEvents; @@ -292,7 +293,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); // Maximum number recent bitmaps to keep in memory. - static final int MAX_RECENT_BITMAPS = 5; + static final int MAX_RECENT_BITMAPS = 3; // Amount of time after a call to stopAppSwitches() during which we will // prevent further untrusted switches from happening. @@ -370,6 +371,9 @@ public final class ActivityManagerService extends ActivityManagerNative static final int LAST_PREBOOT_DELIVERED_FILE_VERSION = 10000; + // Delay in notifying task stack change listeners (in millis) + static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 1000; + /** All system services */ SystemServiceManager mSystemServiceManager; @@ -378,6 +382,10 @@ public final class ActivityManagerService extends ActivityManagerNative /** Run all ActivityStacks through this */ ActivityStackSupervisor mStackSupervisor; + /** Task stack change listeners. */ + private RemoteCallbackList<ITaskStackListener> mTaskStackListeners = + new RemoteCallbackList<ITaskStackListener>(); + public IntentFirewall mIntentFirewall; // Whether we should show our dialogs (ANR, crash, etc) or just perform their @@ -1219,6 +1227,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int START_USER_SWITCH_MSG = 46; static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47; static final int DISMISS_DIALOG_MSG = 48; + static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 49; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1738,6 +1747,22 @@ public final class ActivityManagerService extends ActivityManagerNative d.dismiss(); break; } + case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: { + synchronized (ActivityManagerService.this) { + int i = mTaskStackListeners.beginBroadcast(); + while (i > 0) { + i--; + try { + // Make a one-way callback to the listener + mTaskStackListeners.getBroadcastItem(i).onTaskStackChanged(); + } catch (RemoteException e){ + // Handled by the RemoteCallbackList + } + } + mTaskStackListeners.finishBroadcast(); + } + break; + } } } }; @@ -2332,6 +2357,16 @@ public final class ActivityManagerService extends ActivityManagerNative } } + /** Sets the task stack listener that gets callbacks when a task stack changes. */ + @Override + public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException { + synchronized (ActivityManagerService.this) { + if (listener != null) { + mTaskStackListeners.register(listener); + } + } + } + @Override public void notifyActivityDrawn(IBinder token) { if (DEBUG_VISBILITY) Slog.d(TAG, "notifyActivityDrawn: token=" + token); @@ -3643,12 +3678,12 @@ public final class ActivityManagerService extends ActivityManagerNative if(DEBUG_TASKS) Slog.i(TAG, "remove RecentTask " + tr + " when finishing user" + userId); mRecentTasks.remove(i); - tr.removedFromRecents(mTaskPersister); + tr.removedFromRecents(); } } // Remove tasks from persistent storage. - mTaskPersister.wakeup(null, true); + notifyTaskPersisterLocked(null, true); } // Sort by taskId @@ -3660,7 +3695,7 @@ public final class ActivityManagerService extends ActivityManagerNative }; // Extract the affiliates of the chain containing mRecentTasks[start]. - private int processNextAffiliateChain(int start) { + private int processNextAffiliateChainLocked(int start) { final TaskRecord startTask = mRecentTasks.get(start); final int affiliateId = startTask.mAffiliatedTaskId; @@ -3695,7 +3730,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (first.mNextAffiliate != null) { Slog.w(TAG, "Link error 1 first.next=" + first.mNextAffiliate); first.setNextAffiliate(null); - mTaskPersister.wakeup(first, false); + notifyTaskPersisterLocked(first, false); } // Everything in the middle is doubly linked from next to prev. final int tmpSize = mTmpRecents.size(); @@ -3706,13 +3741,13 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, "Link error 2 next=" + next + " prev=" + next.mPrevAffiliate + " setting prev=" + prev); next.setPrevAffiliate(prev); - mTaskPersister.wakeup(next, false); + notifyTaskPersisterLocked(next, false); } if (prev.mNextAffiliate != next) { Slog.w(TAG, "Link error 3 prev=" + prev + " next=" + prev.mNextAffiliate + " setting next=" + next); prev.setNextAffiliate(next); - mTaskPersister.wakeup(prev, false); + notifyTaskPersisterLocked(prev, false); } prev.inRecents = true; } @@ -3721,7 +3756,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (last.mPrevAffiliate != null) { Slog.w(TAG, "Link error 4 last.prev=" + last.mPrevAffiliate); last.setPrevAffiliate(null); - mTaskPersister.wakeup(last, false); + notifyTaskPersisterLocked(last, false); } // Insert the group back into mRecentTasks at start. @@ -3762,7 +3797,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (task.autoRemoveRecents && task.getTopActivity() == null) { // This situation is broken, and we should just get rid of it now. mRecentTasks.remove(i); - task.removedFromRecents(mTaskPersister); + task.removedFromRecents(); i--; N--; Slog.w(TAG, "Removing auto-remove without activity: " + task); @@ -3807,7 +3842,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app == dummyApp || (app.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { // Doesn't exist any more! Good-bye. mRecentTasks.remove(i); - task.removedFromRecents(mTaskPersister); + task.removedFromRecents(); i--; N--; Slog.w(TAG, "Removing no longer valid recent: " + task); @@ -3843,7 +3878,7 @@ public final class ActivityManagerService extends ActivityManagerNative } // Verify the affiliate chain for each task. - for (int i = 0; i < N; i = processNextAffiliateChain(i)) { + for (int i = 0; i < N; i = processNextAffiliateChainLocked(i)) { } mTmpRecents.clear(); @@ -4009,12 +4044,12 @@ public final class ActivityManagerService extends ActivityManagerNative } if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: trimming tasks for " + task); - trimRecentsForTask(task, true); + trimRecentsForTaskLocked(task, true); N = mRecentTasks.size(); while (N >= ActivityManager.getMaxRecentTasksStatic()) { final TaskRecord tr = mRecentTasks.remove(N - 1); - tr.removedFromRecents(mTaskPersister); + tr.removedFromRecents(); N--; } task.inRecents = true; @@ -4079,7 +4114,7 @@ public final class ActivityManagerService extends ActivityManagerNative * If needed, remove oldest existing entries in recents that are for the same kind * of task as the given one. */ - int trimRecentsForTask(TaskRecord task, boolean doTrim) { + int trimRecentsForTaskLocked(TaskRecord task, boolean doTrim) { int N = mRecentTasks.size(); final Intent intent = task.intent; final boolean document = intent != null && intent.isDocument(); @@ -4126,7 +4161,7 @@ public final class ActivityManagerService extends ActivityManagerNative tr.disposeThumbnail(); mRecentTasks.remove(i); if (task != tr) { - tr.removedFromRecents(mTaskPersister); + tr.removedFromRecents(); } i--; N--; @@ -7989,10 +8024,6 @@ public final class ActivityManagerService extends ActivityManagerNative return list; } - TaskRecord getMostRecentTask() { - return mRecentTasks.get(0); - } - /** * Creates a new RecentTaskInfo from a TaskRecord. */ @@ -8221,7 +8252,7 @@ public final class ActivityManagerService extends ActivityManagerNative TaskRecord task = new TaskRecord(this, mStackSupervisor.getNextTaskId(), ainfo, intent, description); - int trimIdx = trimRecentsForTask(task, false); + int trimIdx = trimRecentsForTaskLocked(task, false); if (trimIdx >= 0) { // If this would have caused a trim, then we'll abort because that // means it would be added at the end of the list but then just removed. @@ -8231,7 +8262,7 @@ public final class ActivityManagerService extends ActivityManagerNative final int N = mRecentTasks.size(); if (N >= (ActivityManager.getMaxRecentTasksStatic()-1)) { final TaskRecord tr = mRecentTasks.remove(N - 1); - tr.removedFromRecents(mTaskPersister); + tr.removedFromRecents(); } task.inRecents = true; @@ -8291,7 +8322,7 @@ public final class ActivityManagerService extends ActivityManagerNative private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) { mRecentTasks.remove(tr); - tr.removedFromRecents(mTaskPersister); + tr.removedFromRecents(); ComponentName component = tr.getBaseIntent().getComponent(); if (component == null) { Slog.w(TAG, "No component for base intent of task: " + tr); @@ -9979,6 +10010,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } + /** Pokes the task persister. */ void notifyTaskPersisterLocked(TaskRecord task, boolean flush) { if (task != null && task.stack != null && task.stack.isHomeStack()) { // Never persist the home stack. @@ -9987,6 +10019,13 @@ public final class ActivityManagerService extends ActivityManagerNative mTaskPersister.wakeup(task, flush); } + /** Notifies all listeners when the task stack has changed. */ + void notifyTaskStackChangedLocked() { + mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG); + Message nmsg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG); + mHandler.sendMessageDelayed(nmsg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY); + } + @Override public boolean shutdown(int timeout) { if (checkCallingPermission(android.Manifest.permission.SHUTDOWN) @@ -10010,12 +10049,12 @@ public final class ActivityManagerService extends ActivityManagerNative mBatteryStatsService.shutdown(); synchronized (this) { mProcessStats.shutdownLocked(); + notifyTaskPersisterLocked(null, true); } - notifyTaskPersisterLocked(null, true); return timedout; } - + public final void activitySlept(IBinder token) { if (localLOGV) Slog.v(TAG, "Activity slept: token=" + token); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index c12cadb..e37d5f3 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -69,7 +69,7 @@ import java.util.Objects; final class ActivityRecord { static final String TAG = ActivityManagerService.TAG; static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE; - final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recent"; + final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents"; private static final String TAG_ACTIVITY = "activity"; private static final String ATTR_ID = "id"; @@ -792,7 +792,7 @@ final class ActivityRecord { } } - void updateThumbnail(Bitmap newThumbnail, CharSequence description) { + void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) { if (newThumbnail != null) { if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG, "Setting thumbnail of " + this + " to " + newThumbnail); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index ea694ad..ad86aea 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -65,7 +65,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; @@ -838,7 +837,7 @@ final class ActivityStack { clearLaunchTime(prev); final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) { - prev.updateThumbnail(screenshotActivities(prev), null); + prev.updateThumbnailLocked(screenshotActivities(prev), null); } stopFullyDrawnTraceIfNeeded(); @@ -950,7 +949,7 @@ final class ActivityStack { r.icicle = icicle; r.haveState = true; r.launchCount = 0; - r.updateThumbnail(null, description); + r.updateThumbnailLocked(null, description); } if (!r.stopped) { if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)"); @@ -1060,6 +1059,9 @@ final class ActivityStack { } prev.cpuTimeAtResume = 0; // reset it } + + // Notfiy when the task stack has changed + mService.notifyTaskStackChangedLocked(); } /** @@ -4105,7 +4107,7 @@ final class ActivityStack { // Task creator asked to remove this when done, or this task was a voice // interaction, so it should not remain on the recent tasks list. mService.mRecentTasks.remove(task); - task.removedFromRecents(mService.mTaskPersister); + task.removedFromRecents(); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 38809cb..d9396d8 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2871,6 +2871,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final TaskRecord task = r.task; task.setLastThumbnail(task.stack.screenshotActivities(r)); mService.addRecentTaskLocked(task); + mService.notifyTaskStackChangedLocked(); mWindowManager.setAppVisibility(r.appToken, false); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index ee93233..d726685 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -383,12 +383,12 @@ final class TaskRecord { setNextAffiliate(null); } - void removedFromRecents(TaskPersister persister) { + void removedFromRecents() { disposeThumbnail(); closeRecentsChain(); if (inRecents) { inRecents = false; - persister.wakeup(this, false); + mService.notifyTaskPersisterLocked(this, false); } } |