Use cached thumbnails in Recent tasks.

The thumbnail returned from ActivityManager.getTaskThumbnail() now
contains either a Bitmap or a ParcelFileDescriptor that points to
a file containing a compressed Bitmap. The Recent tasks list is
now responsible for all thumbnail Bitmap caching as the activity
manager keeps only the most recent 5. This also permits low memory
devices to have many more tasks in the Recent tasks list.

As part of this CL the concept of subtasks is removed eliminating
code supporting the TaskAccessInfo and IThumbnailRetriever classes.

Fixes bug 15828934.

Change-Id: I0fd0320a1a04e3c78d79357899b83a2fff97abf2
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 87140a3..6e458688 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -18,6 +18,7 @@
 
 import android.os.BatteryStats;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import com.android.internal.app.IUsageStats;
 import com.android.internal.app.ProcessStats;
 import com.android.internal.os.TransferPipe;
@@ -1018,28 +1019,6 @@
     }
 
     /**
-     * Remove some end of a task's activity stack that is not part of
-     * the main application.  The selected activities will be finished, so
-     * they are no longer part of the main task.
-     *
-     * @param taskId The identifier of the task.
-     * @param subTaskIndex The number of the sub-task; this corresponds
-     * to the index of the thumbnail returned by {@link #getTaskThumbnails(int)}.
-     * @return Returns true if the sub-task was found and was removed.
-     *
-     * @hide
-     */
-    public boolean removeSubTask(int taskId, int subTaskIndex)
-            throws SecurityException {
-        try {
-            return ActivityManagerNative.getDefault().removeSubTask(taskId, subTaskIndex);
-        } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return false;
-        }
-    }
-
-    /**
      * If set, the process of the root activity of the task will be killed
      * as part of removing the task.
      * @hide
@@ -1067,26 +1046,17 @@
     }
 
     /** @hide */
-    public static class TaskThumbnails implements Parcelable {
+    public static class TaskThumbnail implements Parcelable {
         public Bitmap mainThumbnail;
+        public ParcelFileDescriptor thumbnailFileDescriptor;
 
-        public int numSubThumbbails;
-
-        /** @hide */
-        public IThumbnailRetriever retriever;
-
-        public TaskThumbnails() {
-        }
-
-        public Bitmap getSubThumbnail(int index) {
-            try {
-                return retriever.getThumbnail(index);
-            } catch (RemoteException e) {
-                return null;
-            }
+        public TaskThumbnail() {
         }
 
         public int describeContents() {
+            if (thumbnailFileDescriptor != null) {
+                return thumbnailFileDescriptor.describeContents();
+            }
             return 0;
         }
 
@@ -1097,8 +1067,12 @@
             } else {
                 dest.writeInt(0);
             }
-            dest.writeInt(numSubThumbbails);
-            dest.writeStrongInterface(retriever);
+            if (thumbnailFileDescriptor != null) {
+                dest.writeInt(1);
+                thumbnailFileDescriptor.writeToParcel(dest, 0);
+            } else {
+                dest.writeInt(0);
+            }
         }
 
         public void readFromParcel(Parcel source) {
@@ -1107,38 +1081,31 @@
             } else {
                 mainThumbnail = null;
             }
-            numSubThumbbails = source.readInt();
-            retriever = IThumbnailRetriever.Stub.asInterface(source.readStrongBinder());
+            if (source.readInt() != 0) {
+                thumbnailFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(source);
+            } else {
+                thumbnailFileDescriptor = null;
+            }
         }
 
-        public static final Creator<TaskThumbnails> CREATOR = new Creator<TaskThumbnails>() {
-            public TaskThumbnails createFromParcel(Parcel source) {
-                return new TaskThumbnails(source);
+        public static final Creator<TaskThumbnail> CREATOR = new Creator<TaskThumbnail>() {
+            public TaskThumbnail createFromParcel(Parcel source) {
+                return new TaskThumbnail(source);
             }
-            public TaskThumbnails[] newArray(int size) {
-                return new TaskThumbnails[size];
+            public TaskThumbnail[] newArray(int size) {
+                return new TaskThumbnail[size];
             }
         };
 
-        private TaskThumbnails(Parcel source) {
+        private TaskThumbnail(Parcel source) {
             readFromParcel(source);
         }
     }
 
     /** @hide */
-    public TaskThumbnails getTaskThumbnails(int id) throws SecurityException {
+    public TaskThumbnail getTaskThumbnail(int id) throws SecurityException {
         try {
-            return ActivityManagerNative.getDefault().getTaskThumbnails(id);
-        } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
-        }
-    }
-
-    /** @hide */
-    public Bitmap getTaskTopThumbnail(int id) throws SecurityException {
-        try {
-            return ActivityManagerNative.getDefault().getTaskTopThumbnail(id);
+            return ActivityManagerNative.getDefault().getTaskThumbnail(id);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
             return null;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 572d389..9e10e3d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -548,28 +548,14 @@
             return true;
         }
 
-        case GET_TASK_THUMBNAILS_TRANSACTION: {
+        case GET_TASK_THUMBNAIL_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int id = data.readInt();
-            ActivityManager.TaskThumbnails bm = getTaskThumbnails(id);
+            ActivityManager.TaskThumbnail taskThumbnail = getTaskThumbnail(id);
             reply.writeNoException();
-            if (bm != null) {
+            if (taskThumbnail != null) {
                 reply.writeInt(1);
-                bm.writeToParcel(reply, 0);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case GET_TASK_TOP_THUMBNAIL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int id = data.readInt();
-            Bitmap bm = getTaskTopThumbnail(id);
-            reply.writeNoException();
-            if (bm != null) {
-                reply.writeInt(1);
-                bm.writeToParcel(reply, 0);
+                taskThumbnail.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
             } else {
                 reply.writeInt(0);
             }
@@ -1799,17 +1785,6 @@
             return true;
         }
 
-        case REMOVE_SUB_TASK_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            int subTaskIndex = data.readInt();
-            boolean result = removeSubTask(taskId, subTaskIndex);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
         case REMOVE_TASK_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -2773,35 +2748,20 @@
         reply.recycle();
         return list;
     }
-    public ActivityManager.TaskThumbnails getTaskThumbnails(int id) throws RemoteException {
+    public ActivityManager.TaskThumbnail getTaskThumbnail(int id) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(id);
-        mRemote.transact(GET_TASK_THUMBNAILS_TRANSACTION, data, reply, 0);
+        mRemote.transact(GET_TASK_THUMBNAIL_TRANSACTION, data, reply, 0);
         reply.readException();
-        ActivityManager.TaskThumbnails bm = null;
+        ActivityManager.TaskThumbnail taskThumbnail = null;
         if (reply.readInt() != 0) {
-            bm = ActivityManager.TaskThumbnails.CREATOR.createFromParcel(reply);
+            taskThumbnail = ActivityManager.TaskThumbnail.CREATOR.createFromParcel(reply);
         }
         data.recycle();
         reply.recycle();
-        return bm;
-    }
-    public Bitmap getTaskTopThumbnail(int id) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(id);
-        mRemote.transact(GET_TASK_TOP_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;
+        return taskThumbnail;
     }
     public List getServices(int maxNum, int flags) throws RemoteException {
         Parcel data = Parcel.obtain();
@@ -4516,20 +4476,6 @@
         return result;
     }
 
-    public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(subTaskIndex);
-        mRemote.transact(REMOVE_SUB_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
     public boolean removeTask(int taskId, int flags) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b630278..01977fe 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -116,8 +116,7 @@
     public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
             int flags, int userId) throws RemoteException;
-    public ActivityManager.TaskThumbnails getTaskThumbnails(int taskId) throws RemoteException;
-    public Bitmap getTaskTopThumbnail(int taskId) throws RemoteException;
+    public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException;
     public List<RunningServiceInfo> getServices(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
             throws RemoteException;
@@ -360,8 +359,6 @@
     public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
     public int[] getRunningUserIds() throws RemoteException;
 
-    public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
-
     public boolean removeTask(int taskId, int flags) throws RemoteException;
 
     public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
@@ -631,7 +628,7 @@
     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_THUMBNAILS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
+    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;
@@ -644,7 +641,7 @@
     int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
     int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
     int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
-    int GET_TASK_TOP_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
+    int ___AVAILABLE_2___ = IBinder.FIRST_CALL_TRANSACTION+94;
     int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
@@ -680,7 +677,7 @@
     int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127;
     int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128;
     int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129;
-    int REMOVE_SUB_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130;
+    int ___AVAILABLE_1___ = IBinder.FIRST_CALL_TRANSACTION+130;
     int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
     int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
     int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
diff --git a/core/java/android/app/IThumbnailRetriever.aidl b/core/java/android/app/IThumbnailRetriever.aidl
deleted file mode 100644
index 410cc20..0000000
--- a/core/java/android/app/IThumbnailRetriever.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2011, 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;
-
-import android.graphics.Bitmap;
-
-/**
- * System private API for retrieving thumbnails
- * {@hide}
- */
-interface IThumbnailRetriever {
-    Bitmap getThumbnail(int index);
-}