Merge "Revert "Fixing issue with old tasks being visible in Overview"" into nyc-mr1-dev
This commit is contained in:
@@ -6332,21 +6332,6 @@ public final class Settings {
|
|||||||
*/
|
*/
|
||||||
public static final String WEB_ACTION_ENABLED = "web_action_enabled";
|
public static final String WEB_ACTION_ENABLED = "web_action_enabled";
|
||||||
|
|
||||||
/**
|
|
||||||
* The uptime when tasks were last persisted. This is used to adjust the previous task
|
|
||||||
* active times to be relative to the current boot time.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final String TASK_PERSISTER_LAST_WRITE_UPTIME = "task_persister_write_uptime";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by Overview to keep track of the last visible task's active time to determine what
|
|
||||||
* should tasks be visible.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final String OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME =
|
|
||||||
"overview_last_visible_task_active_uptime";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This are the settings to be backed up.
|
* This are the settings to be backed up.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ public final class Prefs {
|
|||||||
Key.QS_WORK_ADDED,
|
Key.QS_WORK_ADDED,
|
||||||
})
|
})
|
||||||
public @interface Key {
|
public @interface Key {
|
||||||
@Deprecated
|
|
||||||
String OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME = "OverviewLastStackTaskActiveTime";
|
String OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME = "OverviewLastStackTaskActiveTime";
|
||||||
String DEBUG_MODE_ENABLED = "debugModeEnabled";
|
String DEBUG_MODE_ENABLED = "debugModeEnabled";
|
||||||
String HOTSPOT_TILE_LAST_USED = "HotspotTileLastUsed";
|
String HOTSPOT_TILE_LAST_USED = "HotspotTileLastUsed";
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import android.os.Build;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -47,7 +46,6 @@ import com.android.internal.logging.MetricsLogger;
|
|||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
import com.android.systemui.EventLogConstants;
|
import com.android.systemui.EventLogConstants;
|
||||||
import com.android.systemui.EventLogTags;
|
import com.android.systemui.EventLogTags;
|
||||||
import com.android.systemui.Prefs;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.RecentsComponent;
|
import com.android.systemui.RecentsComponent;
|
||||||
import com.android.systemui.SystemUI;
|
import com.android.systemui.SystemUI;
|
||||||
@@ -252,19 +250,6 @@ public class Recents extends SystemUI
|
|||||||
registerWithSystemUser();
|
registerWithSystemUser();
|
||||||
}
|
}
|
||||||
putComponent(Recents.class, this);
|
putComponent(Recents.class, this);
|
||||||
|
|
||||||
// Migrate the old stack active time if necessary, otherwise, it will already be managed
|
|
||||||
// when the tasks are loaded in the system. See TaskPersister.restoreTasksForUserLocked().
|
|
||||||
long lastVisibleTaskActiveTime = Prefs.getLong(mContext,
|
|
||||||
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, -1);
|
|
||||||
if (lastVisibleTaskActiveTime != -1) {
|
|
||||||
long uptime = SystemClock.elapsedRealtime();
|
|
||||||
Settings.Secure.putLongForUser(mContext.getContentResolver(),
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME,
|
|
||||||
uptime - Math.max(0, System.currentTimeMillis() - lastVisibleTaskActiveTime),
|
|
||||||
processUser);
|
|
||||||
Prefs.remove(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.app.Activity;
|
|||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
import android.app.TaskStackBuilder;
|
import android.app.TaskStackBuilder;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@@ -171,6 +170,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
|||||||
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
|
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
|
||||||
// When the screen turns off, dismiss Recents to Home
|
// When the screen turns off, dismiss Recents to Home
|
||||||
dismissRecentsToHomeIfVisible(false);
|
dismissRecentsToHomeIfVisible(false);
|
||||||
|
} else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
|
||||||
|
// For the time being, if the time changes, then invalidate the
|
||||||
|
// last-stack-active-time, this ensures that we will just show the last N tasks
|
||||||
|
// the next time that Recents loads, but prevents really old tasks from showing
|
||||||
|
// up if the task time is set forward.
|
||||||
|
Prefs.putLong(RecentsActivity.this, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -316,6 +322,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
|||||||
// Register the broadcast receiver to handle messages when the screen is turned off
|
// Register the broadcast receiver to handle messages when the screen is turned off
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||||
|
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||||
registerReceiver(mSystemBroadcastReceiver, filter);
|
registerReceiver(mSystemBroadcastReceiver, filter);
|
||||||
|
|
||||||
getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
|
getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
|
||||||
@@ -793,19 +800,14 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
|||||||
EventBus.getDefault().dump(prefix, writer);
|
EventBus.getDefault().dump(prefix, writer);
|
||||||
Recents.getTaskLoader().dump(prefix, writer);
|
Recents.getTaskLoader().dump(prefix, writer);
|
||||||
|
|
||||||
ContentResolver cr = getContentResolver();
|
|
||||||
long lastPersistUptime = Settings.Secure.getLong(cr,
|
|
||||||
Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, 0);
|
|
||||||
long lastVisibleTaskActiveUptime = Settings.Secure.getLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME,
|
|
||||||
SystemClock.elapsedRealtime(), Recents.getSystemServices().getCurrentUser());
|
|
||||||
|
|
||||||
String id = Integer.toHexString(System.identityHashCode(this));
|
String id = Integer.toHexString(System.identityHashCode(this));
|
||||||
|
long lastStackActiveTime = Prefs.getLong(this,
|
||||||
|
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, -1);
|
||||||
|
|
||||||
writer.print(prefix); writer.print(TAG);
|
writer.print(prefix); writer.print(TAG);
|
||||||
writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
|
writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
|
||||||
writer.print(" lastPersistUptime="); writer.print(lastPersistUptime);
|
writer.print(" lastStackTaskActiveTime="); writer.print(lastStackActiveTime);
|
||||||
writer.print(" lastVisibleTaskActiveUptime="); writer.print(lastVisibleTaskActiveUptime);
|
writer.print(" currentTime="); writer.print(System.currentTimeMillis());
|
||||||
writer.print(" [0x"); writer.print(id); writer.print("]");
|
writer.print(" [0x"); writer.print(id); writer.print("]");
|
||||||
writer.println();
|
writer.println();
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ import android.os.Looper;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
@@ -75,7 +74,6 @@ import android.view.WindowManager.KeyboardShortcutsReceiver;
|
|||||||
import android.view.WindowManagerGlobal;
|
import android.view.WindowManagerGlobal;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
import com.android.internal.app.AssistUtils;
|
import com.android.internal.app.AssistUtils;
|
||||||
import com.android.internal.os.BackgroundThread;
|
import com.android.internal.os.BackgroundThread;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -200,9 +198,6 @@ public class SystemServicesProxy {
|
|||||||
*/
|
*/
|
||||||
private List<TaskStackListener> mTaskStackListeners = new ArrayList<>();
|
private List<TaskStackListener> mTaskStackListeners = new ArrayList<>();
|
||||||
|
|
||||||
/** Test constructor */
|
|
||||||
@VisibleForTesting public SystemServicesProxy() {}
|
|
||||||
|
|
||||||
/** Private constructor */
|
/** Private constructor */
|
||||||
private SystemServicesProxy(Context context) {
|
private SystemServicesProxy(Context context) {
|
||||||
mAccm = AccessibilityManager.getInstance(context);
|
mAccm = AccessibilityManager.getInstance(context);
|
||||||
@@ -304,7 +299,7 @@ public class SystemServicesProxy {
|
|||||||
rti.baseIntent = new Intent();
|
rti.baseIntent = new Intent();
|
||||||
rti.baseIntent.setComponent(cn);
|
rti.baseIntent.setComponent(cn);
|
||||||
rti.description = description;
|
rti.description = description;
|
||||||
rti.firstActiveTime = rti.lastActiveTime = SystemClock.elapsedRealtime();
|
rti.firstActiveTime = rti.lastActiveTime = i;
|
||||||
if (i % 2 == 0) {
|
if (i % 2 == 0) {
|
||||||
rti.taskDescription = new ActivityManager.TaskDescription(description,
|
rti.taskDescription = new ActivityManager.TaskDescription(description,
|
||||||
Bitmap.createBitmap(mDummyIcon), null,
|
Bitmap.createBitmap(mDummyIcon), null,
|
||||||
|
|||||||
@@ -24,15 +24,13 @@ import android.content.pm.UserInfo;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.systemui.Prefs;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.recents.Recents;
|
import com.android.systemui.recents.Recents;
|
||||||
import com.android.systemui.recents.RecentsConfiguration;
|
import com.android.systemui.recents.RecentsConfiguration;
|
||||||
@@ -58,11 +56,6 @@ public class RecentsTaskLoadPlan {
|
|||||||
private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
|
private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
|
||||||
6 /* hrs */;
|
6 /* hrs */;
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public interface SystemTimeProvider {
|
|
||||||
public long getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The set of conditions to load tasks. */
|
/** The set of conditions to load tasks. */
|
||||||
public static class Options {
|
public static class Options {
|
||||||
public int runningTaskId = -1;
|
public int runningTaskId = -1;
|
||||||
@@ -74,46 +67,15 @@ public class RecentsTaskLoadPlan {
|
|||||||
public int numVisibleTaskThumbnails = 0;
|
public int numVisibleTaskThumbnails = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Context mContext;
|
Context mContext;
|
||||||
@VisibleForTesting private SystemServicesProxy mSystemServicesProxy;
|
|
||||||
|
|
||||||
private List<ActivityManager.RecentTaskInfo> mRawTasks;
|
List<ActivityManager.RecentTaskInfo> mRawTasks;
|
||||||
private long mLastVisibileTaskActiveTime;
|
TaskStack mStack;
|
||||||
private TaskStack mStack;
|
ArraySet<Integer> mCurrentQuietProfiles = new ArraySet<Integer>();
|
||||||
private ArraySet<Integer> mCurrentQuietProfiles = new ArraySet<Integer>();
|
|
||||||
private SystemTimeProvider mTimeProvider = new SystemTimeProvider() {
|
|
||||||
@Override
|
|
||||||
public long getTime() {
|
|
||||||
return SystemClock.elapsedRealtime();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@VisibleForTesting
|
/** Package level ctor */
|
||||||
public RecentsTaskLoadPlan(Context context, SystemServicesProxy ssp) {
|
RecentsTaskLoadPlan(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mSystemServicesProxy = ssp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public void setInternals(List<ActivityManager.RecentTaskInfo> tasks,
|
|
||||||
final long currentTime, long lastVisibleTaskActiveTime) {
|
|
||||||
setInternals(tasks, MIN_NUM_TASKS, currentTime, lastVisibleTaskActiveTime,
|
|
||||||
SESSION_BEGIN_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public void setInternals(List<ActivityManager.RecentTaskInfo> tasks, int minNumTasks,
|
|
||||||
final long currentTime, long lastVisibleTaskActiveTime, int sessionBeginTime) {
|
|
||||||
mRawTasks = tasks;
|
|
||||||
mLastVisibileTaskActiveTime = lastVisibleTaskActiveTime;
|
|
||||||
mTimeProvider = new SystemTimeProvider() {
|
|
||||||
@Override
|
|
||||||
public long getTime() {
|
|
||||||
return currentTime;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MIN_NUM_TASKS = minNumTasks;
|
|
||||||
SESSION_BEGIN_TIME = sessionBeginTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCurrentQuietProfilesCache(int currentUserId) {
|
private void updateCurrentQuietProfilesCache(int currentUserId) {
|
||||||
@@ -141,13 +103,9 @@ public class RecentsTaskLoadPlan {
|
|||||||
public synchronized void preloadRawTasks(boolean includeFrontMostExcludedTask) {
|
public synchronized void preloadRawTasks(boolean includeFrontMostExcludedTask) {
|
||||||
int currentUserId = UserHandle.USER_CURRENT;
|
int currentUserId = UserHandle.USER_CURRENT;
|
||||||
updateCurrentQuietProfilesCache(currentUserId);
|
updateCurrentQuietProfilesCache(currentUserId);
|
||||||
mRawTasks = mSystemServicesProxy.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
|
mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
|
||||||
currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
|
currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
|
||||||
mLastVisibileTaskActiveTime = RecentsDebugFlags.Static.EnableMockTasks
|
|
||||||
? SystemClock.elapsedRealtime()
|
|
||||||
: Settings.Secure.getLongForUser(mContext.getContentResolver(),
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME,
|
|
||||||
0, currentUserId);
|
|
||||||
|
|
||||||
// Since the raw tasks are given in most-recent to least-recent order, we need to reverse it
|
// Since the raw tasks are given in most-recent to least-recent order, we need to reverse it
|
||||||
Collections.reverse(mRawTasks);
|
Collections.reverse(mRawTasks);
|
||||||
@@ -176,9 +134,12 @@ public class RecentsTaskLoadPlan {
|
|||||||
R.string.accessibility_recents_item_will_be_dismissed);
|
R.string.accessibility_recents_item_will_be_dismissed);
|
||||||
String appInfoDescFormat = mContext.getString(
|
String appInfoDescFormat = mContext.getString(
|
||||||
R.string.accessibility_recents_item_open_app_info);
|
R.string.accessibility_recents_item_open_app_info);
|
||||||
boolean updatedLastVisibleTaskActiveTime = false;
|
long lastStackActiveTime = Prefs.getLong(mContext,
|
||||||
long newLastVisibileTaskActiveTime = 0;
|
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
|
||||||
long currentTime = mTimeProvider.getTime();
|
if (RecentsDebugFlags.Static.EnableMockTasks) {
|
||||||
|
lastStackActiveTime = 0;
|
||||||
|
}
|
||||||
|
long newLastStackActiveTime = -1;
|
||||||
int taskCount = mRawTasks.size();
|
int taskCount = mRawTasks.size();
|
||||||
for (int i = 0; i < taskCount; i++) {
|
for (int i = 0; i < taskCount; i++) {
|
||||||
ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
|
ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
|
||||||
@@ -187,20 +148,19 @@ public class RecentsTaskLoadPlan {
|
|||||||
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
|
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
|
||||||
t.userId, t.firstActiveTime, t.lastActiveTime);
|
t.userId, t.firstActiveTime, t.lastActiveTime);
|
||||||
|
|
||||||
// Only show the task if it is freeform, or later than the last visible task active time
|
// This task is only shown in the stack if it statisfies the historical time or min
|
||||||
// and either recently used, or within the last five tasks
|
// number of tasks constraints. Freeform tasks are also always shown.
|
||||||
boolean isFreeformTask = mSystemServicesProxy.isFreeformStack(t.stackId);
|
boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
|
||||||
boolean isRecentlyUsedTask = t.lastActiveTime >= (currentTime - SESSION_BEGIN_TIME);
|
boolean isStackTask = isFreeformTask || !isHistoricalTask(t) ||
|
||||||
boolean isMoreRecentThanLastVisible = t.lastActiveTime >= mLastVisibileTaskActiveTime;
|
(t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS));
|
||||||
boolean isStackTask = isFreeformTask || (isMoreRecentThanLastVisible &&
|
boolean isLaunchTarget = taskKey.id == runningTaskId;
|
||||||
(isRecentlyUsedTask || i >= (taskCount - MIN_NUM_TASKS)));
|
|
||||||
boolean isLaunchTarget = t.persistentId == runningTaskId;
|
|
||||||
|
|
||||||
// If this is the first task satisfying the stack constraints, update the baseline
|
// The last stack active time is the baseline for which we show visible tasks. Since
|
||||||
// at which we show visible tasks
|
// the system will store all the tasks, we don't want to show the tasks prior to the
|
||||||
if (isStackTask && !updatedLastVisibleTaskActiveTime) {
|
// last visible ones, otherwise, as you dismiss them, the previous tasks may satisfy
|
||||||
newLastVisibileTaskActiveTime = t.lastActiveTime;
|
// the other stack-task constraints.
|
||||||
updatedLastVisibleTaskActiveTime = true;
|
if (isStackTask && newLastStackActiveTime < 0) {
|
||||||
|
newLastStackActiveTime = t.lastActiveTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the title, icon, and color
|
// Load the title, icon, and color
|
||||||
@@ -228,12 +188,9 @@ public class RecentsTaskLoadPlan {
|
|||||||
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
|
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
|
||||||
affiliatedTasks.put(taskKey.id, taskKey);
|
affiliatedTasks.put(taskKey.id, taskKey);
|
||||||
}
|
}
|
||||||
if (updatedLastVisibleTaskActiveTime &&
|
if (newLastStackActiveTime != -1) {
|
||||||
newLastVisibileTaskActiveTime != mLastVisibileTaskActiveTime) {
|
Prefs.putLong(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
|
||||||
Settings.Secure.putLongForUser(mContext.getContentResolver(),
|
newLastStackActiveTime);
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME,
|
|
||||||
newLastVisibileTaskActiveTime, UserHandle.USER_CURRENT);
|
|
||||||
mLastVisibileTaskActiveTime = newLastVisibileTaskActiveTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the stacks
|
// Initialize the stacks
|
||||||
@@ -298,4 +255,11 @@ public class RecentsTaskLoadPlan {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this task is too old to be shown.
|
||||||
|
*/
|
||||||
|
private boolean isHistoricalTask(ActivityManager.RecentTaskInfo t) {
|
||||||
|
return t.lastActiveTime < (System.currentTimeMillis() - SESSION_BEGIN_TIME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import android.os.HandlerThread;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.recents.Recents;
|
import com.android.systemui.recents.Recents;
|
||||||
import com.android.systemui.recents.RecentsConfiguration;
|
import com.android.systemui.recents.RecentsConfiguration;
|
||||||
@@ -287,20 +286,6 @@ public class RecentsTaskLoader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public RecentsTaskLoader() {
|
|
||||||
mActivityInfoCache = null;
|
|
||||||
mIconCache = null;
|
|
||||||
mThumbnailCache = null;
|
|
||||||
mActivityLabelCache = null;
|
|
||||||
mContentDescriptionCache = null;
|
|
||||||
mLoadQueue = null;
|
|
||||||
mLoader = null;
|
|
||||||
|
|
||||||
mMaxThumbnailCacheSize = 0;
|
|
||||||
mMaxIconCacheSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecentsTaskLoader(Context context) {
|
public RecentsTaskLoader(Context context) {
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
mDefaultTaskBarBackgroundColor =
|
mDefaultTaskBarBackgroundColor =
|
||||||
@@ -347,8 +332,7 @@ public class RecentsTaskLoader {
|
|||||||
|
|
||||||
/** Creates a new plan for loading the recent tasks. */
|
/** Creates a new plan for loading the recent tasks. */
|
||||||
public RecentsTaskLoadPlan createLoadPlan(Context context) {
|
public RecentsTaskLoadPlan createLoadPlan(Context context) {
|
||||||
RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(context,
|
RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(context);
|
||||||
Recents.getSystemServices());
|
|
||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,8 +455,7 @@ public class RecentsTaskLoader {
|
|||||||
/**
|
/**
|
||||||
* Returns the cached task label if the task key is not expired, updating the cache if it is.
|
* Returns the cached task label if the task key is not expired, updating the cache if it is.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public String getAndUpdateActivityTitle(Task.TaskKey taskKey,
|
String getAndUpdateActivityTitle(Task.TaskKey taskKey, ActivityManager.TaskDescription td) {
|
||||||
ActivityManager.TaskDescription td) {
|
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
|
|
||||||
// Return the task description label if it exists
|
// Return the task description label if it exists
|
||||||
@@ -500,8 +483,7 @@ public class RecentsTaskLoader {
|
|||||||
* Returns the cached task content description if the task key is not expired, updating the
|
* Returns the cached task content description if the task key is not expired, updating the
|
||||||
* cache if it is.
|
* cache if it is.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public String getAndUpdateContentDescription(Task.TaskKey taskKey,
|
String getAndUpdateContentDescription(Task.TaskKey taskKey, Resources res) {
|
||||||
Resources res) {
|
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
|
|
||||||
// Return the cached content description if it exists
|
// Return the cached content description if it exists
|
||||||
@@ -525,8 +507,8 @@ public class RecentsTaskLoader {
|
|||||||
/**
|
/**
|
||||||
* Returns the cached task icon if the task key is not expired, updating the cache if it is.
|
* Returns the cached task icon if the task key is not expired, updating the cache if it is.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey,
|
Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey, ActivityManager.TaskDescription td,
|
||||||
ActivityManager.TaskDescription td, Resources res, boolean loadIfNotCached) {
|
Resources res, boolean loadIfNotCached) {
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
|
|
||||||
// Return the cached activity icon if it exists
|
// Return the cached activity icon if it exists
|
||||||
@@ -560,8 +542,7 @@ public class RecentsTaskLoader {
|
|||||||
/**
|
/**
|
||||||
* Returns the cached thumbnail if the task key is not expired, updating the cache if it is.
|
* Returns the cached thumbnail if the task key is not expired, updating the cache if it is.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey,
|
Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) {
|
||||||
boolean loadIfNotCached) {
|
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
|
|
||||||
// Return the cached thumbnail if it exists
|
// Return the cached thumbnail if it exists
|
||||||
@@ -589,7 +570,7 @@ public class RecentsTaskLoader {
|
|||||||
* Returns the task's primary color if possible, defaulting to the default color if there is
|
* Returns the task's primary color if possible, defaulting to the default color if there is
|
||||||
* no specified primary color.
|
* no specified primary color.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public int getActivityPrimaryColor(ActivityManager.TaskDescription td) {
|
int getActivityPrimaryColor(ActivityManager.TaskDescription td) {
|
||||||
if (td != null && td.getPrimaryColor() != 0) {
|
if (td != null && td.getPrimaryColor() != 0) {
|
||||||
return td.getPrimaryColor();
|
return td.getPrimaryColor();
|
||||||
}
|
}
|
||||||
@@ -599,7 +580,7 @@ public class RecentsTaskLoader {
|
|||||||
/**
|
/**
|
||||||
* Returns the task's background color if possible.
|
* Returns the task's background color if possible.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public int getActivityBackgroundColor(ActivityManager.TaskDescription td) {
|
int getActivityBackgroundColor(ActivityManager.TaskDescription td) {
|
||||||
if (td != null && td.getBackgroundColor() != 0) {
|
if (td != null && td.getBackgroundColor() != 0) {
|
||||||
return td.getBackgroundColor();
|
return td.getBackgroundColor();
|
||||||
}
|
}
|
||||||
@@ -610,7 +591,7 @@ public class RecentsTaskLoader {
|
|||||||
* Returns the activity info for the given task key, retrieving one from the system if the
|
* Returns the activity info for the given task key, retrieving one from the system if the
|
||||||
* task key is expired.
|
* task key is expired.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting public ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) {
|
ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) {
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
ComponentName cn = taskKey.getComponent();
|
ComponentName cn = taskKey.getComponent();
|
||||||
ActivityInfo activityInfo = mActivityInfoCache.get(cn);
|
ActivityInfo activityInfo = mActivityInfoCache.get(cn);
|
||||||
|
|||||||
@@ -290,11 +290,8 @@ public class Task {
|
|||||||
*/
|
*/
|
||||||
public boolean isFreeformTask() {
|
public boolean isFreeformTask() {
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||||
if (ssp != null) {
|
|
||||||
return ssp.hasFreeformWorkspaceSupport() && ssp.isFreeformStack(key.stackId);
|
return ssp.hasFreeformWorkspaceSupport() && ssp.isFreeformStack(key.stackId);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Notifies the callback listeners that this task has been loaded */
|
/** Notifies the callback listeners that this task has been loaded */
|
||||||
public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon,
|
public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon,
|
||||||
|
|||||||
@@ -1,340 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 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.systemui.recents;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
|
||||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
|
||||||
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
|
|
||||||
import com.android.systemui.recents.model.RecentsTaskLoader;
|
|
||||||
import com.android.systemui.recents.model.Task;
|
|
||||||
import com.android.systemui.recents.model.TaskStack;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mock task loader that does not actually load any tasks.
|
|
||||||
*/
|
|
||||||
class MockRecentsTaskNonLoader extends RecentsTaskLoader {
|
|
||||||
@Override
|
|
||||||
public String getAndUpdateActivityTitle(Task.TaskKey taskKey, ActivityManager.TaskDescription td) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAndUpdateContentDescription(Task.TaskKey taskKey, Resources res) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey, ActivityManager.TaskDescription td, Resources res, boolean loadIfNotCached) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getActivityPrimaryColor(ActivityManager.TaskDescription td) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getActivityBackgroundColor(ActivityManager.TaskDescription td) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO(winsonc):
|
|
||||||
* - add test to ensure excluded tasks are loaded at the front of the list
|
|
||||||
* - add test to ensure the last visible task active time is migrated from absolute to uptime
|
|
||||||
*/
|
|
||||||
public class RecentsTaskLoadPlanTest extends SysuiTestCase {
|
|
||||||
private static final String TAG = "RecentsTaskLoadPlanTest";
|
|
||||||
|
|
||||||
private MockRecentsTaskNonLoader mDummyLoader = new MockRecentsTaskNonLoader();
|
|
||||||
private SystemServicesProxy mDummySsp = new SystemServicesProxy();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testEmptyRecents() {
|
|
||||||
RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(getTestContext(), mDummySsp);
|
|
||||||
ArrayList<ActivityManager.RecentTaskInfo> tasks = new ArrayList<>();
|
|
||||||
loadPlan.setInternals(tasks, 0 /* current */, 0 /* lastVisibleTaskActive */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0 /* runningTaskId */,
|
|
||||||
false /* includeFrontMostExcludedTask */);
|
|
||||||
assertFalse("Expected task to be empty", loadPlan.getTaskStack().getStackTaskCount() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLessThanEqualMinTasks() {
|
|
||||||
RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(getTestContext(), mDummySsp);
|
|
||||||
ArrayList<ActivityManager.RecentTaskInfo> tasks = new ArrayList<>();
|
|
||||||
int minTasks = 3;
|
|
||||||
|
|
||||||
resetTaskInfoList(tasks,
|
|
||||||
createTaskInfo(0, 1),
|
|
||||||
createTaskInfo(1, 2),
|
|
||||||
createTaskInfo(2, 3));
|
|
||||||
|
|
||||||
// Ensure that all tasks are loaded if the tasks are within the session and after the last
|
|
||||||
// visible active time (all tasks are loaded because there are < minTasks number of tasks)
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 0 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 1 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
0 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 1 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 3 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 3 /* current */, 1 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
// Ensure that only tasks are not loaded if are after the last visible active time, even if
|
|
||||||
// they are within the session
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 1 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 2 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 1, 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 3 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 50 /* current */, 50 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMoreThanMinTasks() {
|
|
||||||
RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(getTestContext(), mDummySsp);
|
|
||||||
ArrayList<ActivityManager.RecentTaskInfo> tasks = new ArrayList<>();
|
|
||||||
int minTasks = 3;
|
|
||||||
|
|
||||||
// Create all tasks within the session
|
|
||||||
resetTaskInfoList(tasks,
|
|
||||||
createTaskInfo(0, 1),
|
|
||||||
createTaskInfo(1, 50),
|
|
||||||
createTaskInfo(2, 100),
|
|
||||||
createTaskInfo(3, 101),
|
|
||||||
createTaskInfo(4, 102),
|
|
||||||
createTaskInfo(5, 103));
|
|
||||||
|
|
||||||
// Ensure that only the tasks that are within the window but after the last visible active
|
|
||||||
// time is loaded, or the minTasks number of tasks are loaded if there are less than that
|
|
||||||
|
|
||||||
// Session window shifts
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 0 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 1 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 51 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 52 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 100 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 101 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 103 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 151 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 200 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
50 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 3, 4, 5);
|
|
||||||
|
|
||||||
// Last visible active time shifts (everything is in window)
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 0 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 1 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 2 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 50 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 51 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 100 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 2, 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 101 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 3, 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 102 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2, 3);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 4, 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 103 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4);
|
|
||||||
assertTasksInStack(loadPlan.getTaskStack(), 5);
|
|
||||||
|
|
||||||
loadPlan.setInternals(tasks, minTasks, 150 /* current */, 104 /* lastVisibleTaskActive */,
|
|
||||||
150 /* sessionBegin */);
|
|
||||||
loadPlan.preloadPlan(mDummyLoader, 0, false);
|
|
||||||
assertTasksNotInStack(loadPlan.getTaskStack(), 0, 1, 2, 3, 4, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ActivityManager.RecentTaskInfo createTaskInfo(int taskId, long lastActiveTime) {
|
|
||||||
ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo();
|
|
||||||
info.id = info.persistentId = taskId;
|
|
||||||
info.lastActiveTime = lastActiveTime;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetTaskInfoList(ArrayList<ActivityManager.RecentTaskInfo> tasks,
|
|
||||||
ActivityManager.RecentTaskInfo ... infos) {
|
|
||||||
tasks.clear();
|
|
||||||
for (ActivityManager.RecentTaskInfo info : infos) {
|
|
||||||
tasks.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertTasksInStack(TaskStack stack, int... taskIds) {
|
|
||||||
for (int taskId : taskIds) {
|
|
||||||
assertNotNull("Expected task " + taskId + " in stack", stack.findTaskWithId(taskId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertTasksNotInStack(TaskStack stack, int... taskIds) {
|
|
||||||
for (int taskId : taskIds) {
|
|
||||||
assertNull("Expected task " + taskId + " not in stack", stack.findTaskWithId(taskId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.server.am;
|
package com.android.server.am;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
@@ -25,7 +24,6 @@ import android.os.Environment;
|
|||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -82,7 +80,7 @@ public class TaskPersister {
|
|||||||
private static final String PERSISTED_TASK_IDS_FILENAME = "persisted_taskIds.txt";
|
private static final String PERSISTED_TASK_IDS_FILENAME = "persisted_taskIds.txt";
|
||||||
static final String IMAGE_EXTENSION = ".png";
|
static final String IMAGE_EXTENSION = ".png";
|
||||||
|
|
||||||
@VisibleForTesting static final String TAG_TASK = "task";
|
private static final String TAG_TASK = "task";
|
||||||
|
|
||||||
private final ActivityManagerService mService;
|
private final ActivityManagerService mService;
|
||||||
private final ActivityStackSupervisor mStackSupervisor;
|
private final ActivityStackSupervisor mStackSupervisor;
|
||||||
@@ -409,43 +407,18 @@ public class TaskPersister {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
List<TaskRecord> restoreTasksForUserLocked(final int userId) {
|
List<TaskRecord> restoreTasksForUserLocked(final int userId) {
|
||||||
final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
|
final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
|
||||||
ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
|
ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
|
||||||
|
|
||||||
File userTasksDir = getUserTasksDir(userId);
|
File userTasksDir = getUserTasksDir(userId);
|
||||||
|
|
||||||
File[] recentFiles = userTasksDir.listFiles();
|
File[] recentFiles = userTasksDir.listFiles();
|
||||||
if (recentFiles == null) {
|
if (recentFiles == null) {
|
||||||
Slog.e(TAG, "restoreTasksForUserLocked: Unable to list files from " + userTasksDir);
|
Slog.e(TAG, "restoreTasksForUserLocked: Unable to list files from " + userTasksDir);
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the last persist uptime so we know how to adjust the first/last active times for each
|
|
||||||
// task
|
|
||||||
ContentResolver cr = mService.mContext.getContentResolver();
|
|
||||||
long lastPersistUptime = Settings.Secure.getLong(cr,
|
|
||||||
Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, 0);
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TaskPersister.TAG, "restoreTasksForUserLocked: lastPersistUptime=" +
|
|
||||||
lastPersistUptime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the overview last visible task active time as we adjust the task active times when
|
|
||||||
// loading. See TaskRecord.restoreFromXml(). If we have not migrated yet, SystemUI will
|
|
||||||
// migrate the old value into the system setting.
|
|
||||||
if (lastPersistUptime > 0) {
|
|
||||||
long overviewLastActiveTime = Settings.Secure.getLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, 0, userId);
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TaskPersister.TAG, "restoreTasksForUserLocked: overviewLastActiveTime=" +
|
|
||||||
overviewLastActiveTime + " lastPersistUptime=" + lastPersistUptime);
|
|
||||||
}
|
|
||||||
Settings.Secure.putLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME,
|
|
||||||
-lastPersistUptime + overviewLastActiveTime, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
|
for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
|
||||||
File taskFile = recentFiles[taskNdx];
|
File taskFile = recentFiles[taskNdx];
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -466,11 +439,15 @@ public class TaskPersister {
|
|||||||
if (event == XmlPullParser.START_TAG) {
|
if (event == XmlPullParser.START_TAG) {
|
||||||
if (DEBUG) Slog.d(TAG, "restoreTasksForUserLocked: START_TAG name=" + name);
|
if (DEBUG) Slog.d(TAG, "restoreTasksForUserLocked: START_TAG name=" + name);
|
||||||
if (TAG_TASK.equals(name)) {
|
if (TAG_TASK.equals(name)) {
|
||||||
final TaskRecord task = TaskRecord.restoreFromXml(in, mService,
|
final TaskRecord task = TaskRecord.restoreFromXml(in, mStackSupervisor);
|
||||||
mStackSupervisor, lastPersistUptime);
|
|
||||||
if (DEBUG) Slog.d(TAG, "restoreTasksForUserLocked: restored task="
|
if (DEBUG) Slog.d(TAG, "restoreTasksForUserLocked: restored task="
|
||||||
+ task);
|
+ task);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
|
// XXX Don't add to write queue... there is no reason to write
|
||||||
|
// out the stuff we just read, if we don't write it we will
|
||||||
|
// read the same thing again.
|
||||||
|
// mWriteQueue.add(new TaskWriteQueueItem(task));
|
||||||
|
|
||||||
final int taskId = task.taskId;
|
final int taskId = task.taskId;
|
||||||
if (mStackSupervisor.anyTaskForIdLocked(taskId,
|
if (mStackSupervisor.anyTaskForIdLocked(taskId,
|
||||||
/* restoreFromRecents= */ false, 0) != null) {
|
/* restoreFromRecents= */ false, 0) != null) {
|
||||||
@@ -486,12 +463,6 @@ public class TaskPersister {
|
|||||||
task.isPersistable = true;
|
task.isPersistable = true;
|
||||||
tasks.add(task);
|
tasks.add(task);
|
||||||
recoveredTaskIds.add(taskId);
|
recoveredTaskIds.add(taskId);
|
||||||
|
|
||||||
// We've shifted the first and last active times, so we need to
|
|
||||||
// persist the new task data to disk otherwise they will not
|
|
||||||
// have the updated values. This is only done once whenever
|
|
||||||
// the recents are first loaded for the user.
|
|
||||||
wakeup(task, false);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "restoreTasksForUserLocked: Unable to restore taskFile="
|
Slog.e(TAG, "restoreTasksForUserLocked: Unable to restore taskFile="
|
||||||
@@ -780,15 +751,6 @@ public class TaskPersister {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always update the task persister uptime when updating any tasks
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TAG, "LazyTaskWriter: Updating last write uptime=" +
|
|
||||||
SystemClock.elapsedRealtime());
|
|
||||||
}
|
|
||||||
Settings.Secure.putLong(mService.mContext.getContentResolver(),
|
|
||||||
Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME,
|
|
||||||
SystemClock.elapsedRealtime());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,12 @@ import android.graphics.Rect;
|
|||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.voice.IVoiceInteractionSession;
|
import android.service.voice.IVoiceInteractionSession;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
import com.android.internal.app.IVoiceInteractor;
|
import com.android.internal.app.IVoiceInteractor;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
@@ -152,10 +150,8 @@ final class TaskRecord {
|
|||||||
ComponentName realActivity; // The actual activity component that started the task.
|
ComponentName realActivity; // The actual activity component that started the task.
|
||||||
boolean realActivitySuspended; // True if the actual activity component that started the
|
boolean realActivitySuspended; // True if the actual activity component that started the
|
||||||
// task is suspended.
|
// task is suspended.
|
||||||
long firstActiveTime; // First time this task was active, relative to boot time. This can be
|
long firstActiveTime; // First time this task was active.
|
||||||
// negative if this task was last used prior to boot.
|
long lastActiveTime; // Last time this task was active, including sleep.
|
||||||
long lastActiveTime; // Last time this task was active, relative to boot time. This can be
|
|
||||||
// negative if this task was last used prior to boot.
|
|
||||||
boolean inRecents; // Actually in the recents list?
|
boolean inRecents; // Actually in the recents list?
|
||||||
boolean isAvailable; // Is the activity available to be launched?
|
boolean isAvailable; // Is the activity available to be launched?
|
||||||
boolean rootWasReset; // True if the intent at the root of the task had
|
boolean rootWasReset; // True if the intent at the root of the task had
|
||||||
@@ -381,14 +377,14 @@ final class TaskRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void touchActiveTime() {
|
void touchActiveTime() {
|
||||||
lastActiveTime = SystemClock.elapsedRealtime();
|
lastActiveTime = System.currentTimeMillis();
|
||||||
if (firstActiveTime == 0) {
|
if (firstActiveTime == 0) {
|
||||||
firstActiveTime = lastActiveTime;
|
firstActiveTime = lastActiveTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long getInactiveDuration() {
|
long getInactiveDuration() {
|
||||||
return SystemClock.elapsedRealtime() - lastActiveTime;
|
return System.currentTimeMillis() - lastActiveTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the original intent, and the calling uid and package. */
|
/** Sets the original intent, and the calling uid and package. */
|
||||||
@@ -459,8 +455,7 @@ final class TaskRecord {
|
|||||||
rootWasReset = true;
|
rootWasReset = true;
|
||||||
}
|
}
|
||||||
userId = UserHandle.getUserId(info.applicationInfo.uid);
|
userId = UserHandle.getUserId(info.applicationInfo.uid);
|
||||||
mUserSetupComplete = mService != null &&
|
mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
|
||||||
Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
|
|
||||||
USER_SETUP_COMPLETE, 0, userId) != 0;
|
USER_SETUP_COMPLETE, 0, userId) != 0;
|
||||||
if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
|
if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
|
||||||
// If the activity itself has requested auto-remove, then just always do it.
|
// If the activity itself has requested auto-remove, then just always do it.
|
||||||
@@ -1173,9 +1168,7 @@ final class TaskRecord {
|
|||||||
if (lastTaskDescription != null) {
|
if (lastTaskDescription != null) {
|
||||||
lastTaskDescription.saveToXml(out);
|
lastTaskDescription.saveToXml(out);
|
||||||
}
|
}
|
||||||
if (mLastThumbnailInfo != null) {
|
|
||||||
mLastThumbnailInfo.saveToXml(out);
|
mLastThumbnailInfo.saveToXml(out);
|
||||||
}
|
|
||||||
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
|
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
|
||||||
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
|
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
|
||||||
out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
|
out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
|
||||||
@@ -1197,11 +1190,9 @@ final class TaskRecord {
|
|||||||
out.endTag(null, TAG_AFFINITYINTENT);
|
out.endTag(null, TAG_AFFINITYINTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intent != null) {
|
|
||||||
out.startTag(null, TAG_INTENT);
|
out.startTag(null, TAG_INTENT);
|
||||||
intent.saveToXml(out);
|
intent.saveToXml(out);
|
||||||
out.endTag(null, TAG_INTENT);
|
out.endTag(null, TAG_INTENT);
|
||||||
}
|
|
||||||
|
|
||||||
final ArrayList<ActivityRecord> activities = mActivities;
|
final ArrayList<ActivityRecord> activities = mActivities;
|
||||||
final int numActivities = activities.size();
|
final int numActivities = activities.size();
|
||||||
@@ -1220,8 +1211,7 @@ final class TaskRecord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TaskRecord restoreFromXml(XmlPullParser in, ActivityManagerService service,
|
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
|
||||||
ActivityStackSupervisor stackSupervisor, long lastPersistUptime)
|
|
||||||
throws IOException, XmlPullParserException {
|
throws IOException, XmlPullParserException {
|
||||||
Intent intent = null;
|
Intent intent = null;
|
||||||
Intent affinityIntent = null;
|
Intent affinityIntent = null;
|
||||||
@@ -1335,31 +1325,6 @@ final class TaskRecord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastPersistUptime > 0) {
|
|
||||||
if (TaskPersister.DEBUG) {
|
|
||||||
Slog.d(TaskPersister.TAG, "TaskRecord: Adjust firstActiveTime=" + firstActiveTime +
|
|
||||||
" lastPersistUptime=" + lastPersistUptime);
|
|
||||||
Slog.d(TaskPersister.TAG, "TaskRecord: Migrate lastActiveTime=" + lastActiveTime +
|
|
||||||
" lastActiveTime=" + lastPersistUptime);
|
|
||||||
}
|
|
||||||
// The first and last task active times are relative to the last boot time, so offset
|
|
||||||
// them to be prior to the current boot time
|
|
||||||
firstActiveTime = -lastPersistUptime + firstActiveTime;
|
|
||||||
lastActiveTime = -lastPersistUptime + lastActiveTime;
|
|
||||||
} else {
|
|
||||||
// The first/last active times are still absolute clock times, so offset them to be
|
|
||||||
// relative to the current boot time
|
|
||||||
long currentTime = System.currentTimeMillis();
|
|
||||||
if (TaskPersister.DEBUG) {
|
|
||||||
Slog.d(TaskPersister.TAG, "TaskRecord: Migrate firstActiveTime=" + firstActiveTime +
|
|
||||||
" currentTime=" + currentTime);
|
|
||||||
Slog.d(TaskPersister.TAG, "TaskRecord: Migrate lastActiveTime=" + lastActiveTime +
|
|
||||||
" currentTime=" + currentTime);
|
|
||||||
}
|
|
||||||
firstActiveTime = -Math.max(0, currentTime - firstActiveTime);
|
|
||||||
lastActiveTime = -Math.max(0, currentTime - lastActiveTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
int event;
|
int event;
|
||||||
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
|
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
|
||||||
(event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
|
(event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
|
||||||
@@ -1409,7 +1374,7 @@ final class TaskRecord {
|
|||||||
+ ": effectiveUid=" + effectiveUid);
|
+ ": effectiveUid=" + effectiveUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
final TaskRecord task = new TaskRecord(service, taskId, intent,
|
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
|
||||||
affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
|
affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
|
||||||
autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
|
autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
|
||||||
activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
|
activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
|
||||||
@@ -1812,7 +1777,7 @@ final class TaskRecord {
|
|||||||
pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
|
pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
|
||||||
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
|
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
|
||||||
pw.print(" isResizeable=" + isResizeable());
|
pw.print(" isResizeable=" + isResizeable());
|
||||||
pw.print(" firstActiveTime=" + firstActiveTime);
|
pw.print(" firstActiveTime=" + lastActiveTime);
|
||||||
pw.print(" lastActiveTime=" + lastActiveTime);
|
pw.print(" lastActiveTime=" + lastActiveTime);
|
||||||
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
|
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,36 +16,19 @@
|
|||||||
|
|
||||||
package com.android.server.am;
|
package com.android.server.am;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
import android.util.Xml;
|
|
||||||
|
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
|
||||||
import com.android.internal.util.XmlUtils;
|
|
||||||
import com.android.server.am.TaskPersister;
|
import com.android.server.am.TaskPersister;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
public class TaskPersisterTest extends AndroidTestCase {
|
public class TaskPersisterTest extends AndroidTestCase {
|
||||||
private static final String TEST_USER_NAME = "AM-Test-User";
|
private static final String TEST_USER_NAME = "AM-Test-User";
|
||||||
|
|
||||||
@@ -86,140 +69,6 @@ public class TaskPersisterTest extends AndroidTestCase {
|
|||||||
taskIdsOnFile.equals(newTaskIdsOnFile));
|
taskIdsOnFile.equals(newTaskIdsOnFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testActiveTimeMigration() {
|
|
||||||
// Simulate a migration scenario by setting the last write uptime to zero
|
|
||||||
ContentResolver cr = getContext().getContentResolver();
|
|
||||||
Settings.Secure.putLong(cr,
|
|
||||||
Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, 0);
|
|
||||||
|
|
||||||
// Create a dummy task record with an absolute time 1s before now
|
|
||||||
long pastOffset = 1000;
|
|
||||||
long activeTime = System.currentTimeMillis() - pastOffset;
|
|
||||||
TaskRecord tr0 = createDummyTaskRecordWithActiveTime(activeTime, activeTime);
|
|
||||||
|
|
||||||
// Save and load the tasks with no last persist uptime (0)
|
|
||||||
String tr0XmlStr = serializeTaskRecordToXmlString(tr0);
|
|
||||||
TaskRecord xtr0 = unserializeTaskRecordFromXmlString(tr0XmlStr, 0);
|
|
||||||
|
|
||||||
// Ensure that the absolute time has been migrated to be relative to the current elapsed
|
|
||||||
// time
|
|
||||||
assertTrue("Expected firstActiveTime to be migrated from: " + tr0.firstActiveTime +
|
|
||||||
" instead found: " + xtr0.firstActiveTime,
|
|
||||||
xtr0.firstActiveTime <= -pastOffset);
|
|
||||||
assertTrue("Expected lastActiveTime to be migrated from: " + tr0.lastActiveTime +
|
|
||||||
" instead found: " + xtr0.lastActiveTime,
|
|
||||||
xtr0.lastActiveTime <= -pastOffset);
|
|
||||||
|
|
||||||
// Ensure that the last active uptime is not set so that SystemUI can migrate it itself
|
|
||||||
// assuming that the last persist time is zero
|
|
||||||
Settings.Secure.putLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, 0, testUserId);
|
|
||||||
mTaskPersister.restoreTasksForUserLocked(testUserId);
|
|
||||||
long lastVisTaskActiveTime = Settings.Secure.getLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, -1, testUserId);
|
|
||||||
assertTrue("Expected last visible task active time is zero", lastVisTaskActiveTime == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testActiveTimeOffsets() {
|
|
||||||
// Simulate a normal boot scenario by setting the last write uptime
|
|
||||||
long lastWritePastOffset = 1000;
|
|
||||||
long lastVisActivePastOffset = 500;
|
|
||||||
ContentResolver cr = getContext().getContentResolver();
|
|
||||||
Settings.Secure.putLong(cr,
|
|
||||||
Settings.Secure.TASK_PERSISTER_LAST_WRITE_UPTIME, lastWritePastOffset);
|
|
||||||
|
|
||||||
// Create a dummy task record with an absolute time 1s before now
|
|
||||||
long activeTime = 250;
|
|
||||||
TaskRecord tr0 = createDummyTaskRecordWithActiveTime(activeTime, activeTime);
|
|
||||||
|
|
||||||
// Save and load the tasks with the last persist time
|
|
||||||
String tr0XmlStr = serializeTaskRecordToXmlString(tr0);
|
|
||||||
TaskRecord xtr0 = unserializeTaskRecordFromXmlString(tr0XmlStr, lastWritePastOffset);
|
|
||||||
|
|
||||||
// Ensure that the prior elapsed time has been offset to be relative to the current boot
|
|
||||||
// time
|
|
||||||
assertTrue("Expected firstActiveTime to be offset from: " + tr0.firstActiveTime +
|
|
||||||
" instead found: " + xtr0.firstActiveTime,
|
|
||||||
xtr0.firstActiveTime <= (-lastWritePastOffset + activeTime));
|
|
||||||
assertTrue("Expected lastActiveTime to be offset from: " + tr0.lastActiveTime +
|
|
||||||
" instead found: " + xtr0.lastActiveTime,
|
|
||||||
xtr0.lastActiveTime <= (-lastWritePastOffset + activeTime));
|
|
||||||
|
|
||||||
// Ensure that we update the last active uptime as well by simulating a restoreTasks call
|
|
||||||
Settings.Secure.putLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, lastVisActivePastOffset,
|
|
||||||
testUserId);
|
|
||||||
mTaskPersister.restoreTasksForUserLocked(testUserId);
|
|
||||||
long lastVisTaskActiveTime = Settings.Secure.getLongForUser(cr,
|
|
||||||
Settings.Secure.OVERVIEW_LAST_VISIBLE_TASK_ACTIVE_UPTIME, Long.MAX_VALUE,
|
|
||||||
testUserId);
|
|
||||||
assertTrue("Expected last visible task active time to be offset", lastVisTaskActiveTime <=
|
|
||||||
(-lastWritePastOffset + lastVisActivePastOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaskRecord createDummyTaskRecordWithActiveTime(long firstActiveTime,
|
|
||||||
long lastActiveTime) {
|
|
||||||
ActivityInfo info = createDummyActivityInfo();
|
|
||||||
ActivityManager.TaskDescription td = new ActivityManager.TaskDescription();
|
|
||||||
TaskRecord t = new TaskRecord(null, 0, info, null, td, null);
|
|
||||||
t.firstActiveTime = firstActiveTime;
|
|
||||||
t.lastActiveTime = lastActiveTime;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ActivityInfo createDummyActivityInfo() {
|
|
||||||
ActivityInfo info = new ActivityInfo();
|
|
||||||
info.applicationInfo = getContext().getApplicationInfo();
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String serializeTaskRecordToXmlString(TaskRecord tr) {
|
|
||||||
StringWriter stringWriter = new StringWriter();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final XmlSerializer xmlSerializer = new FastXmlSerializer();
|
|
||||||
xmlSerializer.setOutput(stringWriter);
|
|
||||||
|
|
||||||
xmlSerializer.startDocument(null, true);
|
|
||||||
xmlSerializer.startTag(null, TaskPersister.TAG_TASK);
|
|
||||||
tr.saveToXml(xmlSerializer);
|
|
||||||
xmlSerializer.endTag(null, TaskPersister.TAG_TASK);
|
|
||||||
xmlSerializer.endDocument();
|
|
||||||
xmlSerializer.flush();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringWriter.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaskRecord unserializeTaskRecordFromXmlString(String xmlStr, long lastPersistUptime) {
|
|
||||||
StringReader reader = null;
|
|
||||||
TaskRecord task = null;
|
|
||||||
try {
|
|
||||||
reader = new StringReader(xmlStr);
|
|
||||||
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 (TaskPersister.TAG_TASK.equals(name)) {
|
|
||||||
task = TaskRecord.restoreFromXml(in, null, null, lastPersistUptime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XmlUtils.skipCurrentTag(in);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
IoUtils.closeQuietly(reader);
|
|
||||||
}
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int createUser(String name, int flags) {
|
private int createUser(String name, int flags) {
|
||||||
UserInfo user = mUserManager.createUser(name, flags);
|
UserInfo user = mUserManager.createUser(name, flags);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user