summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--CleanSpec.mk1
-rw-r--r--core/java/android/app/ActivityManager.java85
-rw-r--r--core/java/android/app/ActivityManagerNative.java72
-rw-r--r--core/java/android/app/IActivityManager.java11
-rw-r--r--core/java/android/app/IThumbnailRetriever.aidl25
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Utilities.java22
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java47
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java54
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java11
-rw-r--r--services/core/java/com/android/server/am/TaskAccessInfo.java34
-rw-r--r--services/core/java/com/android/server/am/TaskPersister.java100
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java224
-rw-r--r--services/core/java/com/android/server/am/ThumbnailHolder.java29
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java18
18 files changed, 245 insertions, 508 deletions
diff --git a/Android.mk b/Android.mk
index a6271d2..5ffafc0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -80,7 +80,6 @@ LOCAL_SRC_FILES += \
core/java/android/app/job/IJobCallback.aidl \
core/java/android/app/job/IJobScheduler.aidl \
core/java/android/app/job/IJobService.aidl \
- core/java/android/app/IThumbnailRetriever.aidl \
core/java/android/app/ITransientNotification.aidl \
core/java/android/app/IUiAutomationConnection.aidl \
core/java/android/app/IUiModeManager.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 73f370d..909fdb6 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -205,6 +205,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/androi
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 87140a3..6e45868 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -18,6 +18,7 @@ package android.app;
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 @@ public class ActivityManager {
}
/**
- * 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 @@ public class ActivityManager {
}
/** @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 @@ public class ActivityManager {
} 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 @@ public class ActivityManager {
} 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 {
- 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 {
+ public TaskThumbnail getTaskThumbnail(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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
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 @@ class ActivityManagerProxy implements IActivityManager
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 @@ class ActivityManagerProxy implements IActivityManager
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 interface IActivityManager extends IInterface {
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 interface IActivityManager extends IInterface {
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 @@ 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_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 @@ public interface IActivityManager extends IInterface {
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 @@ public interface IActivityManager extends IInterface {
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);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index aa4e69a..1b215c9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -40,6 +40,7 @@ import android.view.MotionEvent;
import android.view.View;
import com.android.systemui.R;
+import com.android.systemui.recents.Utilities;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
@@ -199,7 +200,7 @@ public class RecentTasksLoader implements View.OnTouchListener {
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
final PackageManager pm = mContext.getPackageManager();
- Bitmap thumbnail = am.getTaskTopThumbnail(td.persistentTaskId);
+ final Bitmap thumbnail = Utilities.getThumbnail(am, td.persistentTaskId);
Drawable icon = getFullResIcon(td.resolveInfo, pm);
if (td.userId != UserHandle.myUserId()) {
// Need to badge the icon
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index f7f86c4..3765d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -208,7 +208,7 @@ public class SystemServicesProxy {
return thumbnail;
}
- Bitmap thumbnail = mAm.getTaskTopThumbnail(taskId);
+ Bitmap thumbnail = Utilities.getThumbnail(mAm, taskId);
if (thumbnail != null) {
// We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
// left pixel, then assume the whole thumbnail is transparent. Generally, proper
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 6d6376f..6a7cfcc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -16,10 +16,15 @@
package com.android.systemui.recents;
+import android.app.ActivityManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.ParcelFileDescriptor;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -90,4 +95,21 @@ public class Utilities {
throws IllegalAccessException, InvocationTargetException {
sPropertyMethod.invoke(null, property, value);
}
+
+ /** Retrieves a task thumbnail from the activity manager */
+ public static Bitmap getThumbnail(ActivityManager activityManager, int taskId) {
+ ActivityManager.TaskThumbnail taskThumbnail = activityManager.getTaskThumbnail(taskId);
+ Bitmap thumbnail = taskThumbnail.mainThumbnail;
+ final ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor;
+ if (thumbnail == null && descriptor != null) {
+ thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());
+ }
+ if (descriptor != null) {
+ try {
+ descriptor.close();
+ } catch (IOException e) {
+ }
+ }
+ return thumbnail;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 45367a8..56be936 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -270,7 +270,10 @@ public final class ActivityManagerService extends ActivityManagerNative
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 = ActivityManager.isLowRamDeviceStatic() ? 10 : 200;
+ static final int MAX_RECENT_TASKS = ActivityManager.isLowRamDeviceStatic() ? 100 : 200;
+
+ // Maximum number recent bitmaps to keep in memory.
+ static final int MAX_RECENT_BITMAPS = 5;
// Amount of time after a call to stopAppSwitches() during which we will
// prevent further untrusted switches from happening.
@@ -3601,6 +3604,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (task.userId != tr.userId) {
continue;
}
+ if (i > MAX_RECENT_BITMAPS) {
+ tr.freeLastThumbnail();
+ }
final Intent trIntent = tr.intent;
if ((task.affinity == null || !task.affinity.equals(tr.affinity)) &&
(intent == null || !intent.filterEquals(trIntent))) {
@@ -7348,26 +7354,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
+ public ActivityManager.TaskThumbnail getTaskThumbnail(int id) {
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
- "getTaskThumbnails()");
+ "getTaskThumbnail()");
TaskRecord tr = recentTaskForIdLocked(id);
if (tr != null) {
- return tr.getTaskThumbnailsLocked();
- }
- }
- return null;
- }
-
- @Override
- public Bitmap getTaskTopThumbnail(int id) {
- synchronized (this) {
- enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
- "getTaskTopThumbnail()");
- TaskRecord tr = recentTaskForIdLocked(id);
- if (tr != null) {
- return tr.getTaskTopThumbnailLocked();
+ return tr.getTaskThumbnailLocked();
}
}
return null;
@@ -7384,24 +7377,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- @Override
- public boolean removeSubTask(int taskId, int subTaskIndex) {
- synchronized (this) {
- enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
- "removeSubTask()");
- long ident = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = recentTaskForIdLocked(taskId);
- if (tr != null) {
- return tr.removeTaskActivitiesLocked(subTaskIndex, true) != null;
- }
- return false;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
private void killUnneededProcessLocked(ProcessRecord pr, String reason) {
if (!pr.killedByAm) {
Slog.i(TAG, "Killing " + pr.toShortString() + " (adj " + pr.setAdj + "): " + reason);
@@ -7473,7 +7448,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private boolean removeTaskByIdLocked(int taskId, int flags) {
TaskRecord tr = recentTaskForIdLocked(taskId);
if (tr != null) {
- tr.removeTaskActivitiesLocked(-1, false);
+ tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, flags);
if (tr.isPersistable) {
notifyTaskPersisterLocked(tr, true);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 287ad00..fd2a0b1 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.os.PersistableBundle;
import android.os.Trace;
@@ -113,7 +114,6 @@ final class ActivityRecord {
int realTheme; // actual theme resource we will use, never 0.
int windowFlags; // custom window flags for preview window.
TaskRecord task; // the task this is in.
- ThumbnailHolder thumbHolder; // where our thumbnails should go.
long createTime = System.currentTimeMillis();
long displayStartTime; // when we started launching this activity
long fullyDrawnStartTime; // when we started launching this activity
@@ -262,13 +262,6 @@ final class ActivityRecord {
pw.print(" forceNewConfig="); pw.println(forceNewConfig);
pw.print(prefix); pw.print("mActivityType=");
pw.println(activityTypeToString(mActivityType));
- pw.print(prefix); pw.print("thumbHolder: ");
- pw.print(Integer.toHexString(System.identityHashCode(thumbHolder)));
- if (thumbHolder != null) {
- pw.print(" bm="); pw.print(thumbHolder.lastThumbnail);
- pw.print(" desc="); pw.print(thumbHolder.lastDescription);
- }
- pw.println();
if (displayStartTime != 0 || startTime != 0) {
pw.print(prefix); pw.print("displayStartTime=");
if (displayStartTime == 0) pw.print("0");
@@ -497,7 +490,7 @@ final class ActivityRecord {
}
}
- void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
+ void setTask(TaskRecord newTask, boolean isRoot) {
if (task != null && task.removeActivity(this)) {
if (task != newTask) {
task.stack.removeTask(task);
@@ -506,18 +499,7 @@ final class ActivityRecord {
(newTask == null ? null : newTask.stack));
}
}
- if (newThumbHolder == null) {
- newThumbHolder = newTask;
- }
task = newTask;
- if (!isRoot && (intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
- // This is the start of a new sub-task.
- if (thumbHolder == null) {
- thumbHolder = new ThumbnailHolder();
- }
- } else {
- thumbHolder = newThumbHolder;
- }
}
boolean changeWindowTranslucency(boolean toOpaque) {
@@ -764,18 +746,15 @@ final class ActivityRecord {
}
void updateThumbnail(Bitmap newThumbnail, CharSequence description) {
- if (thumbHolder != null) {
- if (newThumbnail != null) {
- if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
- "Setting thumbnail of " + this + " holder " + thumbHolder
- + " to " + newThumbnail);
- thumbHolder.lastThumbnail = newThumbnail;
- if (isPersistable()) {
- mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
- }
+ if (newThumbnail != null) {
+ if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
+ "Setting thumbnail of " + this + " to " + newThumbnail);
+ task.setLastThumbnail(newThumbnail);
+ if (isPersistable()) {
+ mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
}
- thumbHolder.lastDescription = description;
}
+ task.lastDescription = description;
}
void startLaunchTickingLocked() {
@@ -1051,6 +1030,11 @@ final class ActivityRecord {
return null;
}
+ private static String createImageFilename(ActivityRecord r) {
+ return String.valueOf(r.task.taskId) + ACTIVITY_ICON_SUFFIX + r.createTime +
+ TaskPersister.IMAGE_EXTENSION;
+ }
+
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
out.attribute(null, ATTR_ID, String.valueOf(createTime));
out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
@@ -1064,8 +1048,7 @@ final class ActivityRecord {
out.attribute(null, ATTR_USERID, String.valueOf(userId));
if (taskDescription != null) {
- TaskPersister.saveTaskDescription(taskDescription, String.valueOf(task.taskId) +
- ACTIVITY_ICON_SUFFIX + createTime, out);
+ task.saveTaskDescription(taskDescription, createImageFilename(this), out);
}
out.startTag(null, TAG_INTENT);
@@ -1109,9 +1092,9 @@ final class ActivityRecord {
componentSpecified = Boolean.valueOf(attrValue);
} else if (ATTR_USERID.equals(attrName)) {
userId = Integer.valueOf(attrValue);
- } else if (TaskPersister.readTaskDescriptionAttribute(taskDescription, attrName,
+ } else if (TaskRecord.readTaskDescriptionAttribute(taskDescription, attrName,
attrValue)) {
- // Completed in TaskPersister.readTaskDescriptionAttribute()
+ // Completed in TaskRecord.readTaskDescriptionAttribute()
} else {
Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
}
@@ -1157,8 +1140,7 @@ final class ActivityRecord {
r.persistentState = persistentState;
if (createTime >= 0) {
- taskDescription.setIcon(TaskPersister.restoreImage(String.valueOf(taskId) +
- ACTIVITY_ICON_SUFFIX + createTime));
+ taskDescription.setIcon(TaskPersister.restoreImage(createImageFilename(r)));
}
r.taskDescription = taskDescription;
r.createTime = createTime;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1ecb43c..f2922c3 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2063,7 +2063,6 @@ final class ActivityStack {
// bottom of the activity stack. This also keeps it
// correctly ordered with any activities we previously
// moved.
- final ThumbnailHolder newThumbHolder;
final TaskRecord targetTask;
final ActivityRecord bottom =
!mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
@@ -2074,20 +2073,16 @@ final class ActivityStack {
// same task affinity as the one we are moving,
// then merge it into the same task.
targetTask = bottom.task;
- newThumbHolder = bottom.thumbHolder == null ? targetTask : bottom.thumbHolder;
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+ " out to bottom task " + bottom.task);
} else {
targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
null, null, null, false);
- newThumbHolder = targetTask;
targetTask.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+ " out to new task " + target.task);
}
- target.thumbHolder = newThumbHolder;
-
final int targetTaskId = targetTask.taskId;
mWindowManager.setAppGroupId(target.appToken, targetTaskId);
@@ -2099,7 +2094,6 @@ final class ActivityStack {
continue;
}
- ThumbnailHolder curThumbHolder = p.thumbHolder;
canMoveOptions = false;
if (noOptions && topOptions == null) {
topOptions = p.takeOptionsLocked();
@@ -2112,7 +2106,7 @@ final class ActivityStack {
+ " Callers=" + Debug.getCallers(4));
if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
+ " out to target's task " + target.task);
- p.setTask(targetTask, curThumbHolder, false);
+ p.setTask(targetTask, false);
targetTask.addActivityAtBottom(p);
mWindowManager.setAppGroupId(p.appToken, targetTaskId);
@@ -2243,7 +2237,7 @@ final class ActivityStack {
+ start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
for (int srcPos = start; srcPos >= i; --srcPos) {
final ActivityRecord p = activities.get(srcPos);
- p.setTask(task, null, false);
+ p.setTask(task, false);
task.addActivityAtIndex(taskInsertionPoint, p);
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
@@ -3626,8 +3620,8 @@ final class ActivityStack {
ci.topActivity = top.intent.getComponent();
ci.lastActiveTime = task.lastActiveTime;
- if (top.thumbHolder != null) {
- ci.description = top.thumbHolder.lastDescription;
+ if (top.task != null) {
+ ci.description = top.task.lastDescription;
}
ci.numActivities = numActivities;
ci.numRunning = numRunning;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e7f5720..dbd3638 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1894,11 +1894,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
- voiceSession, voiceInteractor, true), null, true);
+ voiceSession, voiceInteractor, true), true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
r.task);
} else {
- r.setTask(reuseTask, reuseTask, true);
+ r.setTask(reuseTask, true);
}
if (!movedHome) {
if ((launchFlags &
@@ -1959,7 +1959,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
- r.setTask(sourceTask, sourceRecord.thumbHolder, false);
+ r.setTask(sourceTask, false);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in existing task " + r.task + " from source " + sourceRecord);
@@ -1970,9 +1970,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
targetStack = adjustStackFocus(r, newTask);
targetStack.moveToFront();
ActivityRecord prev = targetStack.topActivity();
- r.setTask(prev != null ? prev.task
- : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true),
- null, true);
+ r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
+ r.info, intent, null, null, true), true);
mWindowManager.moveTaskToTop(r.task.taskId);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new guessed " + r.task);
diff --git a/services/core/java/com/android/server/am/TaskAccessInfo.java b/services/core/java/com/android/server/am/TaskAccessInfo.java
deleted file mode 100644
index 50aeec1..0000000
--- a/services/core/java/com/android/server/am/TaskAccessInfo.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 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 com.android.server.am;
-
-import java.util.ArrayList;
-
-import android.app.ActivityManager.TaskThumbnails;
-
-final class TaskAccessInfo extends TaskThumbnails {
- final static class SubTask {
- ThumbnailHolder holder;
- ActivityRecord activity;
- int index;
- }
-
- public ActivityRecord root;
- public int rootIndex;
-
- public ArrayList<SubTask> subtasks;
-}
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index eee7e9e..1982d7e 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -40,6 +40,7 @@ import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.LinkedList;
public class TaskPersister {
static final String TAG = "TaskPersister";
@@ -53,15 +54,12 @@ public class TaskPersister {
private static final String TASKS_DIRNAME = "recent_tasks";
private static final String TASK_EXTENSION = ".xml";
private static final String IMAGES_DIRNAME = "recent_images";
- private static final String IMAGE_EXTENSION = ".png";
+ static final String IMAGE_EXTENSION = ".png";
private static final String TAG_TASK = "task";
- private static final String ATTR_TASKDESCRIPTIONLABEL = "task_description_label";
- private static final String ATTR_TASKDESCRIPTIONCOLOR = "task_description_color";
-
- private static File sImagesDir;
- private static File sTasksDir;
+ static File sImagesDir;
+ static File sTasksDir;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
@@ -132,49 +130,8 @@ public class TaskPersister {
return stringWriter;
}
- static void saveImage(Bitmap image, String filename) throws IOException {
- if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename);
- FileOutputStream imageFile = null;
- try {
- imageFile = new FileOutputStream(new File(sImagesDir, filename + IMAGE_EXTENSION));
- image.compress(Bitmap.CompressFormat.PNG, 100, imageFile);
- } catch (Exception e) {
- Slog.e(TAG, "saveImage: unable to save " + filename, e);
- } finally {
- if (imageFile != null) {
- imageFile.close();
- }
- }
- }
-
- static void saveTaskDescription(ActivityManager.TaskDescription taskDescription,
- String iconFilename, XmlSerializer out) throws IOException {
- if (taskDescription != null) {
- final String label = taskDescription.getLabel();
- if (label != null) {
- out.attribute(null, ATTR_TASKDESCRIPTIONLABEL, label);
- }
- final int colorPrimary = taskDescription.getPrimaryColor();
- if (colorPrimary != 0) {
- out.attribute(null, ATTR_TASKDESCRIPTIONCOLOR, Integer.toHexString(colorPrimary));
- }
- final Bitmap icon = taskDescription.getIcon();
- if (icon != null) {
- saveImage(icon, iconFilename);
- }
- }
- }
-
- static boolean readTaskDescriptionAttribute(ActivityManager.TaskDescription taskDescription,
- String attrName, String attrValue) {
- if (ATTR_TASKDESCRIPTIONLABEL.equals(attrName)) {
- taskDescription.setLabel(attrValue);
- return true;
- } else if (ATTR_TASKDESCRIPTIONCOLOR.equals(attrName)) {
- taskDescription.setPrimaryColor((int) Long.parseLong(attrValue, 16));
- return true;
- }
- return false;
+ void saveImage(Bitmap image, String filename) {
+ mLazyTaskWriterThread.saveImage(image, filename);
}
private String fileToString(File file) {
@@ -314,16 +271,33 @@ public class TaskPersister {
static Bitmap restoreImage(String filename) {
if (DEBUG) Slog.d(TAG, "restoreImage: restoring " + filename);
- return BitmapFactory.decodeFile(sImagesDir + File.separator + filename + IMAGE_EXTENSION);
+ return BitmapFactory.decodeFile(sImagesDir + File.separator + filename);
}
private class LazyTaskWriterThread extends Thread {
boolean mSlow = true;
+ LinkedList<BitmapQueueEntry> mSaveImagesQueue = new LinkedList<BitmapQueueEntry>();
LazyTaskWriterThread(String name) {
super(name);
}
+ class BitmapQueueEntry {
+ final Bitmap mImage;
+ final String mFilename;
+ BitmapQueueEntry(Bitmap image, String filename) {
+ mImage = image;
+ mFilename = filename;
+ }
+ }
+
+ void saveImage(Bitmap image, String filename) {
+ synchronized (mSaveImagesQueue) {
+ mSaveImagesQueue.add(new BitmapQueueEntry(image, filename));
+ }
+ TaskPersister.this.notify(null, false);
+ }
+
@Override
public void run() {
ArraySet<Integer> persistentTaskIds = new ArraySet<Integer>();
@@ -344,6 +318,32 @@ public class TaskPersister {
}
}
+ // Write out one bitmap that needs saving each time through.
+ BitmapQueueEntry entry;
+ synchronized (mSaveImagesQueue) {
+ entry = mSaveImagesQueue.poll();
+ // Are there any more after this one?
+ mRecentsChanged |= !mSaveImagesQueue.isEmpty();
+ }
+ if (entry != null) {
+ final String filename = entry.mFilename;
+ if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename);
+ FileOutputStream imageFile = null;
+ try {
+ imageFile = new FileOutputStream(new File(sImagesDir, filename));
+ entry.mImage.compress(Bitmap.CompressFormat.PNG, 100, imageFile);
+ } catch (Exception e) {
+ Slog.e(TAG, "saveImage: unable to save " + filename, e);
+ } finally {
+ if (imageFile != null) {
+ try {
+ imageFile.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
StringWriter stringWriter = null;
TaskRecord task = null;
synchronized(mService) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3ef9494..d221f96 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -24,12 +24,13 @@ import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.TaskThumbnail;
import android.app.ActivityOptions;
-import android.app.IThumbnailRetriever;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
+import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.Slog;
@@ -39,12 +40,12 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-final class TaskRecord extends ThumbnailHolder {
- private static final String TAG_TASK = "task";
+final class TaskRecord {
private static final String ATTR_TASKID = "task_id";
private static final String TAG_INTENT = "intent";
private static final String TAG_AFFINITYINTENT = "affinity_intent";
@@ -60,6 +61,8 @@ final class TaskRecord extends ThumbnailHolder {
private static final String ATTR_LASTDESCRIPTION = "last_description";
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
+ private static final String ATTR_TASKDESCRIPTIONLABEL = "task_description_label";
+ private static final String ATTR_TASKDESCRIPTIONCOLOR = "task_description_color";
private static final String LAST_ACTIVITY_ICON_SUFFIX = "_last_activity_icon_";
private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
@@ -72,7 +75,6 @@ final class TaskRecord extends ThumbnailHolder {
Intent affinityIntent; // Intent of affinity-moved activity that started this task.
ComponentName origActivity; // The non-alias activity component of the intent.
ComponentName realActivity; // The actual activity component that started the task.
- int numActivities; // Current number of activities in this task.
long lastActiveTime; // Last time this task was active, including sleep.
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
@@ -123,11 +125,18 @@ final class TaskRecord extends ThumbnailHolder {
// do not want to delete the stack when the task goes empty.
boolean mReuseTask = false;
+ private Bitmap mLastThumbnail; // Last thumbnail captured for this item.
+ private final File mLastThumbnailFile; // File containing last thubmnail.
+ private final String mFilename;
+ CharSequence lastDescription; // Last description captured for this item.
+
final ActivityManagerService mService;
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
mService = service;
+ mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION;
+ mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename);
taskId = _taskId;
voiceSession = _voiceSession;
voiceInteractor = _voiceInteractor;
@@ -142,6 +151,8 @@ final class TaskRecord extends ThumbnailHolder {
long lastTimeMoved, boolean neverRelinquishIdentity,
ActivityManager.TaskDescription _lastTaskDescription) {
mService = service;
+ mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION;
+ mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename);
taskId = _taskId;
intent = _intent;
affinityIntent = _affinityIntent;
@@ -240,16 +251,38 @@ final class TaskRecord extends ThumbnailHolder {
return mTaskToReturnTo;
}
- void disposeThumbnail() {
- super.disposeThumbnail();
- for (int i=mActivities.size()-1; i>=0; i--) {
- ThumbnailHolder thumb = mActivities.get(i).thumbHolder;
- if (thumb != this) {
- thumb.disposeThumbnail();
+ void setLastThumbnail(Bitmap thumbnail) {
+ mLastThumbnail = thumbnail;
+ if (thumbnail == null) {
+ if (mLastThumbnailFile != null) {
+ mLastThumbnailFile.delete();
+ }
+ } else {
+ mService.mTaskPersister.saveImage(thumbnail, mFilename);
+ }
+ }
+
+ void getLastThumbnail(TaskThumbnail thumbs) {
+ thumbs.mainThumbnail = mLastThumbnail;
+ thumbs.thumbnailFileDescriptor = null;
+ if (mLastThumbnailFile.exists()) {
+ try {
+ thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (IOException e) {
}
}
}
+ void freeLastThumbnail() {
+ mLastThumbnail = null;
+ }
+
+ void disposeThumbnail() {
+ mLastThumbnail = null;
+ lastDescription = null;
+ }
+
/** Returns the intent for the root activity for this task */
Intent getBaseIntent() {
return intent != null ? intent : affinityIntent;
@@ -470,63 +503,22 @@ final class TaskRecord extends ThumbnailHolder {
return null;
}
- public ActivityManager.TaskThumbnails getTaskThumbnailsLocked() {
- TaskAccessInfo info = getTaskAccessInfoLocked();
- final ActivityRecord resumedActivity = stack.mResumedActivity;
- if (resumedActivity != null && resumedActivity.thumbHolder == this) {
- info.mainThumbnail = stack.screenshotActivities(resumedActivity);
- }
- if (info.mainThumbnail == null) {
- info.mainThumbnail = lastThumbnail;
- }
- return info;
- }
-
- public Bitmap getTaskTopThumbnailLocked() {
+ public TaskThumbnail getTaskThumbnailLocked() {
if (stack != null) {
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity != null && resumedActivity.task == this) {
- // This task is the current resumed task, we just need to take
- // a screenshot of it and return that.
- return stack.screenshotActivities(resumedActivity);
+ final Bitmap thumbnail = stack.screenshotActivities(resumedActivity);
+ setLastThumbnail(thumbnail);
}
}
- // Return the information about the task, to figure out the top
- // thumbnail to return.
- TaskAccessInfo info = getTaskAccessInfoLocked();
- if (info.numSubThumbbails <= 0) {
- return info.mainThumbnail != null ? info.mainThumbnail : lastThumbnail;
- }
- return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
+ final TaskThumbnail taskThumbnail = new TaskThumbnail();
+ getLastThumbnail(taskThumbnail);
+ return taskThumbnail;
}
- public ActivityRecord removeTaskActivitiesLocked(int subTaskIndex,
- boolean taskRequired) {
- TaskAccessInfo info = getTaskAccessInfoLocked();
- if (info.root == null) {
- if (taskRequired) {
- Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
- }
- return null;
- }
-
- if (subTaskIndex < 0) {
- // Just remove the entire task.
- performClearTaskAtIndexLocked(info.rootIndex);
- return info.root;
- }
-
- if (subTaskIndex >= info.subtasks.size()) {
- if (taskRequired) {
- Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
- }
- return null;
- }
-
- // Remove all of this task's activities starting at the sub task.
- TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
- performClearTaskAtIndexLocked(subtask.index);
- return subtask.activity;
+ public void removeTaskActivitiesLocked() {
+ // Just remove the entire task.
+ performClearTaskAtIndexLocked(0);
}
boolean isHomeTask() {
@@ -541,68 +533,6 @@ final class TaskRecord extends ThumbnailHolder {
return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
}
- public TaskAccessInfo getTaskAccessInfoLocked() {
- final TaskAccessInfo thumbs = new TaskAccessInfo();
- // How many different sub-thumbnails?
- final int NA = mActivities.size();
- int j = 0;
- ThumbnailHolder holder = null;
- while (j < NA) {
- ActivityRecord ar = mActivities.get(j);
- if (!ar.finishing) {
- thumbs.root = ar;
- thumbs.rootIndex = j;
- holder = ar.thumbHolder;
- if (holder != null) {
- thumbs.mainThumbnail = holder.lastThumbnail;
- }
- j++;
- break;
- }
- j++;
- }
-
- if (j >= NA) {
- return thumbs;
- }
-
- ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
- thumbs.subtasks = subtasks;
- while (j < NA) {
- ActivityRecord ar = mActivities.get(j);
- j++;
- if (ar.finishing) {
- continue;
- }
- if (ar.thumbHolder != holder && holder != null) {
- thumbs.numSubThumbbails++;
- holder = ar.thumbHolder;
- TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
- sub.holder = holder;
- sub.activity = ar;
- sub.index = j-1;
- subtasks.add(sub);
- }
- }
- if (thumbs.numSubThumbbails > 0) {
- thumbs.retriever = new IThumbnailRetriever.Stub() {
- @Override
- public Bitmap getThumbnail(int index) {
- if (index < 0 || index >= thumbs.subtasks.size()) {
- return null;
- }
- TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
- ActivityRecord resumedActivity = stack.mResumedActivity;
- if (resumedActivity != null && resumedActivity.thumbHolder == sub.holder) {
- return stack.screenshotActivities(resumedActivity);
- }
- return sub.holder.lastThumbnail;
- }
- };
- }
- return thumbs;
- }
-
/**
* Find the activity in the history stack within the given task. Returns
* the index within the history at which it's found, or < 0 if not found.
@@ -691,6 +621,36 @@ final class TaskRecord extends ThumbnailHolder {
setIntent(r.intent, r.info);
}
+ void saveTaskDescription(ActivityManager.TaskDescription taskDescription,
+ String iconFilename, XmlSerializer out) throws IOException {
+ if (taskDescription != null) {
+ final String label = taskDescription.getLabel();
+ if (label != null) {
+ out.attribute(null, ATTR_TASKDESCRIPTIONLABEL, label);
+ }
+ final int colorPrimary = taskDescription.getPrimaryColor();
+ if (colorPrimary != 0) {
+ out.attribute(null, ATTR_TASKDESCRIPTIONCOLOR, Integer.toHexString(colorPrimary));
+ }
+ final Bitmap icon = taskDescription.getIcon();
+ if (icon != null) {
+ mService.mTaskPersister.saveImage(icon, iconFilename);
+ }
+ }
+ }
+
+ static boolean readTaskDescriptionAttribute(ActivityManager.TaskDescription taskDescription,
+ String attrName, String attrValue) {
+ if (ATTR_TASKDESCRIPTIONLABEL.equals(attrName)) {
+ taskDescription.setLabel(attrValue);
+ } else if (ATTR_TASKDESCRIPTIONCOLOR.equals(attrName)) {
+ taskDescription.setPrimaryColor((int) Long.parseLong(attrValue, 16));
+ } else {
+ return false;
+ }
+ return true;
+ }
+
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
Slog.i(TAG, "Saving task=" + this);
@@ -716,7 +676,7 @@ final class TaskRecord extends ThumbnailHolder {
}
if (lastTaskDescription != null) {
- TaskPersister.saveTaskDescription(lastTaskDescription, String.valueOf(taskId) +
+ saveTaskDescription(lastTaskDescription, String.valueOf(taskId) +
LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime, out);
}
@@ -744,11 +704,6 @@ final class TaskRecord extends ThumbnailHolder {
r.saveToXml(out);
out.endTag(null, TAG_ACTIVITY);
}
-
- final Bitmap thumbnail = getTaskTopThumbnailLocked();
- if (thumbnail != null) {
- TaskPersister.saveImage(thumbnail, String.valueOf(taskId) + TASK_THUMBNAIL_SUFFIX);
- }
}
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -800,8 +755,7 @@ final class TaskRecord extends ThumbnailHolder {
lastTimeOnTop = Long.valueOf(attrValue);
} else if (ATTR_NEVERRELINQUISH.equals(attrName)) {
neverRelinquishIdentity = Boolean.valueOf(attrValue);
- } else if (TaskPersister.readTaskDescriptionAttribute(taskDescription, attrName,
- attrValue)) {
+ } else if (readTaskDescriptionAttribute(taskDescription, attrName, attrValue)) {
// Completed in TaskPersister.readTaskDescriptionAttribute()
} else {
Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
@@ -836,7 +790,7 @@ final class TaskRecord extends ThumbnailHolder {
if (lastActiveTime >= 0) {
taskDescription.setIcon(TaskPersister.restoreImage(String.valueOf(taskId) +
- LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime));
+ LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime + TaskPersister.IMAGE_EXTENSION));
}
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
@@ -845,12 +799,9 @@ final class TaskRecord extends ThumbnailHolder {
lastTimeOnTop, neverRelinquishIdentity, taskDescription);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- r.thumbHolder = r.task = task;
+ activities.get(activityNdx).task = task;
}
- task.lastThumbnail = TaskPersister.restoreImage(taskId + TASK_THUMBNAIL_SUFFIX);
-
Slog.i(TAG, "Restored task=" + task);
return task;
}
@@ -898,7 +849,8 @@ final class TaskRecord extends ThumbnailHolder {
if (!askedCompatMode) {
pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
}
- pw.print(prefix); pw.print("lastThumbnail="); pw.print(lastThumbnail);
+ pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail);
+ pw.print(" lastThumbnailFile="); pw.print(mLastThumbnailFile);
pw.print(" lastDescription="); pw.println(lastDescription);
pw.print(prefix); pw.print("hasBeenVisible="); pw.print(hasBeenVisible);
pw.print(" lastActiveTime="); pw.print(lastActiveTime);
diff --git a/services/core/java/com/android/server/am/ThumbnailHolder.java b/services/core/java/com/android/server/am/ThumbnailHolder.java
deleted file mode 100644
index a6974f5..0000000
--- a/services/core/java/com/android/server/am/ThumbnailHolder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 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 com.android.server.am;
-
-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/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index d7a6c1d..0e063d6 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -72,7 +72,7 @@ public class ActivityTestMain extends Activity {
private void addThumbnail(LinearLayout container, Bitmap bm,
final ActivityManager.RecentTaskInfo task,
- final ActivityManager.TaskThumbnails thumbs, final int subIndex) {
+ final ActivityManager.TaskThumbnail thumbs) {
ImageView iv = new ImageView(this);
if (bm != null) {
iv.setImageBitmap(bm);
@@ -86,9 +86,6 @@ public class ActivityTestMain extends Activity {
@Override
public void onClick(View v) {
if (task.id >= 0 && thumbs != null) {
- if (subIndex < (thumbs.numSubThumbbails-1)) {
- mAm.removeSubTask(task.id, subIndex+1);
- }
mAm.moveTaskToFront(task.id, ActivityManager.MOVE_TASK_WITH_HOME);
} else {
try {
@@ -104,11 +101,7 @@ public class ActivityTestMain extends Activity {
@Override
public boolean onLongClick(View v) {
if (task.id >= 0 && thumbs != null) {
- if (subIndex < 0) {
- mAm.removeTask(task.id, ActivityManager.REMOVE_TASK_KILL_PROCESS);
- } else {
- mAm.removeSubTask(task.id, subIndex);
- }
+ mAm.removeTask(task.id, ActivityManager.REMOVE_TASK_KILL_PROCESS);
buildUi();
return true;
}
@@ -333,7 +326,7 @@ public class ActivityTestMain extends Activity {
if (recents != null) {
for (int i=0; i<recents.size(); i++) {
ActivityManager.RecentTaskInfo r = recents.get(i);
- ActivityManager.TaskThumbnails tt = mAm.getTaskThumbnails(r.persistentId);
+ ActivityManager.TaskThumbnail tt = mAm.getTaskThumbnail(r.persistentId);
TextView tv = new TextView(this);
tv.setText(r.baseIntent.getComponent().flattenToShortString());
top.addView(tv, new LinearLayout.LayoutParams(
@@ -341,10 +334,7 @@ public class ActivityTestMain extends Activity {
LinearLayout.LayoutParams.WRAP_CONTENT));
LinearLayout item = new LinearLayout(this);
item.setOrientation(LinearLayout.HORIZONTAL);
- addThumbnail(item, tt != null ? tt.mainThumbnail : null, r, tt, -1);
- for (int j=0; j<tt.numSubThumbbails; j++) {
- addThumbnail(item, tt.getSubThumbnail(j), r, tt, j);
- }
+ addThumbnail(item, tt != null ? tt.mainThumbnail : null, r, tt);
top.addView(item, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));