diff options
-rw-r--r-- | api/current.xml | 59 | ||||
-rw-r--r-- | core/java/android/app/ActivityManager.java | 43 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 29 | ||||
-rw-r--r-- | core/java/android/app/FragmentBreadCrumbs.java | 44 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 3 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 40 |
7 files changed, 185 insertions, 38 deletions
diff --git a/api/current.xml b/api/current.xml index 1ce49d4..2c72290 100644 --- a/api/current.xml +++ b/api/current.xml @@ -25064,6 +25064,17 @@ <parameter name="packageName" type="java.lang.String"> </parameter> </method> +<field name="MOVE_TASK_NO_USER_ACTION" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MOVE_TASK_WITH_HOME" type="int" transient="false" @@ -25495,6 +25506,16 @@ visibility="public" > </field> +<field name="persistentId" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <class name="ActivityManager.RunningAppProcessInfo" extends="java.lang.Object" @@ -30692,6 +30713,19 @@ <parameter name="visibleCrumbs" type="int"> </parameter> </method> +<method name="setOnBreadCrumbClickListener" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.app.FragmentBreadCrumbs.OnBreadCrumbClickListener"> +</parameter> +</method> <method name="setParentTitle" return="void" abstract="false" @@ -30725,6 +30759,29 @@ </parameter> </method> </class> +<interface name="FragmentBreadCrumbs.OnBreadCrumbClickListener" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="onBreadCrumbClick" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="backStack" type="android.app.FragmentManager.BackStackEntry"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +</interface> <class name="FragmentManager" extends="java.lang.Object" abstract="true" @@ -265799,7 +265856,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index d76b67d..a660076 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -112,6 +112,11 @@ public class ActivityManager { public int id; /** + * The true identifier of this task, valid even if it is not running. + */ + public int persistentId; + + /** * The original Intent used to launch the task. You can use this * Intent to re-launch the task (if it is no longer running) or bring * the current task to the front. @@ -127,14 +132,6 @@ public class ActivityManager { public ComponentName origActivity; /** - * Thumbnail representation of the task's last state. Must - * use {@link ActivityManager#TASKS_GET_THUMBNAILS} to have this set. - * @hide -- this is not scalable, need to have a separate API to get - * the bitmap. - */ - public Bitmap thumbnail; - - /** * Description of the task's last state. */ public CharSequence description; @@ -148,6 +145,7 @@ public class ActivityManager { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); + dest.writeInt(persistentId); if (baseIntent != null) { dest.writeInt(1); baseIntent.writeToParcel(dest, 0); @@ -155,29 +153,19 @@ public class ActivityManager { dest.writeInt(0); } ComponentName.writeToParcel(origActivity, dest); - if (thumbnail != null) { - dest.writeInt(1); - thumbnail.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } TextUtils.writeToParcel(description, dest, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } public void readFromParcel(Parcel source) { id = source.readInt(); + persistentId = source.readInt(); if (source.readInt() != 0) { baseIntent = Intent.CREATOR.createFromParcel(source); } else { baseIntent = null; } origActivity = ComponentName.readFromParcel(source); - if (source.readInt() != 0) { - thumbnail = Bitmap.CREATOR.createFromParcel(source); - } else { - thumbnail = null; - } description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); } @@ -401,6 +389,16 @@ public class ActivityManager { return getRunningTasks(maxNum, 0, null); } + /** @hide */ + public Bitmap getTaskThumbnail(int id) throws SecurityException { + try { + return ActivityManagerNative.getDefault().getTaskThumbnail(id); + } catch (RemoteException e) { + // System dead, we will be dead too soon! + return null; + } + } + /** * Flag for {@link #moveTaskToFront(int, int)}: also move the "home" * activity along with the task, so it is positioned immediately behind @@ -409,6 +407,13 @@ public class ActivityManager { public static final int MOVE_TASK_WITH_HOME = 0x00000001; /** + * Flag for {@link #moveTaskToFront(int, int)}: don't count this as a + * user-instigated action, so the current activity will not receive a + * hint that the user is leaving. + */ + public static final int MOVE_TASK_NO_USER_ACTION = 0x00000002; + + /** * Ask that the task associated with a given task ID be moved to the * front of the stack, so it is now visible to the user. Requires that * the caller hold permission {@link android.Manifest.permission#REORDER_TASKS} diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index c095c06..d3d3792 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -442,6 +442,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case GET_TASK_THUMBNAIL_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int id = data.readInt(); + Bitmap bm = getTaskThumbnail(id); + reply.writeNoException(); + if (bm != null) { + reply.writeInt(1); + bm.writeToParcel(reply, 0); + } else { + reply.writeInt(0); + } + return true; + } + case GET_SERVICES_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int maxNum = data.readInt(); @@ -1816,6 +1830,21 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); return list; } + public Bitmap getTaskThumbnail(int id) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(id); + mRemote.transact(GET_TASK_THUMBNAIL_TRANSACTION, data, reply, 0); + reply.readException(); + Bitmap bm = null; + if (reply.readInt() != 0) { + bm = Bitmap.CREATOR.createFromParcel(reply); + } + data.recycle(); + reply.recycle(); + return bm; + } public List getServices(int maxNum, int flags) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java index 3f045ac..df64035 100644 --- a/core/java/android/app/FragmentBreadCrumbs.java +++ b/core/java/android/app/FragmentBreadCrumbs.java @@ -50,6 +50,26 @@ public class FragmentBreadCrumbs extends ViewGroup /** Listener to inform when a parent entry is clicked */ private OnClickListener mParentClickListener; + private OnBreadCrumbClickListener mOnBreadCrumbClickListener; + + /** + * Interface to intercept clicks on the bread crumbs. + */ + public interface OnBreadCrumbClickListener { + /** + * Called when a bread crumb is clicked. + * + * @param backStack The BackStackEntry whose bread crumb was clicked. + * May be null, if this bread crumb is for the root of the back stack. + * @param flags Additional information about the entry. Currently + * always 0. + * + * @return Return true to consume this click. Return to false to allow + * the default action (popping back stack to this entry) to occur. + */ + public boolean onBreadCrumbClick(BackStackEntry backStack, int flags); + } + public FragmentBreadCrumbs(Context context) { this(context, null); } @@ -107,6 +127,16 @@ public class FragmentBreadCrumbs extends ViewGroup updateCrumbs(); } + /** + * Sets a listener for clicks on the bread crumbs. This will be called before + * the default click action is performed. + * + * @param listener The new listener to set. Replaces any existing listener. + */ + public void setOnBreadCrumbClickListener(OnBreadCrumbClickListener listener) { + mOnBreadCrumbClickListener = listener; + } + private BackStackRecord createBackStackEntry(CharSequence title, CharSequence shortTitle) { if (title == null) return null; @@ -266,8 +296,18 @@ public class FragmentBreadCrumbs extends ViewGroup mParentClickListener.onClick(v); } } else { - mActivity.getFragmentManager().popBackStack(bse.getId(), - bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0); + if (mOnBreadCrumbClickListener != null) { + if (mOnBreadCrumbClickListener.onBreadCrumbClick( + bse == mTopEntry ? null : bse, 0)) { + return; + } + } + if (bse == mTopEntry) { + // Pop everything off the back stack. + mActivity.getFragmentManager().popBackStack(); + } else { + mActivity.getFragmentManager().popBackStack(bse.getId(), 0); + } } } } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 5d4380b..f42e8fb 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -133,6 +133,7 @@ public interface IActivityManager extends IInterface { IThumbnailReceiver receiver) throws RemoteException; public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags) throws RemoteException; + public Bitmap getTaskThumbnail(int taskId) throws RemoteException; public List getServices(int maxNum, int flags) throws RemoteException; public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() throws RemoteException; @@ -514,7 +515,7 @@ public interface IActivityManager extends IInterface { int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78; int KILL_PIDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79; int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80; - + int GET_TASK_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81; int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82; int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83; int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java index 86c3e75..e0d558f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java @@ -374,8 +374,9 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O if (title != null && title.length() > 0 && icon != null) { if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title); ActivityDescription item = new ActivityDescription( - recentInfo.thumbnail, icon, title, - recentInfo.description, intent, id, index, info.packageName); + am.getTaskThumbnail(recentInfo.persistentId), + icon, title, recentInfo.description, intent, id, + index, info.packageName); activityDescriptions.add(item); ++index; } else { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 9e3b9c6..f3ccd38 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4969,11 +4969,6 @@ public final class ActivityManagerService extends ActivityManagerNative enforceCallingPermission(android.Manifest.permission.GET_TASKS, "getRecentTasks()"); - final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0 - && checkCallingPermission( - android.Manifest.permission.READ_FRAME_BUFFER) - == PackageManager.PERMISSION_GRANTED; - IPackageManager pm = AppGlobals.getPackageManager(); ActivityRecord resumed = mMainStack.mResumedActivity; @@ -4991,17 +4986,10 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo(); rti.id = tr.numActivities > 0 ? tr.taskId : -1; + rti.persistentId = tr.taskId; rti.baseIntent = new Intent( tr.intent != null ? tr.intent : tr.affinityIntent); rti.origActivity = tr.origActivity; - - if (canReadFb) { - if (resumed != null && resumed.task == tr) { - rti.thumbnail = resumed.stack.screenshotActivities(resumed); - } else { - rti.thumbnail = tr.lastThumbnail; - } - } rti.description = tr.lastDescription; if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) { @@ -5030,6 +5018,26 @@ public final class ActivityManagerService extends ActivityManagerNative } } + public Bitmap getTaskThumbnail(int id) { + synchronized (this) { + enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, + "getTaskThumbnail()"); + ActivityRecord resumed = mMainStack.mResumedActivity; + final int N = mRecentTasks.size(); + for (int i=0; i<N; i++) { + TaskRecord tr = mRecentTasks.get(i); + if (tr.taskId == id) { + if (resumed != null && resumed.task == tr) { + return resumed.stack.screenshotActivities(resumed); + } else { + return tr.lastThumbnail; + } + } + } + } + return null; + } + private final int findAffinityTaskTopLocked(int startIndex, String affinity) { int j; TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task; @@ -5085,6 +5093,9 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<N; i++) { TaskRecord tr = mRecentTasks.get(i); if (tr.taskId == task) { + if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) { + mMainStack.mUserLeaving = true; + } if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just move the home task to the top first. @@ -5097,6 +5108,9 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i); if (hr.task.taskId == task) { + if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) { + mMainStack.mUserLeaving = true; + } if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just move the home task to the top first. |