Merge "Launch new tasks with Doc Centric flag."
diff --git a/api/current.txt b/api/current.txt
index 9a30c44..4534dd4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7646,6 +7646,7 @@
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
@@ -7669,7 +7670,7 @@
field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
- field public static final java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
+ field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
field public static final java.lang.String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2facef6..e86833b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1233,6 +1233,26 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports leanback UI. This is
+ * typically used in a living room television experience, but is a software
+ * feature unlike {@link #FEATURE_TELEVISION}. Devices running with this
+ * feature will use resources associated with the "television" UI mode.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_LEANBACK = "android.software.leanback";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports only leanback UI. Only
+ * applications designed for this experience should be run, though this is
+ * not enforced by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports WiFi (802.11) networking.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -1252,6 +1272,7 @@
* room television experience: displayed on a big screen, where the user
* is sitting far away from it, and the dominant form of input will be
* something like a DPAD, not through touch or mouse.
+ * @deprecated use {@link #FEATURE_LEANBACK} instead.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEVISION = "android.hardware.type.television";
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 875e8de..4a743a5 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -140,12 +140,33 @@
mContext.registerReceiver(mExternalReceiver, sdFilter);
}
+ private final void handlePackageEvent(Intent intent, int userId) {
+ // Don't regenerate the services map when the package is removed or its
+ // ASEC container unmounted as a step in replacement. The subsequent
+ // _ADDED / _AVAILABLE call will regenerate the map in the final state.
+ final String action = intent.getAction();
+ // it's a new-component action if it isn't some sort of removal
+ final boolean isRemoval = Intent.ACTION_PACKAGE_REMOVED.equals(action)
+ || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action);
+ // if it's a removal, is it part of an update-in-place step?
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+ if (isRemoval && replacing) {
+ // package is going away, but it's the middle of an upgrade: keep the current
+ // state and do nothing here. This clause is intentionally empty.
+ } else {
+ // either we're adding/changing, or it's a removal without replacement, so
+ // we need to recalculate the set of available services
+ generateServicesMap(userId);
+ }
+ }
+
private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
if (uid != -1) {
- generateServicesMap(UserHandle.getUserId(uid));
+ handlePackageEvent(intent, UserHandle.getUserId(uid));
}
}
};
@@ -154,7 +175,7 @@
@Override
public void onReceive(Context context, Intent intent) {
// External apps can't coexist with multi-user, so scan owner
- generateServicesMap(UserHandle.USER_OWNER);
+ handlePackageEvent(intent, UserHandle.USER_OWNER);
}
};
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 94c3f44..d8cf18e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -435,6 +435,14 @@
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
+ * CAUTION: when adding options in here, be careful not to put the
+ * char buffer inside a nested scope. Adding the buffer to the
+ * options using mOptions.add() does not copy the buffer, so if the
+ * buffer goes out of scope the option may be overwritten. It's best
+ * to put the buffer at the top of the function so that it is more
+ * unlikely that someone will surround it in a scope at a later time
+ * and thus introduce a bug.
+ *
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
@@ -469,7 +477,15 @@
kEMIntFast,
kEMJitCompiler,
} executionMode = kEMDefault;
-
+ char profile_period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+ char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+ char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+ char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+ char langOption[sizeof("-Duser.language=") + 3];
+ char regionOption[sizeof("-Duser.region=") + 3];
+ char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
+ char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
+ char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
@@ -670,7 +686,6 @@
//mOptions.add(opt);
}
- char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
property_get("dalvik.vm.lockprof.threshold", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
@@ -680,7 +695,6 @@
}
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
- char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.op", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitOpBuf, "-Xjitop:");
@@ -690,7 +704,6 @@
}
/* Force interpreter-only mode for selected methods */
- char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.method", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitMethodBuf, "-Xjitmethod:");
@@ -770,8 +783,6 @@
/* Set the properties for locale */
{
- char langOption[sizeof("-Duser.language=") + 3];
- char regionOption[sizeof("-Duser.region=") + 3];
strcpy(langOption, "-Duser.language=");
strcpy(regionOption, "-Duser.region=");
readLocale(langOption, regionOption);
@@ -786,35 +797,30 @@
* Set profiler options
*/
if (libart) {
- char period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
- char duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
- char interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
- char backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
-
// Number of seconds during profile runs.
- strcpy(period, "-Xprofile-period:");
- property_get("dalvik.vm.profile.period_secs", period+17, "10");
- opt.optionString = period;
+ strcpy(profile_period, "-Xprofile-period:");
+ property_get("dalvik.vm.profile.period_secs", profile_period+17, "10");
+ opt.optionString = profile_period;
mOptions.add(opt);
// Length of each profile run (seconds).
- strcpy(duration, "-Xprofile-duration:");
- property_get("dalvik.vm.profile.duration_secs", duration+19, "30");
- opt.optionString = duration;
+ strcpy(profile_duration, "-Xprofile-duration:");
+ property_get("dalvik.vm.profile.duration_secs", profile_duration+19, "30");
+ opt.optionString = profile_duration;
mOptions.add(opt);
// Polling interval during profile run (microseconds).
- strcpy(interval, "-Xprofile-interval:");
- property_get("dalvik.vm.profile.interval_us", interval+19, "10000");
- opt.optionString = interval;
+ strcpy(profile_interval, "-Xprofile-interval:");
+ property_get("dalvik.vm.profile.interval_us", profile_interval+19, "10000");
+ opt.optionString = profile_interval;
mOptions.add(opt);
// Coefficient for period backoff. The the period is multiplied
// by this value after each profile run.
- strcpy(backoff, "-Xprofile-backoff:");
- property_get("dalvik.vm.profile.backoff_coeff", backoff+18, "2.0");
- opt.optionString = backoff;
+ strcpy(profile_backoff, "-Xprofile-backoff:");
+ property_get("dalvik.vm.profile.backoff_coeff", profile_backoff+18, "2.0");
+ opt.optionString = profile_backoff;
mOptions.add(opt);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index b3d9ccf..db95193 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
@@ -36,20 +37,20 @@
/** Logs a key */
public static void log(String key) {
- Console.log(true, key, "", AnsiReset);
+ log(true, key, "", AnsiReset);
}
/** Logs a conditioned key */
public static void log(boolean condition, String key) {
if (condition) {
- Console.log(condition, key, "", AnsiReset);
+ log(condition, key, "", AnsiReset);
}
}
/** Logs a key in a specific color */
public static void log(boolean condition, String key, Object data) {
if (condition) {
- Console.log(condition, key, data, AnsiReset);
+ log(condition, key, data, AnsiReset);
}
}
@@ -74,6 +75,50 @@
}
}
+ /** Logs a stack trace */
+ public static void logStackTrace() {
+ logStackTrace("", 99);
+ }
+
+ /** Logs a stack trace to a certain depth */
+ public static void logStackTrace(int depth) {
+ logStackTrace("", depth);
+ }
+
+ /** Logs a stack trace to a certain depth with a key */
+ public static void logStackTrace(String key, int depth) {
+ int offset = 0;
+ StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+ String tinyStackTrace = "";
+ // Skip over the known stack trace classes
+ for (int i = 0; i < callStack.length; i++) {
+ StackTraceElement el = callStack[i];
+ String className = el.getClassName();
+ if (className.indexOf("dalvik.system.VMStack") == -1 &&
+ className.indexOf("java.lang.Thread") == -1 &&
+ className.indexOf("recents.Console") == -1) {
+ break;
+ } else {
+ offset++;
+ }
+ }
+ // Build the pretty stack trace
+ int start = Math.min(offset + depth, callStack.length);
+ int end = offset;
+ String indent = "";
+ for (int i = start - 1; i >= end; i--) {
+ StackTraceElement el = callStack[i];
+ tinyStackTrace += indent + " -> " + el.getClassName() +
+ "[" + el.getLineNumber() + "]." + el.getMethodName();
+ if (i > end) {
+ tinyStackTrace += "\n";
+ indent += " ";
+ }
+ }
+ log(true, key, tinyStackTrace, AnsiRed);
+ }
+
+
/** Returns the stringified MotionEvent action */
public static String motionEventActionToString(int action) {
switch (action) {
@@ -93,4 +138,25 @@
return "" + action;
}
}
+
+ public static String trimMemoryLevelToString(int level) {
+ switch (level) {
+ case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+ return "UI Hidden";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+ return "Running Moderate";
+ case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+ return "Background";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+ return "Running Low";
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ return "Moderate";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+ return "Critical";
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ return "Complete";
+ default:
+ return "" + level;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index aeae4ab..57ebbc2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -30,9 +30,11 @@
public static final boolean EnableTaskStackClipping = false;
public static final boolean EnableBackgroundTaskLoading = true;
public static final boolean ForceDisableBackgroundCache = false;
+
public static final boolean TaskDataLoader = false;
public static final boolean SystemUIHandshake = false;
public static final boolean TimeSystemCalls = false;
+ public static final boolean Memory = false;
}
public static class UI {
@@ -41,7 +43,7 @@
public static final boolean TouchEvents = false;
public static final boolean MeasureAndLayout = false;
public static final boolean Clipping = false;
- public static final boolean HwLayers = true;
+ public static final boolean HwLayers = false;
}
public static class TaskStack {
@@ -55,13 +57,16 @@
public static class Values {
public static class Window {
+ // The dark background dim is set behind the empty recents view
public static final float DarkBackgroundDim = 0.5f;
+ // The background dim is set behind the card stack
public static final float BackgroundDim = 0.35f;
}
public static class RecentsTaskLoader {
// XXX: This should be calculated on the first load
public static final int PreloadFirstTasksCount = 5;
+ // For debugging, this allows us to multiply the number of cards for each task
public static final int TaskEntryMultiplier = 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d050847..fc4d819 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -23,6 +23,7 @@
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.RecentsView;
@@ -168,6 +169,14 @@
}
@Override
+ public void onTrimMemory(int level) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ if (loader != null) {
+ loader.onTrimMemory(level);
+ }
+ }
+
+ @Override
public void onBackPressed() {
if (!mRecentsView.unfilterFilteredStacks()) {
super.onBackPressed();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index f3881ae..ed981ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -30,7 +30,6 @@
DisplayMetrics mDisplayMetrics;
- public boolean layoutVerticalStack;
public Rect systemInsets = new Rect();
/** Private constructor */
@@ -56,7 +55,6 @@
boolean isPortrait = context.getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT;
- layoutVerticalStack = isPortrait || Constants.LANDSCAPE_LAYOUT_VERTICAL_STACK;
}
public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 522ab0f..13a3424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -57,8 +57,9 @@
tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top);
tsv.boundScroll();
TaskViewTransform transform = tsv.getStackTransform(0);
+ Rect taskRect = new Rect(transform.rect);
- data.putParcelable("taskRect", transform.rect);
+ data.putParcelable("taskRect", taskRect);
Message reply = Message.obtain(null, MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
reply.setData(data);
msg.replyTo.send(reply);
@@ -100,4 +101,12 @@
Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsService|onDestroy]");
super.onDestroy();
}
+
+ @Override
+ public void onTrimMemory(int level) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ if (loader != null) {
+ loader.onTrimMemory(level);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index c303ca7..96efed4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -233,7 +235,7 @@
@Override
protected int sizeOf(Task t, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than number of items
- return bitmap.getByteCount() / 1024;
+ return bitmap.getAllocationByteCount() / 1024;
}
}
@@ -247,17 +249,28 @@
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
+ int mMaxThumbnailCacheSize;
+ int mMaxIconCacheSize;
+
BitmapDrawable mDefaultIcon;
Bitmap mDefaultThumbnail;
/** Private Constructor */
private RecentsTaskLoader(Context context) {
+ // Calculate the cache sizes
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
- int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 16;
- int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 8;
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ mMaxThumbnailCacheSize = maxMemory / 8;
+ mMaxIconCacheSize = mMaxThumbnailCacheSize / 4;
+ int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+ mMaxIconCacheSize;
+ int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+ mMaxThumbnailCacheSize;
+
+ Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
"[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
" iconCache: " + iconCacheSize);
+
+ // Initialize the cache and loaders
mLoadQueue = new TaskResourceLoadQueue();
mIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -293,7 +306,7 @@
/** Reload the set of recent tasks */
SpaceNode reload(Context context, int preloadCount) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|reload]");
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
TaskStack stack = new TaskStack(context);
SpaceNode root = new SpaceNode(context);
root.setStack(stack);
@@ -310,7 +323,7 @@
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
"[RecentsTaskLoader|getRecentTasks]",
"" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
"[RecentsTaskLoader|tasks]", "" + tasks.size());
// Remove home/recents tasks
@@ -335,35 +348,51 @@
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
-
- // Load the label, icon and thumbnail
ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
PackageManager.GET_META_DATA);
String title = info.loadLabel(pm).toString();
- Drawable icon = null;
- Bitmap thumbnail = null;
Task task;
- if (i >= (taskCount - preloadCount) || !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ // Preload the specified number of apps
+ if (i >= (taskCount - preloadCount) ||
+ !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
"[RecentsTaskLoader|preloadTask]",
"i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
- icon = info.loadIcon(pm);
- thumbnail = am.getTaskTopThumbnail(t.id);
- for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
- task = new Task(t.persistentId, t.baseIntent, title, icon, thumbnail);
+
+ task = new Task(t.persistentId, t.baseIntent, title, null, null);
+
+ // Load the icon (if possible from the cache)
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ task.icon = mIconCache.get(task);
+ }
+ if (task.icon == null) {
+ task.icon = info.loadIcon(pm);
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- if (thumbnail != null) mThumbnailCache.put(task, thumbnail);
- if (icon != null) {
- mIconCache.put(task, icon);
- }
+ mIconCache.put(task, task.icon);
}
+ }
+
+ // Load the thumbnail (if possible from the cache)
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ task.thumbnail = mThumbnailCache.get(task);
+ }
+ if (task.thumbnail == null) {
+ task.thumbnail = am.getTaskTopThumbnail(t.id);
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ mThumbnailCache.put(task, task.thumbnail);
+ }
+ }
+
+ // Create as many tasks a we want to multiply by
+ for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
stack.addTask(task);
}
} else {
+ // Create as many tasks a we want to multiply by
for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
task = new Task(t.persistentId, t.baseIntent, title, null, null);
stack.addTask(task);
@@ -388,9 +417,9 @@
t1 = System.currentTimeMillis();
List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
for (ActivityManager.StackInfo s : stackInfos) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, " [RecentsTaskLoader|stack]", s.toString());
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
if (stacks.containsKey(s.stackId)) {
stacks.get(s.stackId).setRect(s.bounds);
}
@@ -403,45 +432,46 @@
return root;
}
- /** Acquires the task resource data from the pool.
- * XXX: Move this into Task? */
+ /** Acquires the task resource data from the pool. */
public void loadTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- t.icon = mIconCache.get(t);
- t.thumbnail = mThumbnailCache.get(t);
+ Drawable icon = mIconCache.get(t);
+ Bitmap thumbnail = mThumbnailCache.get(t);
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
- t + " icon: " + t.icon + " thumbnail: " + t.thumbnail);
+ t + " icon: " + icon + " thumbnail: " + thumbnail +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
boolean requiresLoad = false;
- if (t.icon == null) {
- t.icon = mDefaultIcon;
+ if (icon == null) {
+ icon = mDefaultIcon;
requiresLoad = true;
}
- if (t.thumbnail == null) {
- t.thumbnail = mDefaultThumbnail;
+ if (thumbnail == null) {
+ thumbnail = mDefaultThumbnail;
requiresLoad = true;
}
if (requiresLoad) {
mLoadQueue.addTask(t);
}
+ t.notifyTaskLoaded(thumbnail, icon);
}
}
- /** Releases the task resource data back into the pool.
- * XXX: Move this into Task? */
+ /** Releases the task resource data back into the pool. */
public void unloadTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
Console.log(Constants.DebugFlags.App.TaskDataLoader,
- "[RecentsTaskLoader|unloadTask]", t);
+ "[RecentsTaskLoader|unloadTask]", t +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
mLoadQueue.removeTask(t);
- t.icon = mDefaultIcon;
- t.thumbnail = mDefaultThumbnail;
+ t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+ } else {
+ t.notifyTaskUnloaded(null, null);
}
}
- /** Completely removes the resource data from the pool.
- * XXX: Move this into Task? */
+ /** Completely removes the resource data from the pool. */
public void deleteTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -449,9 +479,10 @@
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t);
mIconCache.remove(t);
+ t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+ } else {
+ t.notifyTaskUnloaded(null, null);
}
- t.icon = mDefaultIcon;
- t.thumbnail = mDefaultThumbnail;
}
/** Stops the task loader */
@@ -460,4 +491,51 @@
mLoader.stop();
mLoadQueue.clearTasks();
}
+
+ void onTrimMemory(int level) {
+ Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
+ Console.trimMemoryLevelToString(level));
+
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ // If we are hidden, then we should unload each of the task keys
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|unloadTasks]"
+ );
+ // Unload each of the keys in the thumbnail cache
+ Map<Task, Bitmap> thumbnailCache = mThumbnailCache.snapshot();
+ for (Task t : thumbnailCache.keySet()) {
+ unloadTaskData(t);
+ }
+ // As well as the keys in the icon cache
+ Map<Task, Drawable> iconCache = mIconCache.snapshot();
+ for (Task t : iconCache.keySet()) {
+ unloadTaskData(t);
+ }
+ }
+
+ switch (level) {
+ case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+ case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+ // We are leaving recents, so trim the data a bit
+ mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
+ mIconCache.trimToSize(mMaxIconCacheSize / 2);
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ // We are going to be low on memory
+ mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
+ mIconCache.trimToSize(mMaxIconCacheSize / 4);
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ // We are low on memory, so release everything
+ mThumbnailCache.evictAll();
+ mIconCache.evictAll();
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 9b03c5d..378984c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -54,6 +54,24 @@
}
}
+ /** Notifies the callback listeners that this task has been loaded */
+ public void notifyTaskLoaded(Bitmap thumbnail, Drawable icon) {
+ this.icon = icon;
+ this.thumbnail = thumbnail;
+ if (mCb != null) {
+ mCb.onTaskBound();
+ }
+ }
+
+ /** Notifies the callback listeners that this task has been unloaded */
+ public void notifyTaskUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) {
+ icon = defaultIcon;
+ thumbnail = defaultThumbnail;
+ if (mCb != null) {
+ mCb.onTaskUnbound();
+ }
+ }
+
@Override
public boolean equals(Object o) {
// If we have multiple task entries for the same task, then we do the simple object
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
index 169f56c..712580d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
@@ -20,4 +20,8 @@
public interface TaskCallbacks {
/* Notifies when a task's data has been updated */
public void onTaskDataChanged(Task task);
+ /* Notifies when a task has been bound */
+ public void onTaskBound();
+ /* Notifies when a task has been unbound */
+ public void onTaskUnbound();
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index fe661bc..21ef9ff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -28,6 +28,8 @@
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.LinearInterpolator;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
/**
* This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -176,6 +178,9 @@
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[SwipeHelper|interceptTouchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
final int action = ev.getAction();
switch (action) {
@@ -200,7 +205,7 @@
if (Math.abs(delta) > mPagingTouchSlop) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
- mInitialTouchPos = getPos(ev) - getTranslation(mCurrView);
+ mInitialTouchPos = pos - getTranslation(mCurrView);
}
}
break;
@@ -286,6 +291,10 @@
}
public boolean onTouchEvent(MotionEvent ev) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[SwipeHelper|touchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+
if (!mDragging) {
if (!onInterceptTouchEvent(ev)) {
return mCanCurrViewBeDimissed;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 9dd6c0b..7753d69 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -435,19 +435,12 @@
mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
// Compute the task rect
- if (RecentsConfiguration.getInstance().layoutVerticalStack) {
- int minHeight = (int) (mStackRect.height() -
- (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
- int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
- int centerX = mStackRect.centerX();
- mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
- centerX + size / 2, mStackRectSansPeek.top + size);
- } else {
- int size = Math.min(mStackRect.width(), mStackRect.height());
- int centerY = mStackRect.centerY();
- mTaskRect.set(mStackRectSansPeek.top, centerY - size / 2,
- mStackRectSansPeek.top + size, centerY + size / 2);
- }
+ int minHeight = (int) (mStackRect.height() -
+ (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
+ int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
+ int centerX = mStackRect.centerX();
+ mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
+ centerX + size / 2, mStackRectSansPeek.top + size);
// Update the scroll bounds
updateMinMaxScroll(false);
@@ -589,7 +582,6 @@
// Report that this tasks's data is no longer being used
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.unloadTaskData(task);
- tv.unbindFromTask();
// Detach the view from the hierarchy
detachViewFromParent(tv);
@@ -610,7 +602,6 @@
// Request that this tasks's data be filled
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.loadTaskData(task);
- tv.syncToTask();
// Find the index where this task should be placed in the children
int insertIndex = -1;
@@ -678,14 +669,13 @@
}
/* Handles touch events */
-class TaskStackViewTouchHandler {
+class TaskStackViewTouchHandler implements SwipeHelper.Callback {
static int INACTIVE_POINTER_ID = -1;
TaskStackView mSv;
VelocityTracker mVelocityTracker;
boolean mIsScrolling;
- boolean mIsSwiping;
int mInitialMotionX, mInitialMotionY;
int mLastMotionX, mLastMotionY;
@@ -697,21 +687,24 @@
int mMaximumVelocity;
// The scroll touch slop is used to calculate when we start scrolling
int mScrollTouchSlop;
- // The swipe touch slop is used to calculate when we start swiping left/right, this takes
- // precendence over the scroll touch slop in case the user makes a gesture that starts scrolling
- // but is intended to be a swipe
- int mSwipeTouchSlop;
- // After a certain amount of scrolling, we should start ignoring checks for swiping
- int mMaxScrollMotionToRejectSwipe;
+ // The page touch slop is used to calculate when we start swiping
+ float mPagingTouchSlop;
+
+ SwipeHelper mSwipeHelper;
+ boolean mInterceptedBySwipeHelper;
public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mScrollTouchSlop = configuration.getScaledTouchSlop();
- mSwipeTouchSlop = 2 * mScrollTouchSlop;
- mMaxScrollMotionToRejectSwipe = 4 * mScrollTouchSlop;
+ mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
mSv = sv;
+
+
+ float densityScale = context.getResources().getDisplayMetrics().density;
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
+ mSwipeHelper.setMinAlpha(1f);
}
/** Velocity tracker helpers */
@@ -754,11 +747,18 @@
"[TaskStackViewTouchHandler|interceptTouchEvent]",
Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ // Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
return false;
}
+ // Pass through to swipe helper if we are swiping
+ mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
+ if (mInterceptedBySwipeHelper) {
+ return true;
+ }
+
boolean wasScrolling = !mSv.mScroller.isFinished() ||
(mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
int action = ev.getAction();
@@ -777,7 +777,8 @@
mVelocityTracker.addMovement(ev);
// Check if the scroller is finished yet
mIsScrolling = !mSv.mScroller.isFinished();
- mIsSwiping = false;
+ // Enable HW layers
+ mSv.addHwLayersRefCount();
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -786,25 +787,7 @@
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
int x = (int) ev.getX(activePointerIndex);
- if (mActiveTaskView != null &&
- mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
- Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
- Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
- // Start swiping and stop scrolling
- mIsScrolling = false;
- mIsSwiping = true;
- System.out.println("SWIPING: " + mActiveTaskView);
- // Initialize the velocity tracker if necessary
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount();
- } else if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+ if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
// Save the touch move info
mIsScrolling = true;
// Initialize the velocity tracker if necessary
@@ -815,8 +798,6 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // Enable HW layers
- mSv.addHwLayersRefCount();
}
mLastMotionX = x;
@@ -829,16 +810,17 @@
mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
// Reset the drag state and the velocity tracker
mIsScrolling = false;
- mIsSwiping = false;
mActivePointerId = INACTIVE_POINTER_ID;
mActiveTaskView = null;
mTotalScrollMotion = 0;
recycleVelocityTracker();
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
break;
}
}
- return wasScrolling || mIsScrolling || mIsSwiping;
+ return wasScrolling || mIsScrolling;
}
/** Handles touch events once we have intercepted them */
@@ -853,6 +835,11 @@
return false;
}
+ // Pass through to swipe helper if we are swiping
+ if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
+ return true;
+ }
+
// Update the velocity tracker
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
@@ -871,7 +858,6 @@
// Initialize the velocity tracker
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
- // XXX: Set mIsScrolling or mIsSwiping?
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
@@ -886,28 +872,7 @@
int x = (int) ev.getX(activePointerIndex);
int y = (int) ev.getY(activePointerIndex);
int deltaY = mLastMotionY - y;
- int deltaX = x - mLastMotionX;
- if (!mIsSwiping) {
- if (mActiveTaskView != null &&
- mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
- Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
- Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
- mIsScrolling = false;
- mIsSwiping = true;
- System.out.println("SWIPING: " + mActiveTaskView);
- // Initialize the velocity tracker if necessary
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount();
- }
- }
- if (!mIsSwiping && !mIsScrolling) {
+ if (!mIsScrolling) {
if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
mIsScrolling = true;
// Initialize the velocity tracker
@@ -927,8 +892,6 @@
if (mSv.isScrollOutOfBounds()) {
mVelocityTracker.clear();
}
- } else if (mIsSwiping) {
- mActiveTaskView.setTranslationX(mActiveTaskView.getTranslationX() + deltaX);
}
mLastMotionX = x;
mLastMotionY = y;
@@ -936,107 +899,33 @@
break;
}
case MotionEvent.ACTION_UP: {
- if (mIsScrolling || mIsSwiping) {
- final TaskView activeTv = mActiveTaskView;
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if (mIsSwiping) {
- int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
- if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
- // Fling to dismiss
- int newScrollX = (int) (Math.signum(initialVelocity) *
- activeTv.getMeasuredWidth());
- int duration = Math.min(Constants.Values.TaskStackView.Animation.SwipeDismissDuration,
- (int) (Math.abs(newScrollX - activeTv.getScrollX()) *
- 1000f / Math.abs(initialVelocity)));
- activeTv.animate()
- .translationX(newScrollX)
- .alpha(0f)
- .setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- Task task = activeTv.getTask();
- Activity activity = (Activity) mSv.getContext();
-
- // We have to disable the listener to ensure that we
- // don't hit this again
- activeTv.animate().setListener(null);
-
- // Remove the task from the view
- mSv.mStack.removeTask(task);
-
- // Remove any stored data from the loader
- RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
- loader.deleteTaskData(task);
-
- // Remove the task from activity manager
- final ActivityManager am = (ActivityManager)
- activity.getSystemService(Context.ACTIVITY_SERVICE);
- if (am != null) {
- am.removeTask(activeTv.getTask().id,
- ActivityManager.REMOVE_TASK_KILL_PROCESS);
- }
-
- // If there are no remaining tasks, then just close the activity
- if (mSv.mStack.getTaskCount() == 0) {
- activity.finish();
- }
-
- // Disable HW layers
- mSv.decHwLayersRefCount();
- }
- })
- .start();
- // Enable HW layers
- mSv.addHwLayersRefCount();
- } else {
- // Animate it back into place
- // XXX: Make this animation a function of the velocity OR distance
- int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
- activeTv.animate()
- .translationX(0)
- .setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Disable HW layers
- mSv.decHwLayersRefCount();
- }
- })
- .start();
- // Enable HW layers
- mSv.addHwLayersRefCount();
- }
- } else {
- int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if ((Math.abs(velocity) > mMinimumVelocity)) {
- Console.log(Constants.DebugFlags.UI.TouchEvents,
- "[TaskStackViewTouchHandler|fling]",
- "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
- Console.AnsiGreen);
- // Enable HW layers on the stack
- mSv.addHwLayersRefCount();
- // Fling scroll
- mSv.mScroller.fling(0, mSv.getStackScroll(),
- 0, -velocity,
- 0, 0,
- mSv.mMinScroll, mSv.mMaxScroll,
- 0, 0);
- // Invalidate to kick off computeScroll
- mSv.invalidate();
- } else if (mSv.isScrollOutOfBounds()) {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
- }
- }
+ if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|fling]",
+ "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
+ Console.AnsiGreen);
+ // Enable HW layers on the stack
+ mSv.addHwLayersRefCount();
+ // Fling scroll
+ mSv.mScroller.fling(0, mSv.getStackScroll(),
+ 0, -velocity,
+ 0, 0,
+ mSv.mMinScroll, mSv.mMaxScroll,
+ 0, 0);
+ // Invalidate to kick off computeScroll
+ mSv.invalidate();
+ } else if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
- mIsSwiping = false;
mTotalScrollMotion = 0;
recycleVelocityTracker();
// Disable HW layers
@@ -1044,25 +933,14 @@
break;
}
case MotionEvent.ACTION_CANCEL: {
- if (mIsScrolling || mIsSwiping) {
- if (mIsSwiping) {
- // Animate it back into place
- // XXX: Make this animation a function of the velocity OR distance
- int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
- mActiveTaskView.animate()
- .translationX(0)
- .setDuration(duration)
- .start();
- } else {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
- }
+ if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
- mIsSwiping = false;
mTotalScrollMotion = 0;
recycleVelocityTracker();
// Disable HW layers
@@ -1072,4 +950,72 @@
}
return true;
}
+
+ /**** SwipeHelper Implementation ****/
+
+ @Override
+ public View getChildAtPosition(MotionEvent ev) {
+ return findViewAtPoint((int) ev.getX(), (int) ev.getY());
+ }
+
+ @Override
+ public boolean canChildBeDismissed(View v) {
+ return true;
+ }
+
+ @Override
+ public void onBeginDrag(View v) {
+ // Enable HW layers
+ mSv.addHwLayersRefCount();
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ @Override
+ public void onChildDismissed(View v) {
+ TaskView tv = (TaskView) v;
+ Task task = tv.getTask();
+ Activity activity = (Activity) mSv.getContext();
+
+ // We have to disable the listener to ensure that we
+ // don't hit this again
+ tv.animate().setListener(null);
+
+ // Remove the task from the view
+ mSv.mStack.removeTask(task);
+
+ // Remove any stored data from the loader
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ loader.deleteTaskData(task);
+
+ // Remove the task from activity manager
+ final ActivityManager am = (ActivityManager)
+ activity.getSystemService(Context.ACTIVITY_SERVICE);
+ if (am != null) {
+ am.removeTask(tv.getTask().id,
+ ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ }
+
+ // If there are no remaining tasks, then just close the activity
+ if (mSv.mStack.getTaskCount() == 0) {
+ activity.finish();
+ }
+
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
+ }
+
+ @Override
+ public void onSnapBackCompleted(View v) {
+ // Do Nothing
+ }
+
+ @Override
+ public void onDragCancelled(View v) {
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b1d0d13..9ef74ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -255,13 +255,13 @@
}
/** Actually synchronizes the model data into the views */
- void syncToTask() {
+ private void syncToTask() {
mThumbnailView.rebindToTask(mTask, false);
mIconView.rebindToTask(mTask, false);
}
/** Unset the task and callback */
- void unbindFromTask() {
+ private void unbindFromTask() {
mTask.setCallbacks(null);
mThumbnailView.unbindFromTask();
mIconView.unbindFromTask();
@@ -357,16 +357,16 @@
/** Enable the hw layers on this task view */
void enableHwLayers() {
- Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|enableHwLayers]");
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
/** Disable the hw layers on this task view */
void disableHwLayers() {
- Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|disableHwLayers]");
mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
}
+ /**** TaskCallbacks Implementation ****/
+
@Override
public void onTaskDataChanged(Task task) {
Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
@@ -380,6 +380,16 @@
}
@Override
+ public void onTaskBound() {
+ syncToTask();
+ }
+
+ @Override
+ public void onTaskUnbound() {
+ unbindFromTask();
+ }
+
+ @Override
public void onClick(View v) {
mCb.onTaskIconClicked(this);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 6666385..b235408 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -142,6 +142,13 @@
}
@LayoutlibDelegate
+ /*package*/ static boolean native_isConvex(long nPath) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Path.isConvex is not supported.", null, null);
+ return true;
+ }
+
+ @LayoutlibDelegate
/*package*/ static int native_getFillType(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index 998b08b..b16b4aa 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -18,6 +18,7 @@
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.ibm.icu.text.DateTimePatternGenerator;
+import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ULocale;
import java.util.Locale;
@@ -117,6 +118,11 @@
}
@LayoutlibDelegate
+ /*package*/ static int getCurrencyNumericCode(String currencyCode) {
+ return Currency.getInstance(currencyCode).getNumericCode();
+ }
+
+ @LayoutlibDelegate
/*package*/ static String getCurrencySymbol(String locale, String currencyCode) {
return "";
}