am a2968ad5: Merge "Revert "Backup/restore recents task list"" into mnc-dev

* commit 'a2968ad51e36190ad8042ec330237905bc7fe5c1':
  Revert "Backup/restore recents task list"
This commit is contained in:
Stefan Kuhne
2015-05-18 23:31:37 +00:00
committed by Android Git Automerger
8 changed files with 53 additions and 833 deletions

View File

@@ -2466,13 +2466,6 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
case SYSTEM_BACKUP_RESTORED: {
data.enforceInterface(IActivityManager.descriptor);
systemBackupRestored();
reply.writeNoException();
return true;
}
case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final int uid = data.readInt();
@@ -5758,17 +5751,6 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
public void systemBackupRestored() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
mRemote.transact(SYSTEM_BACKUP_RESTORED, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
@Override
public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException {
Parcel data = Parcel.obtain();

View File

@@ -488,7 +488,6 @@ public interface IActivityManager extends IInterface {
public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
public void systemBackupRestored() throws RemoteException;
public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
@@ -825,7 +824,6 @@ public interface IActivityManager extends IInterface {
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;
int SYSTEM_BACKUP_RESTORED = IBinder.FIRST_CALL_TRANSACTION+243;
// Start of M transactions
int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;

View File

@@ -1,130 +0,0 @@
/*
* 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.backup;
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
import java.io.File;
/**
* Helper for saving/restoring 'recent tasks' infrastructure.
* @hide
*/
public class RecentsBackupHelper implements BackupHelper {
private static final String TAG = "RecentsBackup";
private static final boolean DEBUG = false;
// This must match TaskPersister.TASKS_DIRNAME, but that class is not accessible from here
private static final String RECENTS_TASK_DIR = "recent_tasks";
// Must match TaskPersister.IMAGES_DIRNAME, as above
private static final String RECENTS_IMAGE_DIR = "recent_images";
// At restore time, tasks/thumbnails are placed in these directories alongside
// the "live" recents dirs named above.
private static final String RECENTS_TASK_RESTORE_DIR = "restored_" + RECENTS_TASK_DIR;
private static final String RECENTS_IMAGE_RESTORE_DIR = "restored_" + RECENTS_IMAGE_DIR;
// Prefixes for tagging the two kinds of recents backup records that we might generate
private static final String RECENTS_TASK_KEY = "task:";
private static final String RECENTS_IMAGE_KEY = "image:";
FileBackupHelperBase mTaskFileHelper;
final File mSystemDir;
final File mTasksDir;
final File mRestoredTasksDir;
final File mRestoredImagesDir;
final String[] mRecentFiles;
final String[] mRecentKeys;
/**
* @param context The agent context in which this helper instance will run
*/
public RecentsBackupHelper(Context context) {
mTaskFileHelper = new FileBackupHelperBase(context);
mSystemDir = new File(Environment.getDataDirectory(), "system");
mTasksDir = new File(mSystemDir, RECENTS_TASK_DIR);
mRestoredTasksDir = new File(mSystemDir, RECENTS_TASK_RESTORE_DIR);
mRestoredImagesDir = new File(mSystemDir, RECENTS_IMAGE_RESTORE_DIR);
// Currently we back up only the recent-task descriptions, not the thumbnails
File[] recentFiles = mTasksDir.listFiles();
if (recentFiles != null) {
// We explicitly proceed even if this is a zero-size array
final int N = recentFiles.length;
mRecentKeys = new String[N];
mRecentFiles = new String[N];
if (DEBUG) {
Slog.i(TAG, "Identifying recents for backup: " + N);
}
for (int i = 0; i < N; i++) {
mRecentKeys[i] = new String(RECENTS_TASK_KEY + recentFiles[i].getName());
mRecentFiles[i] = recentFiles[i].getAbsolutePath();
if (DEBUG) {
Slog.i(TAG, " " + mRecentKeys[i]);
}
}
} else {
mRecentFiles = mRecentKeys = new String[0];
}
}
/**
* Task-file key: RECENTS_TASK_KEY + leaf filename
* Thumbnail-file key: RECENTS_IMAGE_KEY + leaf filename
*/
@Override
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
FileBackupHelperBase.performBackup_checked(oldState, data, newState,
mRecentFiles, mRecentKeys);
}
@Override
public void restoreEntity(BackupDataInputStream data) {
final String key = data.getKey();
File output = null;
if (key.startsWith(RECENTS_TASK_KEY)) {
String name = key.substring(RECENTS_TASK_KEY.length());
output = new File(mRestoredTasksDir, name);
mRestoredTasksDir.mkdirs();
} else if (key.startsWith(RECENTS_IMAGE_KEY)) {
String name = key.substring(RECENTS_IMAGE_KEY.length());
output = new File(mRestoredImagesDir, name);
mRestoredImagesDir.mkdirs();
}
if (output != null) {
if (DEBUG) {
Slog.i(TAG, "Restoring key='"
+ key + "' to " + output.getAbsolutePath());
}
mTaskFileHelper.writeFile(output, data);
}
}
@Override
public void writeNewStateDescription(ParcelFileDescriptor newState) {
mTaskFileHelper.writeNewStateDescription(newState);
}
}

View File

@@ -16,14 +16,12 @@
package com.android.server.backup;
import android.app.ActivityManagerNative;
import android.app.IWallpaperManager;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.app.backup.RecentsBackupHelper;
import android.app.backup.WallpaperBackupHelper;
import android.content.Context;
import android.os.Environment;
@@ -45,7 +43,6 @@ public class SystemBackupAgent extends BackupAgentHelper {
// Names of the helper tags within the dataset. Changing one of these names will
// break the ability to restore from datasets that predate the change.
private static final String WALLPAPER_HELPER = "wallpaper";
private static final String RECENTS_HELPER = "recents";
private static final String SYNC_SETTINGS_HELPER = "account_sync_settings";
private static final String PREFERRED_HELPER = "preferred_activities";
private static final String NOTIFICATION_HELPER = "notifications";
@@ -92,7 +89,6 @@ public class SystemBackupAgent extends BackupAgentHelper {
}
}
addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, files, keys));
addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -127,7 +123,6 @@ public class SystemBackupAgent extends BackupAgentHelper {
addHelper("system_files", new WallpaperBackupHelper(this,
new String[] { WALLPAPER_IMAGE },
new String[] { WALLPAPER_IMAGE_KEY} ));
addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -200,13 +195,4 @@ public class SystemBackupAgent extends BackupAgentHelper {
}
}
}
@Override
public void onRestoreFinished() {
try {
ActivityManagerNative.getDefault().systemBackupRestored();
} catch (RemoteException e) {
// Not possible since this code is running in the system process.
}
}
}

View File

@@ -6164,17 +6164,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
@Override
public void systemBackupRestored() {
synchronized (this) {
if (mSystemReady) {
mTaskPersister.restoreTasksFromOtherDeviceLocked();
} else {
Slog.w(TAG, "System backup restored before system is ready");
}
}
}
final void ensureBootCompleted() {
boolean booting;
boolean enableScreen;
@@ -11327,7 +11316,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mRecentTasks.clear();
mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
mTaskPersister.restoreTasksFromOtherDeviceLocked();
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
mTaskPersister.startPersisting();
@@ -16191,18 +16179,12 @@ public final class ActivityManagerService extends ActivityManagerNative
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
if (userId == UserHandle.USER_OWNER) {
mTaskPersister.removeFromPackageCache(ssp);
}
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
cleanupDisabledPackageComponentsLocked(ssp, userId,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
if (userId == UserHandle.USER_OWNER) {
mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
}
}
}
break;
@@ -16217,8 +16199,8 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
if (userId == UserHandle.USER_OWNER) {
mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
if (replacing) {
removeTasksByRemovedPackageComponentsLocked(ssp, userId);
}
try {
ApplicationInfo ai = AppGlobals.getPackageManager().

View File

@@ -17,8 +17,6 @@
package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import android.app.ActivityManager.TaskDescription;
@@ -85,7 +83,7 @@ final class ActivityRecord {
private static final String ATTR_USERID = "user_id";
private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
private static final String ATTR_RESOLVEDTYPE = "resolved_type";
private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
@@ -94,7 +92,7 @@ final class ActivityRecord {
final IApplicationToken.Stub appToken; // window manager token
final ActivityInfo info; // all about me
final ApplicationInfo appInfo; // information about activity's app
int launchedFromUid; // always the uid who started the activity.
final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
final int userId; // Which user is this running for?
final Intent intent; // the original intent that generated us
@@ -1178,8 +1176,8 @@ final class ActivityRecord {
}
}
static ActivityRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
throws IOException, XmlPullParserException {
static ActivityRecord restoreFromXml(XmlPullParser in,
ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
Intent intent = null;
PersistableBundle persistentState = null;
int launchedFromUid = 0;
@@ -1194,7 +1192,7 @@ final class ActivityRecord {
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
final String attrValue = in.getAttributeValue(attrNdx);
if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
if (ATTR_ID.equals(attrName)) {
createTime = Long.valueOf(attrValue);
@@ -1220,15 +1218,15 @@ final class ActivityRecord {
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
if (DEBUG_PERSISTER || DEBUG_RESTORER)
if (TaskPersister.DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
if (TAG_INTENT.equals(name)) {
intent = Intent.restoreFromXml(in);
if (DEBUG_PERSISTER || DEBUG_RESTORER)
if (TaskPersister.DEBUG)
Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
} else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
persistentState = PersistableBundle.restoreFromXml(in);
if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
"ActivityRecord: persistentState=" + persistentState);
} else {
Slog.w(TAG, "restoreActivity: unexpected name=" + name);

View File

@@ -59,8 +59,7 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
public class TaskPersister {
static final String TAG = "TaskPersister";
static final boolean DEBUG_PERSISTER = false;
static final boolean DEBUG_RESTORER = false;
static final boolean DEBUG = false;
/** When not flushing don't write out files faster than this */
private static final long INTER_WRITE_DELAY_MS = 500;
@@ -81,21 +80,10 @@ public class TaskPersister {
private static final String IMAGES_DIRNAME = "recent_images";
static final String IMAGE_EXTENSION = ".png";
// Directory where restored historical task XML/PNG files are placed. This directory
// contains subdirs named after TASKS_DIRNAME and IMAGES_DIRNAME mirroring the
// ancestral device's dataset. This needs to match the RECENTS_TASK_RESTORE_DIR
// value in RecentsBackupHelper.
private static final String RESTORED_TASKS_DIRNAME = "restored_" + TASKS_DIRNAME;
// Max time to wait for the application/package of a restored task to be installed
// before giving up.
private static final long MAX_INSTALL_WAIT_TIME = DateUtils.DAY_IN_MILLIS;
private static final String TAG_TASK = "task";
static File sImagesDir;
static File sTasksDir;
static File sRestoredTasksDir;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
@@ -129,23 +117,11 @@ public class TaskPersister {
ArrayList<WriteQueueItem> mWriteQueue = new ArrayList<WriteQueueItem>();
// Map of tasks that were backed-up on a different device that can be restored on this device.
// Data organization: <packageNameOfAffiliateTask, listOfAffiliatedTasksChains>
private ArrayMap<String, List<List<OtherDeviceTask>>> mOtherDeviceTasksMap =
new ArrayMap<>(10);
// Local cache of package names to uid used when restoring a task from another device.
private ArrayMap<String, Integer> mPackageUidMap;
// The next time in milliseconds we will remove expired task from
// {@link #mOtherDeviceTasksMap} and disk. Set to {@link Long.MAX_VALUE} to never clean-up
// tasks.
private long mExpiredTasksCleanupTime = Long.MAX_VALUE;
TaskPersister(File systemDir, ActivityStackSupervisor stackSupervisor,
RecentTasks recentTasks) {
sTasksDir = new File(systemDir, TASKS_DIRNAME);
if (!sTasksDir.exists()) {
if (DEBUG_PERSISTER) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
if (DEBUG) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
if (!sTasksDir.mkdir()) {
Slog.e(TAG, "Failure creating tasks directory " + sTasksDir);
}
@@ -153,14 +129,12 @@ public class TaskPersister {
sImagesDir = new File(systemDir, IMAGES_DIRNAME);
if (!sImagesDir.exists()) {
if (DEBUG_PERSISTER) Slog.d(TAG, "Creating images directory " + sTasksDir);
if (DEBUG) Slog.d(TAG, "Creating images directory " + sTasksDir);
if (!sImagesDir.mkdir()) {
Slog.e(TAG, "Failure creating images directory " + sImagesDir);
}
}
sRestoredTasksDir = new File(systemDir, RESTORED_TASKS_DIRNAME);
mStackSupervisor = stackSupervisor;
mService = stackSupervisor.mService;
mRecentTasks = recentTasks;
@@ -179,8 +153,8 @@ public class TaskPersister {
final WriteQueueItem item = mWriteQueue.get(queueNdx);
if (item instanceof ImageWriteQueueItem &&
((ImageWriteQueueItem) item).mFilename.startsWith(taskString)) {
if (DEBUG_PERSISTER) Slog.d(TAG, "Removing "
+ ((ImageWriteQueueItem) item).mFilename + " from write queue");
if (DEBUG) Slog.d(TAG, "Removing " + ((ImageWriteQueueItem) item).mFilename +
" from write queue");
mWriteQueue.remove(queueNdx);
}
}
@@ -225,9 +199,9 @@ public class TaskPersister {
} else if (mNextWriteTime == 0) {
mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
}
if (DEBUG_PERSISTER) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush
+ " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
+ mWriteQueue.size() + " Callers=" + Debug.getCallers(4));
if (DEBUG) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush + " mNextWriteTime="
+ mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size()
+ " Callers=" + Debug.getCallers(4));
notifyAll();
}
@@ -269,7 +243,7 @@ public class TaskPersister {
} else if (mNextWriteTime == 0) {
mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
}
if (DEBUG_PERSISTER) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
SystemClock.uptimeMillis() + " mNextWriteTime=" +
mNextWriteTime + " Callers=" + Debug.getCallers(4));
notifyAll();
@@ -303,12 +277,12 @@ public class TaskPersister {
}
private StringWriter saveToXml(TaskRecord task) throws IOException, XmlPullParserException {
if (DEBUG_PERSISTER) Slog.d(TAG, "saveToXml: task=" + task);
if (DEBUG) Slog.d(TAG, "saveToXml: task=" + task);
final XmlSerializer xmlSerializer = new FastXmlSerializer();
StringWriter stringWriter = new StringWriter();
xmlSerializer.setOutput(stringWriter);
if (DEBUG_PERSISTER) xmlSerializer.setFeature(
if (DEBUG) xmlSerializer.setFeature(
"http://xmlpull.org/v1/doc/features.html#indent-output", true);
// save task
@@ -367,7 +341,7 @@ public class TaskPersister {
for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
File taskFile = recentFiles[taskNdx];
if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
if (DEBUG) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
BufferedReader reader = null;
boolean deleteFile = false;
try {
@@ -380,12 +354,11 @@ public class TaskPersister {
event != XmlPullParser.END_TAG) {
final String name = in.getName();
if (event == XmlPullParser.START_TAG) {
if (DEBUG_PERSISTER)
Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
if (DEBUG) Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
if (TAG_TASK.equals(name)) {
final TaskRecord task =
TaskRecord.restoreFromXml(in, mStackSupervisor);
if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: restored task=" +
if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
task);
if (task != null) {
task.isPersistable = true;
@@ -414,15 +387,14 @@ public class TaskPersister {
deleteFile = true;
} finally {
IoUtils.closeQuietly(reader);
if (!DEBUG_PERSISTER && deleteFile) {
if (true || DEBUG_PERSISTER)
Slog.d(TAG, "Deleting file=" + taskFile.getName());
if (deleteFile) {
if (DEBUG) Slog.d(TAG, "Deleting file=" + taskFile.getName());
taskFile.delete();
}
}
}
if (!DEBUG_PERSISTER) {
if (!DEBUG) {
removeObsoleteFiles(recoveredTaskIds);
}
@@ -453,8 +425,8 @@ public class TaskPersister {
}
private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) {
if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds="
+ persistentTaskIds + " files=" + files);
if (DEBUG) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds=" + persistentTaskIds +
" files=" + files);
if (files == null) {
Slog.e(TAG, "File error accessing recents directory (too many files open?).");
return;
@@ -467,15 +439,14 @@ public class TaskPersister {
final int taskId;
try {
taskId = Integer.valueOf(filename.substring(0, taskIdEnd));
if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
if (DEBUG) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
} catch (Exception e) {
Slog.wtf(TAG, "removeObsoleteFile: Can't parse file=" + file.getName());
file.delete();
continue;
}
if (!persistentTaskIds.contains(taskId)) {
if (true || DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: deleting file=" +
file.getName());
if (DEBUG) Slog.d(TAG, "removeObsoleteFile: deleting file=" + file.getName());
file.delete();
}
}
@@ -488,441 +459,10 @@ public class TaskPersister {
}
static Bitmap restoreImage(String filename) {
if (DEBUG_PERSISTER) Slog.d(TAG, "restoreImage: restoring " + filename);
if (DEBUG) Slog.d(TAG, "restoreImage: restoring " + filename);
return BitmapFactory.decodeFile(sImagesDir + File.separator + filename);
}
/**
* Tries to restore task that were backed-up on a different device onto this device.
*/
void restoreTasksFromOtherDeviceLocked() {
readOtherDeviceTasksFromDisk();
addOtherDeviceTasksToRecentsLocked();
}
/**
* Read the tasks that were backed-up on a different device and can be restored to this device
* from disk and populated {@link #mOtherDeviceTasksMap} with the information. Also sets up
* time to clear out other device tasks that have not been restored on this device
* within the allotted time.
*/
private void readOtherDeviceTasksFromDisk() {
synchronized (mOtherDeviceTasksMap) {
// Clear out current map and expiration time.
mOtherDeviceTasksMap.clear();
mExpiredTasksCleanupTime = Long.MAX_VALUE;
final File[] taskFiles;
if (!sRestoredTasksDir.exists()
|| (taskFiles = sRestoredTasksDir.listFiles()) == null) {
// Nothing to do if there are no tasks to restore.
return;
}
long earliestMtime = System.currentTimeMillis();
SparseArray<List<OtherDeviceTask>> tasksByAffiliateIds =
new SparseArray<>(taskFiles.length);
// Read new tasks from disk
for (int i = 0; i < taskFiles.length; ++i) {
final File taskFile = taskFiles[i];
if (DEBUG_RESTORER) Slog.d(TAG, "readOtherDeviceTasksFromDisk: taskFile="
+ taskFile.getName());
final OtherDeviceTask task = OtherDeviceTask.createFromFile(taskFile);
if (task == null) {
// Go ahead and remove the file on disk if we are unable to create a task from
// it.
if (DEBUG_RESTORER) Slog.e(TAG, "Unable to create task for file="
+ taskFile.getName() + "...deleting file.");
taskFile.delete();
continue;
}
List<OtherDeviceTask> tasks = tasksByAffiliateIds.get(task.mAffiliatedTaskId);
if (tasks == null) {
tasks = new ArrayList<>();
tasksByAffiliateIds.put(task.mAffiliatedTaskId, tasks);
}
tasks.add(task);
final long taskMtime = taskFile.lastModified();
if (earliestMtime > taskMtime) {
earliestMtime = taskMtime;
}
}
if (tasksByAffiliateIds.size() > 0) {
// Sort each affiliated tasks chain by taskId which is the order they were created
// that should always be correct...Then add to task map.
for (int i = 0; i < tasksByAffiliateIds.size(); i++) {
List<OtherDeviceTask> chain = tasksByAffiliateIds.valueAt(i);
Collections.sort(chain);
// Package name of the root task in the affiliate chain.
final String packageName =
chain.get(chain.size()-1).mComponentName.getPackageName();
List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
if (chains == null) {
chains = new ArrayList<>();
mOtherDeviceTasksMap.put(packageName, chains);
}
chains.add(chain);
}
// Set expiration time.
mExpiredTasksCleanupTime = earliestMtime + MAX_INSTALL_WAIT_TIME;
if (DEBUG_RESTORER) Slog.d(TAG, "Set Expiration time to "
+ DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
}
}
}
/**
* Removed any expired tasks from {@link #mOtherDeviceTasksMap} and disk if their expiration
* time is less than or equal to {@link #mExpiredTasksCleanupTime}.
*/
private void removeExpiredTasksIfNeeded() {
synchronized (mOtherDeviceTasksMap) {
final long now = System.currentTimeMillis();
final boolean noMoreTasks = mOtherDeviceTasksMap.isEmpty();
if (noMoreTasks || now < mExpiredTasksCleanupTime) {
if (noMoreTasks && mPackageUidMap != null) {
// All done! package->uid map no longer needed.
mPackageUidMap = null;
}
return;
}
long earliestNonExpiredMtime = now;
mExpiredTasksCleanupTime = Long.MAX_VALUE;
// Remove expired backed-up tasks that have not been restored. We only want to
// remove task if it is safe to remove all tasks in the affiliation chain.
for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0 ; i--) {
List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.valueAt(i);
for (int j = chains.size() - 1; j >= 0 ; j--) {
List<OtherDeviceTask> chain = chains.get(j);
boolean removeChain = true;
for (int k = chain.size() - 1; k >= 0 ; k--) {
OtherDeviceTask task = chain.get(k);
final long taskLastModified = task.mFile.lastModified();
if ((taskLastModified + MAX_INSTALL_WAIT_TIME) > now) {
// File has not expired yet...but we keep looping to get the earliest
// mtime.
if (earliestNonExpiredMtime > taskLastModified) {
earliestNonExpiredMtime = taskLastModified;
}
removeChain = false;
}
}
if (removeChain) {
for (int k = chain.size() - 1; k >= 0; k--) {
final File file = chain.get(k).mFile;
if (DEBUG_RESTORER) Slog.d(TAG, "Deleting expired file="
+ file.getName() + " mapped to not installed component="
+ chain.get(k).mComponentName);
file.delete();
}
chains.remove(j);
}
}
if (chains.isEmpty()) {
final String packageName = mOtherDeviceTasksMap.keyAt(i);
mOtherDeviceTasksMap.removeAt(i);
if (DEBUG_RESTORER) Slog.d(TAG, "Removed package=" + packageName
+ " from task map");
}
}
// Reset expiration time if there is any task remaining.
if (!mOtherDeviceTasksMap.isEmpty()) {
mExpiredTasksCleanupTime = earliestNonExpiredMtime + MAX_INSTALL_WAIT_TIME;
if (DEBUG_RESTORER) Slog.d(TAG, "Reset expiration time to "
+ DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
} else {
// All done! package->uid map no longer needed.
mPackageUidMap = null;
}
}
}
/**
* Removes the input package name from the local package->uid map.
*/
void removeFromPackageCache(String packageName) {
synchronized (mOtherDeviceTasksMap) {
if (mPackageUidMap != null) {
mPackageUidMap.remove(packageName);
}
}
}
/**
* Tries to add all backed-up tasks from another device to this device recent's list.
*/
private void addOtherDeviceTasksToRecentsLocked() {
synchronized (mOtherDeviceTasksMap) {
for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0; i--) {
addOtherDeviceTasksToRecentsLocked(mOtherDeviceTasksMap.keyAt(i));
}
}
}
/**
* Tries to add backed-up tasks that are associated with the input package from
* another device to this device recent's list.
*/
void addOtherDeviceTasksToRecentsLocked(String packageName) {
synchronized (mOtherDeviceTasksMap) {
List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
if (chains == null) {
return;
}
for (int i = chains.size() - 1; i >= 0; i--) {
List<OtherDeviceTask> chain = chains.get(i);
if (!canAddOtherDeviceTaskChain(chain)) {
if (DEBUG_RESTORER) Slog.d(TAG, "Can't add task chain at index=" + i
+ " for package=" + packageName);
continue;
}
// Generate task records for this chain.
List<TaskRecord> tasks = new ArrayList<>();
TaskRecord prev = null;
for (int j = chain.size() - 1; j >= 0; j--) {
TaskRecord task = createTaskRecordLocked(chain.get(j));
if (task == null) {
// There was a problem in creating one of this task records in this chain.
// There is no way we can continue...
if (DEBUG_RESTORER) Slog.d(TAG, "Can't create task record for file="
+ chain.get(j).mFile + " for package=" + packageName);
break;
}
// Wire-up affiliation chain.
if (prev == null) {
task.mPrevAffiliate = null;
task.mPrevAffiliateTaskId = INVALID_TASK_ID;
task.mAffiliatedTaskId = task.taskId;
} else {
prev.mNextAffiliate = task;
prev.mNextAffiliateTaskId = task.taskId;
task.mAffiliatedTaskId = prev.mAffiliatedTaskId;
task.mPrevAffiliate = prev;
task.mPrevAffiliateTaskId = prev.taskId;
}
prev = task;
tasks.add(0, task);
}
// Add tasks to recent's if we were able to create task records for all the tasks
// in the chain.
if (tasks.size() == chain.size()) {
// Make sure there is space in recent's to add the new task. If there is space
// to the to the back.
// TODO: Would be more fancy to interleave the new tasks into recent's based on
// {@link TaskRecord.mLastTimeMoved} and drop the oldest recent's vs. just
// adding to the back of the list.
int spaceLeft =
ActivityManager.getMaxRecentTasksStatic() - mRecentTasks.size();
if (spaceLeft >= tasks.size()) {
mRecentTasks.addAll(mRecentTasks.size(), tasks);
for (int k = tasks.size() - 1; k >= 0; k--) {
// Persist new tasks.
wakeup(tasks.get(k), false);
}
if (DEBUG_RESTORER) Slog.d(TAG, "Added " + tasks.size()
+ " tasks to recent's for" + " package=" + packageName);
} else {
if (DEBUG_RESTORER) Slog.d(TAG, "Didn't add to recents. tasks.size("
+ tasks.size() + ") != chain.size(" + chain.size()
+ ") for package=" + packageName);
}
} else {
if (DEBUG_RESTORER) Slog.v(TAG, "Unable to add restored tasks to recents "
+ tasks.size() + " tasks for package=" + packageName);
}
// Clean-up structures
for (int j = chain.size() - 1; j >= 0; j--) {
chain.get(j).mFile.delete();
}
chains.remove(i);
if (chains.isEmpty()) {
// The fate of all backed-up tasks associated with this package has been
// determine. Go ahead and remove it from the to-process list.
mOtherDeviceTasksMap.remove(packageName);
if (DEBUG_RESTORER)
Slog.d(TAG, "Removed package=" + packageName + " from restore map");
}
}
}
}
/**
* Creates and returns {@link TaskRecord} for the task from another device that can be used on
* this device. Returns null if the operation failed.
*/
private TaskRecord createTaskRecordLocked(OtherDeviceTask other) {
File file = other.mFile;
BufferedReader reader = null;
TaskRecord task = null;
if (DEBUG_RESTORER) Slog.d(TAG, "createTaskRecordLocked: file=" + file.getName());
try {
reader = new BufferedReader(new FileReader(file));
final XmlPullParser in = Xml.newPullParser();
in.setInput(reader);
int event;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
&& event != XmlPullParser.END_TAG) {
final String name = in.getName();
if (event == XmlPullParser.START_TAG) {
if (TAG_TASK.equals(name)) {
// Create a task record using a task id that is valid for this device.
task = TaskRecord.restoreFromXml(
in, mStackSupervisor, mStackSupervisor.getNextTaskId());
if (DEBUG_RESTORER)
Slog.d(TAG, "createTaskRecordLocked: restored task=" + task);
if (task != null) {
task.isPersistable = true;
task.inRecents = true;
// Task can/should only be backed-up/restored for device owner.
task.userId = UserHandle.USER_OWNER;
// Clear out affiliated ids that are no longer valid on this device.
task.mAffiliatedTaskId = INVALID_TASK_ID;
task.mPrevAffiliateTaskId = INVALID_TASK_ID;
task.mNextAffiliateTaskId = INVALID_TASK_ID;
// Set up uids valid for this device.
Integer uid = mPackageUidMap.get(task.realActivity.getPackageName());
if (uid == null) {
// How did this happen???
Slog.wtf(TAG, "Can't find uid for task=" + task
+ " in mPackageUidMap=" + mPackageUidMap);
return null;
}
task.effectiveUid = task.mCallingUid = uid;
for (int i = task.mActivities.size() - 1; i >= 0; --i) {
final ActivityRecord activity = task.mActivities.get(i);
uid = mPackageUidMap.get(activity.launchedFromPackage);
if (uid == null) {
// How did this happen??
Slog.wtf(TAG, "Can't find uid for activity=" + activity
+ " in mPackageUidMap=" + mPackageUidMap);
return null;
}
activity.launchedFromUid = uid;
}
} else {
Slog.e(TAG, "Unable to create task for backed-up file=" + file + ": "
+ fileToString(file));
}
} else {
Slog.wtf(TAG, "createTaskRecordLocked Unknown xml event=" + event
+ " name=" + name);
}
}
XmlUtils.skipCurrentTag(in);
}
} catch (Exception e) {
Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
Slog.e(TAG, "Failing file: " + fileToString(file));
} finally {
IoUtils.closeQuietly(reader);
}
return task;
}
/**
* Returns true if the input task chain backed-up from another device can be restored on this
* device. Also, sets the {@link OtherDeviceTask#mUid} on the input tasks if they can be
* restored.
*/
private boolean canAddOtherDeviceTaskChain(List<OtherDeviceTask> chain) {
final ArraySet<ComponentName> validComponents = new ArraySet<>();
final IPackageManager pm = AppGlobals.getPackageManager();
for (int i = 0; i < chain.size(); i++) {
OtherDeviceTask task = chain.get(i);
// Quick check, we can't add the task chain if any of its task files don't exist.
if (!task.mFile.exists()) {
if (DEBUG_RESTORER) Slog.d(TAG,
"Can't add chain due to missing file=" + task.mFile);
return false;
}
// Verify task package is installed.
if (!isPackageInstalled(task.mComponentName.getPackageName())) {
return false;
}
// Verify that all the launch packages are installed.
if (task.mLaunchPackages != null) {
for (int j = task.mLaunchPackages.size() - 1; j >= 0; --j) {
if (!isPackageInstalled(task.mLaunchPackages.valueAt(j))) {
return false;
}
}
}
if (validComponents.contains(task.mComponentName)) {
// Existance of component has already been verified.
continue;
}
// Check to see if the specific component is installed.
try {
if (pm.getActivityInfo(task.mComponentName, 0, UserHandle.USER_OWNER) == null) {
// Component isn't installed...
return false;
}
validComponents.add(task.mComponentName);
} catch (RemoteException e) {
// Should not happen???
return false;
}
}
return true;
}
/**
* Returns true if the input package name is installed. If the package is installed, an entry
* for the package is added to {@link #mPackageUidMap}.
*/
private boolean isPackageInstalled(final String packageName) {
if (mPackageUidMap != null && mPackageUidMap.containsKey(packageName)) {
return true;
}
try {
int uid = AppGlobals.getPackageManager().getPackageUid(
packageName, UserHandle.USER_OWNER);
if (uid == -1) {
// package doesn't exist...
return false;
}
if (mPackageUidMap == null) {
mPackageUidMap = new ArrayMap<>();
}
mPackageUidMap.put(packageName, uid);
return true;
} catch (RemoteException e) {
// Should not happen???
return false;
}
}
private class LazyTaskWriterThread extends Thread {
LazyTaskWriterThread(String name) {
@@ -941,21 +481,20 @@ public class TaskPersister {
probablyDone = mWriteQueue.isEmpty();
}
if (probablyDone) {
if (DEBUG_PERSISTER) Slog.d(TAG, "Looking for obsolete files.");
if (DEBUG) Slog.d(TAG, "Looking for obsolete files.");
persistentTaskIds.clear();
synchronized (mService) {
if (DEBUG_PERSISTER) Slog.d(TAG, "mRecents=" + mRecentTasks);
if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mRecentTasks.get(taskNdx);
if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: task=" + task +
if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
" persistable=" + task.isPersistable);
if ((task.isPersistable || task.inRecents)
&& (task.stack == null || !task.stack.isHomeStack())) {
if (DEBUG_PERSISTER)
Slog.d(TAG, "adding to persistentTaskIds task=" + task);
if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
persistentTaskIds.add(task.taskId);
} else {
if (DEBUG_PERSISTER) Slog.d(TAG,
if (DEBUG) Slog.d(TAG,
"omitting from persistentTaskIds task=" + task);
}
}
@@ -969,7 +508,7 @@ public class TaskPersister {
if (mNextWriteTime != FLUSH_QUEUE) {
// The next write we don't have to wait so long.
mNextWriteTime = SystemClock.uptimeMillis() + INTER_WRITE_DELAY_MS;
if (DEBUG_PERSISTER) Slog.d(TAG, "Next write time may be in " +
if (DEBUG) Slog.d(TAG, "Next write time may be in " +
INTER_WRITE_DELAY_MS + " msec. (" + mNextWriteTime + ")");
}
@@ -979,13 +518,8 @@ public class TaskPersister {
mNextWriteTime = 0; // idle.
TaskPersister.this.notifyAll(); // wake up flush() if needed.
}
// See if we need to remove any expired back-up tasks before waiting.
removeExpiredTasksIfNeeded();
try {
if (DEBUG_PERSISTER)
Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
TaskPersister.this.wait();
} catch (InterruptedException e) {
}
@@ -995,12 +529,11 @@ public class TaskPersister {
item = mWriteQueue.remove(0);
long now = SystemClock.uptimeMillis();
if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: now=" + now
+ " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
+ mWriteQueue.size());
if (DEBUG) Slog.d(TAG, "LazyTaskWriter: now=" + now + " mNextWriteTime=" +
mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size());
while (now < mNextWriteTime) {
try {
if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: waiting " +
if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting " +
(mNextWriteTime - now));
TaskPersister.this.wait(mNextWriteTime - now);
} catch (InterruptedException e) {
@@ -1015,7 +548,7 @@ public class TaskPersister {
ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
final String filename = imageWriteQueueItem.mFilename;
final Bitmap bitmap = imageWriteQueueItem.mImage;
if (DEBUG_PERSISTER) Slog.d(TAG, "writing bitmap: filename=" + filename);
if (DEBUG) Slog.d(TAG, "writing bitmap: filename=" + filename);
FileOutputStream imageFile = null;
try {
imageFile = new FileOutputStream(new File(sImagesDir, filename));
@@ -1029,12 +562,12 @@ public class TaskPersister {
// Write out one task.
StringWriter stringWriter = null;
TaskRecord task = ((TaskWriteQueueItem) item).mTask;
if (DEBUG_PERSISTER) Slog.d(TAG, "Writing task=" + task);
if (DEBUG) Slog.d(TAG, "Writing task=" + task);
synchronized (mService) {
if (task.inRecents) {
// Still there.
try {
if (DEBUG_PERSISTER) Slog.d(TAG, "Saving task=" + task);
if (DEBUG) Slog.d(TAG, "Saving task=" + task);
stringWriter = saveToXml(task);
} catch (IOException e) {
} catch (XmlPullParserException e) {
@@ -1064,127 +597,4 @@ public class TaskPersister {
}
}
}
/**
* Helper class for holding essential information about task that were backed-up on a different
* device that can be restored on this device.
*/
private static class OtherDeviceTask implements Comparable<OtherDeviceTask> {
final File mFile;
// See {@link TaskRecord} for information on the fields below.
final ComponentName mComponentName;
final int mTaskId;
final int mAffiliatedTaskId;
// Names of packages that launched activities in this task. All packages listed here need
// to be installed on the current device in order for the task to be restored successfully.
final ArraySet<String> mLaunchPackages;
private OtherDeviceTask(File file, ComponentName componentName, int taskId,
int affiliatedTaskId, ArraySet<String> launchPackages) {
mFile = file;
mComponentName = componentName;
mTaskId = taskId;
mAffiliatedTaskId = (affiliatedTaskId == INVALID_TASK_ID) ? taskId: affiliatedTaskId;
mLaunchPackages = launchPackages;
}
@Override
public int compareTo(OtherDeviceTask another) {
return mTaskId - another.mTaskId;
}
/**
* Creates a new {@link OtherDeviceTask} object based on the contents of the input file.
*
* @param file input file that contains the complete task information.
* @return new {@link OtherDeviceTask} object or null if we failed to create the object.
*/
static OtherDeviceTask createFromFile(File file) {
if (file == null || !file.exists()) {
if (DEBUG_RESTORER)
Slog.d(TAG, "createFromFile: file=" + file + " doesn't exist.");
return null;
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
final XmlPullParser in = Xml.newPullParser();
in.setInput(reader);
int event;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
event != XmlPullParser.START_TAG) {
// Skip to the start tag or end of document
}
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
if (TAG_TASK.equals(name)) {
final int outerDepth = in.getDepth();
ComponentName componentName = null;
int taskId = INVALID_TASK_ID;
int taskAffiliation = INVALID_TASK_ID;
for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
final String attrName = in.getAttributeName(j);
final String attrValue = in.getAttributeValue(j);
if (TaskRecord.ATTR_REALACTIVITY.equals(attrName)) {
componentName = ComponentName.unflattenFromString(attrValue);
} else if (TaskRecord.ATTR_TASKID.equals(attrName)) {
taskId = Integer.valueOf(attrValue);
} else if (TaskRecord.ATTR_TASK_AFFILIATION.equals(attrName)) {
taskAffiliation = Integer.valueOf(attrValue);
}
}
if (componentName == null || taskId == INVALID_TASK_ID) {
if (DEBUG_RESTORER) Slog.e(TAG,
"createFromFile: FAILED componentName=" + componentName
+ " taskId=" + taskId + " file=" + file);
return null;
}
ArraySet<String> launchPackages = null;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
if (TaskRecord.TAG_ACTIVITY.equals(in.getName())) {
for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
if (ActivityRecord.ATTR_LAUNCHEDFROMPACKAGE.equals(
in.getAttributeName(j))) {
if (launchPackages == null) {
launchPackages = new ArraySet();
}
launchPackages.add(in.getAttributeValue(j));
}
}
} else {
XmlUtils.skipCurrentTag(in);
}
}
}
if (DEBUG_RESTORER) Slog.d(TAG, "creating OtherDeviceTask from file="
+ file.getName() + " componentName=" + componentName
+ " taskId=" + taskId + " launchPackages=" + launchPackages);
return new OtherDeviceTask(file, componentName, taskId,
taskAffiliation, launchPackages);
} else {
Slog.wtf(TAG,
"createFromFile: Unknown xml event=" + event + " name=" + name);
}
} else {
Slog.wtf(TAG, "createFromFile: Unable to find start tag in file=" + file);
}
} catch (IOException | XmlPullParserException e) {
Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
} finally {
IoUtils.closeQuietly(reader);
}
// Something went wrong...
return null;
}
}
}

View File

@@ -28,8 +28,6 @@ import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
import android.app.Activity;
import android.app.ActivityManager;
@@ -71,7 +69,7 @@ final class TaskRecord {
private static final String TAG_AFFINITYINTENT = "affinity_intent";
static final String ATTR_REALACTIVITY = "real_activity";
private static final String ATTR_ORIGACTIVITY = "orig_activity";
static final String TAG_ACTIVITY = "activity";
private static final String TAG_ACTIVITY = "activity";
private static final String ATTR_AFFINITY = "affinity";
private static final String ATTR_ROOT_AFFINITY = "root_affinity";
private static final String ATTR_ROOTHASRESET = "root_has_reset";
@@ -970,10 +968,6 @@ final class TaskRecord {
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
throws IOException, XmlPullParserException {
return restoreFromXml(in, stackSupervisor, INVALID_TASK_ID);
}
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor,
int inTaskId) throws IOException, XmlPullParserException {
Intent intent = null;
Intent affinityIntent = null;
ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
@@ -993,7 +987,7 @@ final class TaskRecord {
long lastActiveTime = -1;
long lastTimeOnTop = 0;
boolean neverRelinquishIdentity = true;
int taskId = inTaskId;
int taskId = INVALID_TASK_ID;
final int outerDepth = in.getDepth();
TaskDescription taskDescription = new TaskDescription();
int taskAffiliation = INVALID_TASK_ID;
@@ -1008,8 +1002,8 @@ final class TaskRecord {
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
final String attrValue = in.getAttributeValue(attrNdx);
if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
"TaskRecord: attribute name=" + attrName + " value=" + attrValue);
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
attrName + " value=" + attrValue);
if (ATTR_TASKID.equals(attrName)) {
if (taskId == INVALID_TASK_ID) taskId = Integer.valueOf(attrValue);
} else if (ATTR_REALACTIVITY.equals(attrName)) {
@@ -1071,16 +1065,16 @@ final class TaskRecord {
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
final String name = in.getName();
if (DEBUG_PERSISTER || DEBUG_RESTORER)
Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" + name);
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
name);
if (TAG_AFFINITYINTENT.equals(name)) {
affinityIntent = Intent.restoreFromXml(in);
} else if (TAG_INTENT.equals(name)) {
intent = Intent.restoreFromXml(in);
} else if (TAG_ACTIVITY.equals(name)) {
ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
if (DEBUG_PERSISTER || DEBUG_RESTORER)
Slog.d(TaskPersister.TAG, "TaskRecord: activity=" + activity);
if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
activity);
if (activity != null) {
activities.add(activity);
}