summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt8
-rw-r--r--core/java/android/app/ActivityManager.java6
-rw-r--r--core/java/android/app/ActivityOptions.java73
-rw-r--r--core/java/android/app/LoadedApk.java94
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java4
-rw-r--r--core/java/android/content/pm/PackageManager.java8
-rw-r--r--core/java/android/content/res/Configuration.java19
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/java/android/view/ViewGroup.java16
-rw-r--r--core/java/android/view/accessibility/AccessibilityCache.java12
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java21
-rw-r--r--core/java/android/webkit/CookieManager.java2
-rw-r--r--core/java/com/android/internal/os/InstallerConnection.java18
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Shader.cpp1
-rw-r--r--core/res/res/values-sw600dp/dimens.xml4
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java10
-rw-r--r--include/androidfw/ResourceTypes.h1
-rw-r--r--libs/androidfw/ResourceTypes.cpp37
-rw-r--r--libs/androidfw/tests/Android.mk3
-rw-r--r--libs/androidfw/tests/ConfigLocale_test.cpp (renamed from libs/androidfw/tests/ResourceTypes_test.cpp)18
-rw-r--r--libs/androidfw/tests/Config_test.cpp103
-rw-r--r--libs/androidfw/tests/TestHelpers.h13
-rw-r--r--libs/hwui/DisplayListRenderer.h21
-rw-r--r--libs/hwui/SpotShadow.cpp8
-rw-r--r--libs/hwui/utils/MathUtils.h5
-rw-r--r--media/java/android/media/tv/TvView.java1
-rw-r--r--packages/SettingsProvider/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/res/anim/recents_from_launcher_enter.xml4
-rw-r--r--packages/SystemUI/res/anim/recents_from_launcher_exit.xml2
-rw-r--r--packages/SystemUI/res/anim/recents_to_launcher_enter.xml4
-rw-r--r--packages/SystemUI/res/anim/recents_to_launcher_exit.xml2
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.pngbin755 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.pngbin642 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.pngbin1012 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.pngbin1183 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable/ic_ime_switcher_default.xml25
-rw-r--r--packages/SystemUI/res/layout/recents_task_view.xml40
-rw-r--r--packages/SystemUI/res/layout/recents_task_view_header.xml55
-rw-r--r--packages/SystemUI/res/values/colors.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java114
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java10
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java134
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java40
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java16
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java1
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java59
-rw-r--r--services/core/java/com/android/server/content/SyncOperation.java8
-rw-r--r--services/core/java/com/android/server/pm/Installer.java26
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java230
-rw-r--r--services/core/java/com/android/server/wm/AppWindowAnimator.java36
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java100
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java9
-rw-r--r--tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java2
-rw-r--r--tools/aapt/AaptConfig.cpp7
-rw-r--r--tools/aapt/Bundle.h1
-rw-r--r--tools/aapt/Command.cpp12
-rw-r--r--tools/aapt/IndentPrinter.h63
-rw-r--r--tools/aapt/Main.h3
-rw-r--r--tools/aapt/Resource.cpp134
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java6
81 files changed, 1509 insertions, 562 deletions
diff --git a/api/current.txt b/api/current.txt
index 85a3fc526480..009da96599b5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5511,8 +5511,8 @@ package android.app.admin {
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
- field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+ field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
@@ -8902,6 +8902,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
field public static final java.lang.String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate";
+ field public static final java.lang.String FEATURE_SENSOR_HEART_RATE_ECG = "android.hardware.sensor.heartrate.ecg";
field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
field public static final java.lang.String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity";
@@ -35789,6 +35790,7 @@ package android.view.accessibility {
method public android.view.accessibility.AccessibilityWindowInfo getParent();
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method public int getType();
+ method public boolean isAccessibilityFocused();
method public boolean isActive();
method public boolean isFocused();
method public static android.view.accessibility.AccessibilityWindowInfo obtain();
@@ -36615,7 +36617,7 @@ package android.webkit {
public class CookieManager {
method public synchronized boolean acceptCookie();
- method public synchronized boolean acceptThirdPartyCookies(android.webkit.WebView);
+ method public boolean acceptThirdPartyCookies(android.webkit.WebView);
method public static boolean allowFileSchemeCookies();
method public void flush();
method public java.lang.String getCookie(java.lang.String);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2667bcd30a69..2173647d3ccb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -796,6 +796,12 @@ public class ActivityManager {
public static final int RECENT_INCLUDE_PROFILES = 0x0004;
/**
+ * Ignores all tasks that are on the home stack.
+ * @hide
+ */
+ public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+
+ /**
* <p></p>Return a list of the tasks that the user has recently launched, with
* the most recent being first and older ones after in order.
*
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0653ca9d8dff..9dd46056c3e3 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -128,6 +128,10 @@ public class ActivityOptions {
public static final int ANIM_DEFAULT = 6;
/** @hide */
public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
+ /** @hide */
+ public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
+ /** @hide */
+ public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -338,6 +342,67 @@ public class ActivityOptions {
}
/**
+ * Create an ActivityOptions specifying an animation where the new activity
+ * window and a thumbnail is aspect-scaled to a new location.
+ *
+ * @param source The View that this thumbnail is animating from. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param thumbnail The bitmap that will be shown as the initial thumbnail
+ * of the animation.
+ * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+ * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+ true);
+ }
+
+ /**
+ * Create an ActivityOptions specifying an animation where the new activity
+ * window and a thumbnail is aspect-scaled to a new location.
+ *
+ * @param source The View that this thumbnail is animating to. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param thumbnail The bitmap that will be shown as the final thumbnail
+ * of the animation.
+ * @param startX The x end location of the bitmap, relative to <var>source</var>.
+ * @param startY The y end location of the bitmap, relative to <var>source</var>.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+ false);
+ }
+
+ private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
+ int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+ ActivityOptions opts = new ActivityOptions();
+ opts.mPackageName = source.getContext().getPackageName();
+ opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
+ ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+ opts.mThumbnail = thumbnail;
+ int[] pts = new int[2];
+ source.getLocationOnScreen(pts);
+ opts.mStartX = pts[0] + startX;
+ opts.mStartY = pts[1] + startY;
+ opts.setOnAnimationStartedListener(source.getHandler(), listener);
+ return opts;
+ }
+
+ /**
* Create an ActivityOptions to transition between Activities using cross-Activity scene
* animations. This method carries the position of one shared element to the started Activity.
* The position of <code>sharedElement</code> will be used as the epicenter for the
@@ -484,7 +549,9 @@ public class ActivityOptions {
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
- mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
@@ -635,6 +702,8 @@ public class ActivityOptions {
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
@@ -691,6 +760,8 @@ public class ActivityOptions {
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index e0c7816b78d9..d143b8634531 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -51,8 +51,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -594,55 +594,6 @@ public final class LoadedApk {
return app;
}
- private void rewriteIntField(Field field, int packageId) throws IllegalAccessException {
- int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;
- int bannedModifiers = Modifier.FINAL;
-
- int mod = field.getModifiers();
- if ((mod & requiredModifiers) != requiredModifiers ||
- (mod & bannedModifiers) != 0) {
- throw new IllegalArgumentException("Field " + field.getName() +
- " is not rewritable");
- }
-
- if (field.getType() != int.class && field.getType() != Integer.class) {
- throw new IllegalArgumentException("Field " + field.getName() +
- " is not an integer");
- }
-
- try {
- int resId = field.getInt(null);
- field.setInt(null, (resId & 0x00ffffff) | (packageId << 24));
- } catch (IllegalAccessException e) {
- // This should not occur (we check above if we can write to it)
- throw new IllegalArgumentException(e);
- }
- }
-
- private void rewriteIntArrayField(Field field, int packageId) {
- int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;
-
- if ((field.getModifiers() & requiredModifiers) != requiredModifiers) {
- throw new IllegalArgumentException("Field " + field.getName() +
- " is not rewritable");
- }
-
- if (field.getType() != int[].class) {
- throw new IllegalArgumentException("Field " + field.getName() +
- " is not an integer array");
- }
-
- try {
- int[] array = (int[]) field.get(null);
- for (int i = 0; i < array.length; i++) {
- array[i] = (array[i] & 0x00ffffff) | (packageId << 24);
- }
- } catch (IllegalAccessException e) {
- // This should not occur (we check above if we can write to it)
- throw new IllegalArgumentException(e);
- }
- }
-
private void rewriteRValues(ClassLoader cl, String packageName, int id) {
final Class<?> rClazz;
try {
@@ -650,35 +601,30 @@ public final class LoadedApk {
} catch (ClassNotFoundException e) {
// This is not necessarily an error, as some packages do not ship with resources
// (or they do not need rewriting).
- Log.i(TAG, "Could not find R class for package '" + packageName + "'");
+ Log.i(TAG, "No resource references to update in package " + packageName);
return;
}
+ final Method callback;
try {
- Class<?>[] declaredClasses = rClazz.getDeclaredClasses();
- for (Class<?> clazz : declaredClasses) {
- try {
- if (clazz.getSimpleName().equals("styleable")) {
- for (Field field : clazz.getDeclaredFields()) {
- if (field.getType() == int[].class) {
- rewriteIntArrayField(field, id);
- }
- }
-
- } else {
- for (Field field : clazz.getDeclaredFields()) {
- rewriteIntField(field, id);
- }
- }
- } catch (Exception e) {
- throw new IllegalArgumentException("Failed to rewrite R values for " +
- clazz.getName(), e);
- }
- }
+ callback = rClazz.getMethod("onResourcesLoaded", int.class);
+ } catch (NoSuchMethodException e) {
+ // No rewriting to be done.
+ return;
+ }
- } catch (Exception e) {
- throw new IllegalArgumentException("Failed to rewrite R values", e);
+ Throwable cause;
+ try {
+ callback.invoke(null, id);
+ return;
+ } catch (IllegalAccessException e) {
+ cause = e;
+ } catch (InvocationTargetException e) {
+ cause = e.getCause();
}
+
+ throw new RuntimeException("Failed to rewrite resource references for " + packageName,
+ cause);
}
public void removeContextRegistrations(Context context,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 41bbb87e55e9..b17309f16d52 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -126,7 +126,7 @@ public class DevicePolicyManager {
* message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
+ = "android.app.extra.deviceAdminPackageName";
/**
* A String extra holding the default name of the profile that is created during managed profile
@@ -149,7 +149,7 @@ public class DevicePolicyManager {
* It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
- = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+ = "android.app.extra.ManagedProfileEmailAddress";
/**
* A String extra holding the time zone {@link android.app.AlarmManager} that the device
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 56b71643f5df..5492775d8f68 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1217,6 +1217,14 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocargiogram.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SENSOR_HEART_RATE_ECG =
+ "android.hardware.sensor.heartrate.ecg";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes a relative humidity sensor.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index d19418b37940..e63fd0703339 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -533,6 +533,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public static final int DENSITY_DPI_UNDEFINED = 0;
/**
+ * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
+ * {@hide}
+ */
+ public static final int DENSITY_DPI_ANY = 0xfffe;
+
+ /**
+ * Value for {@link #densityDpi} for resources that are not meant to be scaled.
+ * {@hide}
+ */
+ public static final int DENSITY_DPI_NONE = 0xffff;
+
+ /**
* The target screen density being rendered to,
* corresponding to
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
@@ -1453,7 +1465,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
switch (config.densityDpi) {
- case 0:
+ case DENSITY_DPI_UNDEFINED:
break;
case 120:
parts.add("ldpi");
@@ -1476,6 +1488,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
case 640:
parts.add("xxxhdpi");
break;
+ case DENSITY_DPI_ANY:
+ parts.add("anydpi");
+ break;
+ case DENSITY_DPI_NONE:
+ parts.add("nodpi");
default:
parts.add(config.densityDpi + "dpi");
break;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7deb9c89f79f..5d6d99820b44 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -93,6 +93,8 @@ interface IWindowManager
int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp);
+ void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 854e6be5f84e..adad08242e62 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7022,27 +7022,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (another == null) {
return 1;
}
- if (getClass() != another.getClass()) {
- return 1;
- }
- final int topDiference = mLocation.top - another.mLocation.top;
- if (topDiference != 0) {
- return topDiference;
- }
- // LTR
+ // We are ordering left-to-right, top-to-bottom.
if (mLayoutDirection == LAYOUT_DIRECTION_LTR) {
final int leftDifference = mLocation.left - another.mLocation.left;
- // First more to the left than second.
if (leftDifference != 0) {
return leftDifference;
}
} else { // RTL
final int rightDifference = mLocation.right - another.mLocation.right;
- // First more to the right than second.
if (rightDifference != 0) {
return -rightDifference;
}
}
+ // We are ordering left-to-right, top-to-bottom.
+ final int topDifference = mLocation.top - another.mLocation.top;
+ if (topDifference != 0) {
+ return topDifference;
+ }
// Break tie by height.
final int heightDiference = mLocation.height() - another.mLocation.height();
if (heightDiference != 0) {
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index ca6437a4d31c..ead757eb9a7d 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -54,7 +54,12 @@ final class AccessibilityCache {
if (DEBUG) {
Log.i(LOG_TAG, "Caching window: " + window.getId());
}
- mWindowCache.put(window.getId(), window);
+ final int windowId = window.getId();
+ AccessibilityWindowInfo oldWindow = mWindowCache.get(windowId);
+ if (oldWindow != null) {
+ oldWindow.recycle();
+ }
+ mWindowCache.put(windowId, AccessibilityWindowInfo.obtain(window));
}
}
@@ -183,14 +188,13 @@ final class AccessibilityCache {
sortedWindows.put(window.getLayer(), window);
}
- List<AccessibilityWindowInfo> windows = new ArrayList<>();
+ List<AccessibilityWindowInfo> windows = new ArrayList<>(windowCount);
for (int i = windowCount - 1; i >= 0; i--) {
AccessibilityWindowInfo window = sortedWindows.valueAt(i);
windows.add(AccessibilityWindowInfo.obtain(window));
+ sortedWindows.removeAt(i);
}
- sortedWindows.clear();
-
return windows;
}
return null;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 80b5c5071c3a..ad55f5f2a097 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -55,6 +55,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0;
private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1;
+ private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2;
// Housekeeping.
private static final int MAX_POOL_SIZE = 10;
@@ -258,6 +259,26 @@ public final class AccessibilityWindowInfo implements Parcelable {
}
/**
+ * Gets if this window has accessibility focus.
+ *
+ * @return Whether has accessibility focus.
+ */
+ public boolean isAccessibilityFocused() {
+ return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED);
+ }
+
+ /**
+ * Sets if this window has accessibility focus.
+ *
+ * @param Whether has accessibility focus.
+ *
+ * @hide
+ */
+ public void setAccessibilityFocused(boolean focused) {
+ setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused);
+ }
+
+ /**
* Gets the number of child windows.
*
* @return The child count.
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 7c30d2a0bfb2..de7d2d0e727b 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -98,7 +98,7 @@ public class CookieManager {
* @param webview the {@link WebView} instance to get the cookie policy for
* @return true if the {@link WebView} accepts third party cookies
*/
- public synchronized boolean acceptThirdPartyCookies(WebView webview) {
+ public boolean acceptThirdPartyCookies(WebView webview) {
throw new MustOverrideException();
}
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index e3f229fc659f..2f30ebc5cf4b 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -91,26 +91,40 @@ public class InstallerConnection {
}
public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
+ return dexopt(apkPath, uid, isPublic, "*", instructionSet, false);
+ }
+
+ public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
+ String instructionSet, boolean vmSafeMode) {
StringBuilder builder = new StringBuilder("dexopt");
builder.append(' ');
builder.append(apkPath);
builder.append(' ');
builder.append(uid);
builder.append(isPublic ? " 1" : " 0");
- builder.append(" *"); // No pkgName arg present
+ builder.append(' ');
+ builder.append(pkgName);
builder.append(' ');
builder.append(instructionSet);
+ builder.append(' ');
+ builder.append(vmSafeMode ? " 1" : " 0");
return execute(builder.toString());
}
public int patchoat(String apkPath, int uid, boolean isPublic, String instructionSet) {
+ return patchoat(apkPath, uid, isPublic, "*", instructionSet);
+ }
+
+ public int patchoat(String apkPath, int uid, boolean isPublic, String pkgName,
+ String instructionSet) {
StringBuilder builder = new StringBuilder("patchoat");
builder.append(' ');
builder.append(apkPath);
builder.append(' ');
builder.append(uid);
builder.append(isPublic ? " 1" : " 0");
- builder.append(" *"); // No pkgName arg present
+ builder.append(' ');
+ builder.append(pkgName);
builder.append(' ');
builder.append(instructionSet);
return execute(builder.toString());
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 79b85421c940..a8b8bef18a95 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -881,7 +881,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
"-Xprofile-max-stack-depth:");
}
- parseRuntimeOption("dalvik.vm.native.bridge", nativeBridgeLibrary, "-XX:NativeBridge=");
+ parseRuntimeOption("ro.dalvik.vm.native.bridge", nativeBridgeLibrary, "-XX:NativeBridge=");
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index e02aa5e5560c..6146fff58d50 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -66,6 +66,7 @@ static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jl
} else {
shader->resetLocalMatrix();
}
+ shader->setGenerationID(shader->getGenerationID() + 1);
}
}
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 3180e585ba38..c0d999546399 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -19,9 +19,9 @@
-->
<resources>
<!-- The width that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_width">512dp</dimen>
+ <dimen name="thumbnail_width">360dp</dimen>
<!-- The height that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_height">512dp</dimen>
+ <dimen name="thumbnail_height">360dp</dimen>
<!-- The maximum number of action buttons that should be permitted within
an action bar/action mode. This will be used to determine how many
showAsAction="ifRoom" items can fit. "always" items can override this. -->
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 9ac6927ca6aa..042da5b250d5 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -119,7 +119,7 @@ import java.util.Stack;
* <dd>Defines path string. This is using exactly same format as "d" attribute
* in the SVG's path data. This is defined in the viewport space.</dd>
* <dt><code>android:fillColor</code></dt>
- * <dd>Defines the color to fill the path (black if not present).</dd>
+ * <dd>Defines the color to fill the path (none if not present).</dd>
* <dt><code>android:strokeColor</code></dt>
* <dd>Defines the color to draw the path outline (none if not present).</dd>
* <dt><code>android:strokeWidth</code></dt>
@@ -862,7 +862,7 @@ public class VectorDrawable extends Drawable {
}
mRenderPath.addPath(path, mFinalPathMatrix);
- if (fullPath.mFillColor != 0) {
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
if (mFillPaint == null) {
mFillPaint = new Paint();
mFillPaint.setColorFilter(mColorFilter);
@@ -873,7 +873,7 @@ public class VectorDrawable extends Drawable {
canvas.drawPath(mRenderPath, mFillPaint);
}
- if (fullPath.mStrokeColor != 0) {
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
if (mStrokePaint == null) {
mStrokePaint = new Paint();
mStrokePaint.setColorFilter(mColorFilter);
@@ -1237,9 +1237,9 @@ public class VectorDrawable extends Drawable {
// Variables below need to be copied (deep copy if applicable) for mutation.
private int[] mThemeAttrs;
- int mStrokeColor = 0;
+ int mStrokeColor = Color.TRANSPARENT;
float mStrokeWidth = 0;
- int mFillColor = Color.BLACK;
+ int mFillColor = Color.TRANSPARENT;
int mFillRule;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 1af497cfb2e4..11568d280c24 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -954,6 +954,7 @@ struct ResTable_config
DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH,
DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH,
DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH,
+ DENSITY_ANY = ACONFIGURATION_DENSITY_ANY,
DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
};
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 239d682d1c8c..3f014ef5de1e 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2206,13 +2206,30 @@ bool ResTable_config::isBetterThan(const ResTable_config& o,
if (screenType || o.screenType) {
if (density != o.density) {
- // density is tough. Any density is potentially useful
+ // Use the system default density (DENSITY_MEDIUM, 160dpi) if none specified.
+ const int thisDensity = density ? density : int(ResTable_config::DENSITY_MEDIUM);
+ const int otherDensity = o.density ? o.density : int(ResTable_config::DENSITY_MEDIUM);
+
+ // We always prefer DENSITY_ANY over scaling a density bucket.
+ if (thisDensity == ResTable_config::DENSITY_ANY) {
+ return true;
+ } else if (otherDensity == ResTable_config::DENSITY_ANY) {
+ return false;
+ }
+
+ int requestedDensity = requested->density;
+ if (requested->density == 0 ||
+ requested->density == ResTable_config::DENSITY_ANY) {
+ requestedDensity = ResTable_config::DENSITY_MEDIUM;
+ }
+
+ // DENSITY_ANY is now dealt with. We should look to
+ // pick a density bucket and potentially scale it.
+ // Any density is potentially useful
// because the system will scale it. Scaling down
// is generally better than scaling up.
- // Default density counts as 160dpi (the system default)
- // TODO - remove 160 constants
- int h = (density?density:160);
- int l = (o.density?o.density:160);
+ int h = thisDensity;
+ int l = otherDensity;
bool bImBigger = true;
if (l > h) {
int t = h;
@@ -2221,17 +2238,16 @@ bool ResTable_config::isBetterThan(const ResTable_config& o,
bImBigger = false;
}
- int reqValue = (requested->density?requested->density:160);
- if (reqValue >= h) {
+ if (requestedDensity >= h) {
// requested value higher than both l and h, give h
return bImBigger;
}
- if (l >= reqValue) {
+ if (l >= requestedDensity) {
// requested value lower than both l and h, give l
return !bImBigger;
}
// saying that scaling down is 2x better than up
- if (((2 * l) - reqValue) * h > reqValue * reqValue) {
+ if (((2 * l) - requestedDensity) * h > requestedDensity * requestedDensity) {
return !bImBigger;
} else {
return bImBigger;
@@ -2702,6 +2718,9 @@ String8 ResTable_config::toString() const {
case ResTable_config::DENSITY_NONE:
res.append("nodpi");
break;
+ case ResTable_config::DENSITY_ANY:
+ res.append("anydpi");
+ break;
default:
res.appendFormat("%ddpi", dtohs(density));
break;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 4ff6eecf1685..a10c38761fbd 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -21,8 +21,9 @@
LOCAL_PATH:= $(call my-dir)
testFiles := \
ByteBucketArray_test.cpp \
+ Config_test.cpp \
+ ConfigLocale_test.cpp \
Idmap_test.cpp \
- ResourceTypes_test.cpp \
ResTable_test.cpp \
Split_test.cpp \
TypeWrappers_test.cpp \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index f00a2d9ea6e3..49995942a562 100644
--- a/libs/androidfw/tests/ResourceTypes_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -21,7 +21,7 @@
#include <gtest/gtest.h>
namespace android {
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterLanguage) {
ResTable_config config;
config.packLanguage("en");
@@ -44,7 +44,7 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterRegion) {
ResTable_config config;
config.packRegion("US");
@@ -59,7 +59,7 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguage) {
ResTable_config config;
config.packLanguage("eng");
@@ -75,7 +75,7 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguageAtOffset16) {
ResTable_config config;
config.packLanguage("tgp");
@@ -88,8 +88,8 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
// which is equivalent to:
// 1 [0] [1] [2]
// 1-01111-00110-10011
- EXPECT_EQ(0xbc, config.language[0]);
- EXPECT_EQ(0xd3, config.language[1]);
+ EXPECT_EQ(char(0xbc), config.language[0]);
+ EXPECT_EQ(char(0xd3), config.language[1]);
char out[4] = { 1, 1, 1, 1};
config.unpackLanguage(out);
@@ -99,7 +99,7 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterRegion) {
ResTable_config config;
config.packRegion("419");
@@ -131,7 +131,7 @@ TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
}
}
-TEST(ResourceTypesTest, IsMoreSpecificThan) {
+TEST(ConfigLocaleTest, IsMoreSpecificThan) {
ResTable_config l;
ResTable_config r;
@@ -170,7 +170,7 @@ TEST(ResourceTypesTest, IsMoreSpecificThan) {
EXPECT_TRUE(r.isMoreSpecificThan(l));
}
-TEST(ResourceTypesTest, setLocale) {
+TEST(ConfigLocaleTest, setLocale) {
ResTable_config test;
test.setBcp47Locale("en-US");
EXPECT_EQ('e', test.language[0]);
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
new file mode 100644
index 000000000000..ef30df46d36c
--- /dev/null
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "TestHelpers.h"
+#include <gtest/gtest.h>
+
+namespace android {
+
+static ResTable_config selectBest(const ResTable_config& target,
+ const Vector<ResTable_config>& configs) {
+ ResTable_config bestConfig;
+ memset(&bestConfig, 0, sizeof(bestConfig));
+ const size_t configCount = configs.size();
+ for (size_t i = 0; i < configCount; i++) {
+ const ResTable_config& thisConfig = configs[i];
+ if (!thisConfig.match(target)) {
+ continue;
+ }
+
+ if (thisConfig.isBetterThan(bestConfig, &target)) {
+ bestConfig = thisConfig;
+ }
+ }
+ return bestConfig;
+}
+
+static ResTable_config buildDensityConfig(int density) {
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.density = uint16_t(density);
+ config.sdkVersion = 4;
+ return config;
+}
+
+TEST(ConfigTest, shouldSelectBestDensity) {
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.density = ResTable_config::DENSITY_XHIGH;
+ deviceConfig.sdkVersion = 21;
+
+ Vector<ResTable_config> configs;
+
+ ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_HIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ expectedBest.sdkVersion = 21;
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+TEST(ConfigTest, shouldSelectBestDensityWhenNoneSpecified) {
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.sdkVersion = 21;
+
+ Vector<ResTable_config> configs;
+ configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
+
+ ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+} // namespace android.
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 75a233acad26..fe2e5ce29eff 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -3,6 +3,7 @@
#include <ostream>
+#include <androidfw/ResourceTypes.h>
#include <utils/String8.h>
#include <utils/String16.h>
@@ -14,4 +15,16 @@ static inline ::std::ostream& operator<<(::std::ostream& out, const android::Str
return out << android::String8(str).string();
}
+namespace android {
+
+static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) {
+ return memcmp(&a, &b, sizeof(a)) == 0;
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::ResTable_config& c) {
+ return out << c.toString().string();
+}
+
+} // namespace android
+
#endif // __TEST_HELPERS_H
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 7350082bdad7..e9c937cbeb0c 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -215,11 +215,17 @@ private:
if (!paint) return NULL;
const SkPaint* paintCopy = mPaintMap.valueFor(paint);
- if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
- paintCopy = new SkPaint(*paint);
+ if (paintCopy == NULL
+ || paintCopy->getGenerationID() != paint->getGenerationID()
+ // We can't compare shader pointers because that will always
+ // change as we do partial copying via wrapping. However, if the
+ // shader changes the paint generationID will have changed and
+ // so we don't hit this comparison anyway
+ || !(paint->getShader() && paintCopy->getShader()
+ && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) {
+ paintCopy = copyPaint(paint);
// replaceValueFor() performs an add if the entry doesn't exist
mPaintMap.replaceValueFor(paint, paintCopy);
- mDisplayListData->paints.add(paintCopy);
}
return paintCopy;
@@ -228,8 +234,15 @@ private:
inline SkPaint* copyPaint(const SkPaint* paint) {
if (!paint) return NULL;
SkPaint* paintCopy = new SkPaint(*paint);
+ if (paint->getShader()) {
+ SkShader* shaderCopy = SkShader::CreateLocalMatrixShader(
+ paint->getShader(), paint->getShader()->getLocalMatrix());
+ paintCopy->setShader(shaderCopy);
+ paintCopy->setGenerationID(paint->getGenerationID());
+ shaderCopy->setGenerationID(paint->getShader()->getGenerationID());
+ shaderCopy->unref();
+ }
mDisplayListData->paints.add(paintCopy);
-
return paintCopy;
}
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index cb20a0b2a53f..2178cc7a5567 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -647,7 +647,7 @@ float SpotShadow::projectCasterToOutline(Vector2& outline,
if (lightToPolyZ != 0) {
// If any caster's vertex is almost above the light, we just keep it as 95%
// of the height of the light.
- ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO);
+ ratioZ = MathUtils::clamp(polyVertex.z / lightToPolyZ, 0.0f, CASTER_Z_CAP_RATIO);
}
outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x);
@@ -669,6 +669,10 @@ float SpotShadow::projectCasterToOutline(Vector2& outline,
void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
VertexBuffer& shadowTriangleStrip) {
+ if (CC_UNLIKELY(lightCenter.z <= 0)) {
+ ALOGW("Relative Light Z is not positive. No spot shadow!");
+ return;
+ }
OutlineData outlineData[polyLength];
Vector2 outlineCentroid;
// Calculate the projected outline for each polygon's vertices from the light center.
@@ -787,7 +791,7 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCente
// The ratio can be simulated by using the inverse of maximum of ratioVI for
// all (V).
distOutline = (outlineData[i].position - outlineCentroid).length();
- if (distOutline == 0) {
+ if (CC_UNLIKELY(distOutline == 0)) {
// If the outline has 0 area, then there is no spot shadow anyway.
ALOGW("Outline has 0 area, no spot shadow!");
return;
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 00448b845579..d89859b51992 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -76,6 +76,11 @@ public:
return a < b ? a : b;
}
+ template<typename T>
+ static inline T clamp(T a, T minValue, T maxValue) {
+ return min(max(a, minValue), maxValue);
+ }
+
inline static float lerp(float v1, float v2, float t) {
return v1 + ((v2 - v1) * t);
}
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index e6ef6d7618e2..017645a276b7 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -862,6 +862,7 @@ public class TvView extends ViewGroup {
mSession.setStreamVolume(mStreamVolume);
}
} else {
+ mSessionCallback = null;
if (mListener != null) {
mListener.onConnectionFailed(mInputId);
}
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 783aa0342ae4..469b776064fc 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -16,6 +16,7 @@
android:multiprocess="false"
android:exported="true"
android:writePermission="android.permission.WRITE_SETTINGS"
+ android:singleUser="true"
android:initOrder="100" />
</application>
</manifest>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index 305a82f7c93c..4e1d66dedda6 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -20,9 +20,9 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index 863591f9d221..afab78d0a1ec 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -24,5 +24,5 @@
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
index adcefe074b02..4e1d66dedda6 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -23,6 +23,6 @@
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_linear_in"
- android:duration="200"/>
+ android:interpolator="@android:interpolator/linear"
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
index 863591f9d221..afab78d0a1ec 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -24,5 +24,5 @@
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png
deleted file mode 100644
index 369c88d31707..000000000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_ime_switcher_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png
deleted file mode 100644
index 7d97eb575f2a..000000000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_ime_switcher_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png
deleted file mode 100644
index 900801a4d3d7..000000000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_ime_switcher_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png b/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png
deleted file mode 100644
index 6c8222ec50b7..000000000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_ime_switcher_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
new file mode 100644
index 000000000000..4d9ca884f30a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z"
+ android:fillColor="@color/navigation_bar_icon_color"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 5253ee07e7e8..4cb8498e07d0 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -23,45 +23,7 @@
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.systemui.recents.views.TaskViewHeader
- android:id="@+id/task_view_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/recents_task_bar_height"
- android:layout_gravity="top|center_horizontal">
- <com.android.systemui.recents.views.FixedSizeImageView
- android:id="@+id/application_icon"
- android:layout_width="@dimen/recents_task_view_application_icon_size"
- android:layout_height="@dimen/recents_task_view_application_icon_size"
- android:layout_marginStart="8dp"
- android:layout_gravity="center_vertical|start"
- android:padding="8dp"
- android:background="@drawable/recents_button_bg" />
- <TextView
- android:id="@+id/activity_description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginStart="64dp"
- android:layout_marginEnd="64dp"
- android:textSize="16sp"
- android:textColor="#ffffffff"
- android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-medium"
- android:singleLine="true"
- android:maxLines="2"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
- <com.android.systemui.recents.views.FixedSizeImageView
- android:id="@+id/dismiss_task"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical|end"
- android:padding="12dp"
- android:background="@drawable/recents_button_bg"
- android:visibility="invisible"
- android:src="@drawable/recents_dismiss_light" />
- </com.android.systemui.recents.views.TaskViewHeader>
+ <include layout="@layout/recents_task_view_header" />
<FrameLayout
android:id="@+id/lock_to_app_fab"
android:layout_width="48dp"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
new file mode 100644
index 000000000000..f1d8ad0e4b8e
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.systemui.recents.views.TaskViewHeader
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/task_view_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/recents_task_bar_height"
+ android:layout_gravity="top|center_horizontal">
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/application_icon"
+ android:layout_width="@dimen/recents_task_view_application_icon_size"
+ android:layout_height="@dimen/recents_task_view_application_icon_size"
+ android:layout_marginStart="8dp"
+ android:layout_gravity="center_vertical|start"
+ android:padding="8dp"
+ android:background="@drawable/recents_button_bg" />
+ <TextView
+ android:id="@+id/activity_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="64dp"
+ android:layout_marginEnd="64dp"
+ android:textSize="16sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_empty_message"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="2"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/dismiss_task"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical|end"
+ android:padding="12dp"
+ android:background="@drawable/recents_button_bg"
+ android:visibility="invisible"
+ android:src="@drawable/recents_dismiss_light" />
+</com.android.systemui.recents.views.TaskViewHeader> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index dea14e9fcafc..75ed81ec3e78 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -106,4 +106,7 @@
<color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
<color name="doze_small_icon_background_color">#ff434343</color>
+
+ <!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
+ <color name="navigation_bar_icon_color">#E5FFFFFF</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 52dc000198ec..fa00ebf16a2b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -126,7 +126,7 @@
<integer name="recents_animate_task_bar_enter_duration">275</integer>
<!-- The animation delay for animating the first task in. This should roughly be the animation
duration of the transition in to recents. -->
- <integer name="recents_animate_task_bar_enter_delay">225</integer>
+ <integer name="recents_animate_task_bar_enter_delay">300</integer>
<!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_exit_to_home_duration">225</integer>
<!-- The min animation duration for animating the task bar out. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 354eb55a1880..8710aa25109c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -22,6 +22,7 @@ import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -29,6 +30,7 @@ import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.os.UserHandle;
+import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
@@ -41,6 +43,7 @@ import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackViewLayoutAlgorithm;
+import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import java.util.ArrayList;
@@ -86,6 +89,10 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
int mNavBarHeight;
int mNavBarWidth;
+ // Header (for transition)
+ TaskViewHeader mHeaderBar;
+ TaskStackView mDummyStackView;
+
// Variables to keep track of if we need to start recents after binding
View mStatusBarView;
boolean mTriggeredFromAltTab;
@@ -114,6 +121,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
public void onStart() {
// Initialize some static datastructures
TaskStackViewLayoutAlgorithm.initializeCurve();
+ reloadHeaderBarLayout();
}
public void onBootCompleted() {
@@ -169,7 +177,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
void showRelativeAffiliatedTask(boolean showNextTask) {
TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy,
- Integer.MAX_VALUE);
+ Integer.MAX_VALUE, mContext.getResources());
// Return early if there are no tasks
if (stack.getTaskCount() == 0) return;
@@ -250,6 +258,28 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
}
sLastScreenshot = null;
+ reloadHeaderBarLayout();
+ }
+
+ /** Prepares the header bar layout. */
+ void reloadHeaderBarLayout() {
+ // Inflate the header bar layout so that we can rebind and draw it for the transition
+ Resources res = mContext.getResources();
+ TaskStack stack = new TaskStack();
+ mDummyStackView = new TaskStackView(mContext, stack);
+ TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
+ Rect taskStackBounds = new Rect(mTaskStackBounds);
+ taskStackBounds.bottom -= mSystemInsets.bottom;
+ algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
+ Rect taskViewSize = algo.getUntransformedTaskViewSize();
+ int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, null,
+ false);
+ mHeaderBar.measure(
+ View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY));
+ mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight);
}
/** Gets the top task. */
@@ -361,27 +391,37 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
- // If the screenshot fails, then load the first task thumbnail and use that
- Bitmap firstThumbnail = mSystemServicesProxy.getTaskThumbnail(topTask.id);
- if (firstThumbnail != null) {
- // Update the destination rect
- Rect toTaskRect = getThumbnailTransitionRect(topTask.id, isTopTaskHome);
- if (toTaskRect.width() > 0 && toTaskRect.height() > 0) {
- // Create the new thumbnail for the animation down
- // XXX: We should find a way to optimize this so we don't need to create a new bitmap
- Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
- Bitmap.Config.ARGB_8888);
- int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+ // Update the destination rect
+ Task toTask = new Task();
+ TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome,
+ toTask);
+ if (toTransform != null && toTask.key != null) {
+ Rect toTaskRect = toTransform.rect;
+ ActivityInfo info = mSystemServicesProxy.getActivityInfo(
+ toTask.key.baseIntent.getComponent(), toTask.key.userId);
+ if (toTask.activityIcon == null) {
+ toTask.activityIcon = mSystemServicesProxy.getActivityIcon(info,
+ toTask.key.userId);
+ }
+ if (toTask.activityLabel == null) {
+ toTask.activityLabel = mSystemServicesProxy.getActivityLabel(info);
+ }
+
+ Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ thumbnail.eraseColor(0xFFff0000);
+ } else {
Canvas c = new Canvas(thumbnail);
- c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
- new Rect(0, 0, toTaskRect.width(), toTaskRect.height()), null);
+ c.scale(toTransform.scale, toTransform.scale);
+ mHeaderBar.rebindToTask(toTask);
+ mHeaderBar.draw(c);
c.setBitmap(null);
- // Recycle the old thumbnail
- firstThumbnail.recycle();
- mStartAnimationTriggered = false;
- return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
- thumbnail, toTaskRect.left, toTaskRect.top, this);
}
+
+ mStartAnimationTriggered = false;
+ return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
+ thumbnail, toTaskRect.left, toTaskRect.top, this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -389,21 +429,18 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
/** Returns the transition rect for the given task id. */
- Rect getThumbnailTransitionRect(int runningTaskId, boolean isTopTaskHome) {
+ TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome,
+ Task runningTaskOut) {
// Get the stack of tasks that we are animating into
- TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1);
+ TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1,
+ mContext.getResources());
if (stack.getTaskCount() == 0) {
- return new Rect();
+ return null;
}
// Get the stack
- TaskStackView tsv = new TaskStackView(mContext, stack);
- TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
- Rect taskStackBounds = new Rect(mTaskStackBounds);
- taskStackBounds.bottom -= mSystemInsets.bottom;
- tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds,
- mTriggeredFromAltTab, isTopTaskHome);
- tsv.getScroller().setStackScrollToInitialState();
+ mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
+ mDummyStackView.getScroller().setStackScrollToInitialState();
// Find the running task in the TaskStack
Task task = null;
@@ -415,6 +452,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
Task t = tasks.get(i);
if (t.key.id == runningTaskId) {
task = t;
+ runningTaskOut.copyFrom(t);
break;
}
}
@@ -425,8 +463,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
// Get the transform for the running task
- mTmpTransform = algo.getStackTransform(task, tsv.getScroller().getStackScroll(), mTmpTransform, null);
- return new Rect(mTmpTransform.rect);
+ mTmpTransform = mDummyStackView.getStackAlgorithm().getStackTransform(task,
+ mDummyStackView.getScroller().getStackScroll(), mTmpTransform, null);
+ return mTmpTransform;
}
/** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 3709c4364184..6f4cf6b1cb27 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -27,6 +27,8 @@ public class Constants {
public static class App {
// Enables the screenshot app->Recents transition
public static final boolean EnableScreenshotAppTransition = false;
+ // Enables debug drawing for the transition thumbnail
+ public static final boolean EnableTransitionThumbnailDebugMode = false;
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables clipping of tasks against each other
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7fafe7aa28d1..a5b845d00e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -384,7 +384,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Private API calls to make the shadows look better
try {
- Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
} catch (IllegalAccessException e) {
e.printStackTrace();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5390daf6db00..b29f3780eb4a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -174,6 +174,7 @@ public class SystemServicesProxy {
int minNumTasksToQuery = 10;
int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
+ ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
ActivityManager.RECENT_INCLUDE_PROFILES |
ActivityManager.RECENT_WITH_EXCLUDED, userId);
@@ -185,11 +186,6 @@ public class SystemServicesProxy {
// NOTE: The order of these checks happens in the expected order of the traversal of the
// tasks
- // Skip tasks from this Recents package
- if (t.baseIntent.getComponent().getPackageName().equals(mRecentsPackage)) {
- iter.remove();
- continue;
- }
// Check the first non-recents task, include this task even if it is marked as excluded
// from recents. In other words, only remove excluded tasks if it is not the first task
boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
@@ -199,11 +195,6 @@ public class SystemServicesProxy {
continue;
}
isFirstValidTask = false;
- // Skip tasks in the home stack
- if (isInHomeStack(t.persistentId)) {
- iter.remove();
- continue;
- }
}
return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 0e2f37038283..b93c1260fac2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -18,6 +18,7 @@ package com.android.systemui.recents.model;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
@@ -31,6 +32,7 @@ import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
@@ -171,9 +173,9 @@ class TaskResourceLoader implements Runnable {
// Load the application icon if it is stale or we haven't cached one yet
if (cachedIcon == null) {
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
- t.userId);
+ t.key.userId);
if (info != null) {
- cachedIcon = ssp.getActivityIcon(info, t.userId);
+ cachedIcon = ssp.getActivityIcon(info, t.key.userId);
}
if (cachedIcon == null) {
cachedIcon = mDefaultApplicationIcon;
@@ -228,8 +230,10 @@ public class RecentsTaskLoader {
static RecentsTaskLoader sInstance;
SystemServicesProxy mSystemServicesProxy;
+ DrawableLruCache mTaskDescriptionIconCache;
DrawableLruCache mApplicationIconCache;
BitmapLruCache mThumbnailCache;
+ StringLruCache mActivityLabelCache;
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
@@ -270,8 +274,10 @@ public class RecentsTaskLoader {
mSystemServicesProxy = new SystemServicesProxy(context);
mPackageMonitor = new RecentsPackageMonitor();
mLoadQueue = new TaskResourceLoadQueue();
+ mTaskDescriptionIconCache = new DrawableLruCache(iconCacheSize);
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
+ mActivityLabelCache = new StringLruCache(100);
mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
mDefaultThumbnail, mDefaultApplicationIcon);
}
@@ -313,6 +319,7 @@ public class RecentsTaskLoader {
RecentsConfiguration config = RecentsConfiguration.getInstance();
Resources res = context.getResources();
LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
+ ArrayList<Task> tasksToAdd = new ArrayList<Task>();
TaskStack stack = new TaskStack();
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -325,55 +332,80 @@ public class RecentsTaskLoader {
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
- if (info == null) continue;
+ Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+ t.firstActiveTime, t.lastActiveTime);
+ ComponentName cn = t.baseIntent.getComponent();
+ ActivityInfo info = null;
ActivityManager.TaskDescription av = t.taskDescription;
- String activityLabel = null;
+ String activityLabel = null;
Drawable activityIcon = mDefaultApplicationIcon;
int activityColor = config.taskBarViewDefaultBackgroundColor;
+ boolean loadedActivityIcon = false;
if (av != null) {
- activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
- activityIcon = (av.getIcon() != null) ?
+ activityLabel = av.getLabel();
+ activityIcon = mTaskDescriptionIconCache.getAndInvalidateIfModified(taskKey);
+ if (activityIcon == null) {
+ activityIcon = (av.getIcon() != null) ?
ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
+ if (activityIcon != null) {
+ mTaskDescriptionIconCache.put(taskKey, activityIcon);
+ }
+ }
if (av.getPrimaryColor() != 0) {
activityColor = av.getPrimaryColor();
}
- } else {
- activityLabel = ssp.getActivityLabel(info);
+ loadedActivityIcon = (activityIcon != null);
+ }
+ // If there is no activity label, then try and read it from the label cache before
+ // loading it from the system
+ if (activityLabel == null) {
+ activityLabel = mActivityLabelCache.getAndInvalidateIfModified(taskKey);
+ if (activityLabel == null) {
+ if (info == null) {
+ info = ssp.getActivityInfo(cn, t.userId);
+ }
+ activityLabel = ssp.getActivityLabel(info);
+ mActivityLabelCache.put(taskKey, activityLabel);
+ }
}
// Create a new task
- Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId,
- t.affiliatedTaskColor, activityLabel, activityIcon, activityColor, t.userId,
- t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1)),
+ Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor,
+ activityLabel, activityIcon, activityColor, (i == (taskCount - 1)),
config.lockToAppEnabled);
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
- // Load the icon from the cache if possible
- task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key);
- if (task.applicationIcon == null) {
- // Load the icon from the system
- task.applicationIcon = ssp.getActivityIcon(info, task.userId);
- if (task.applicationIcon != null) {
- mApplicationIconCache.put(task.key, task.applicationIcon);
+ // Load the icon from the cache if possible (only if we don't have an activity icon)
+ if (!loadedActivityIcon) {
+ task.applicationIcon =
+ mApplicationIconCache.getAndInvalidateIfModified(taskKey);
+ if (task.applicationIcon == null) {
+ // Load the icon from the system
+ if (info == null) {
+ info = ssp.getActivityInfo(cn, t.userId);
+ }
+ task.applicationIcon = ssp.getActivityIcon(info, taskKey.userId);
+ if (task.applicationIcon != null) {
+ mApplicationIconCache.put(taskKey, task.applicationIcon);
+ }
+ }
+ if (task.applicationIcon == null) {
+ // Either the task has changed since the last active time, or it was not
+ // previously cached, so try and load the task anew.
+ tasksToLoad.add(task);
}
- }
- if (task.applicationIcon == null) {
- // Either the task has changed since the last active time, or it was not
- // previously cached, so try and load the task anew.
- tasksToLoad.add(task);
}
// Load the thumbnail from the cache if possible
- task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key);
+ task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey);
if (task.thumbnail == null) {
// Load the thumbnail from the system
- task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+ task.thumbnail = ssp.getTaskThumbnail(taskKey.id);
if (task.thumbnail != null) {
task.thumbnail.setHasAlpha(false);
- mThumbnailCache.put(task.key, task.thumbnail);
+ mThumbnailCache.put(taskKey, task.thumbnail);
}
}
if (task.thumbnail == null) {
@@ -384,10 +416,11 @@ public class RecentsTaskLoader {
}
// Add the task to the stack
- stack.addTask(task);
+ tasksToAdd.add(task);
}
// Simulate the groupings that we describe
+ stack.setTasks(tasksToAdd);
stack.createAffiliatedGroupings(config);
// Start the task loader and add all the tasks we need to load
@@ -401,21 +434,29 @@ public class RecentsTaskLoader {
}
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
- public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks) {
+ public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks,
+ Resources resources) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, numTasks);
+ ArrayList<Task> tasksToAdd = new ArrayList<Task>();
TaskStack stack = new TaskStack();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
- if (info == null) continue;
+ ActivityManager.TaskDescription av = t.taskDescription;
- stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId,
- t.affiliatedTaskColor, null, null, 0, 0, t.firstActiveTime, t.lastActiveTime,
- (i == (taskCount - 1)), config.lockToAppEnabled));
+ BitmapDrawable icon = null;
+ if (av.getIcon() != null) {
+ icon = new BitmapDrawable(resources, av.getIcon());
+ }
+ Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+ t.firstActiveTime, t.lastActiveTime);
+ tasksToAdd.add(new Task(taskKey, true, t.affiliatedTaskId, t.affiliatedTaskColor,
+ av.getLabel(), icon, av.getPrimaryColor(), (i == (taskCount - 1)),
+ config.lockToAppEnabled));
}
+ stack.setTasks(tasksToAdd);
stack.createAffiliatedGroupings(config);
return stack;
}
@@ -484,18 +525,23 @@ public class RecentsTaskLoader {
// We are leaving recents, so trim the data a bit
mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
+ mTaskDescriptionIconCache.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);
mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
+ mTaskDescriptionIconCache.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();
mApplicationIconCache.evictAll();
+ mTaskDescriptionIconCache.evictAll();
+ // The cache is small, only clear the label cache when we are critical
+ mActivityLabelCache.evictAll();
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
new file mode 100644
index 000000000000..b06c4548c0ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.model;
+
+/**
+ * The String LRU cache.
+ */
+class StringLruCache extends KeyStoreLruCache<String> {
+ public StringLruCache(int cacheSize) {
+ super(cacheSize);
+ }
+
+ @Override
+ protected int computeSize(String s) {
+ // The cache size is measured in number of strings
+ return 1;
+ }
+} \ No newline at end of file
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 f6c3a7ed8ed1..977db602f9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -88,7 +88,6 @@ public class Task {
public boolean isActive;
public boolean lockToThisTask;
public boolean lockToTaskEnabled;
- public int userId;
TaskCallbacks mCb;
@@ -96,13 +95,12 @@ public class Task {
// Only used by RecentsService for task rect calculations.
}
- public Task(int id, boolean isActive, Intent intent, int taskAffiliation, int taskAffiliationColor,
- String activityTitle, Drawable activityIcon, int colorPrimary, int userId,
- long firstActiveTime, long lastActiveTime, boolean lockToThisTask,
- boolean lockToTaskEnabled) {
- boolean isInAffiliationGroup = (taskAffiliation != id);
+ public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
+ String activityTitle, Drawable activityIcon, int colorPrimary,
+ boolean lockToThisTask, boolean lockToTaskEnabled) {
+ boolean isInAffiliationGroup = (taskAffiliation != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
- this.key = new TaskKey(id, intent, userId, firstActiveTime, lastActiveTime);
+ this.key = key;
this.taskAffiliation = taskAffiliation;
this.taskAffiliationColor = taskAffiliationColor;
this.activityLabel = activityTitle;
@@ -113,7 +111,20 @@ public class Task {
this.isActive = isActive;
this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
this.lockToTaskEnabled = lockToTaskEnabled;
- this.userId = userId;
+ }
+
+ /** Copies the other task. */
+ public void copyFrom(Task o) {
+ this.key = o.key;
+ this.taskAffiliation = o.taskAffiliation;
+ this.taskAffiliationColor = o.taskAffiliationColor;
+ this.activityLabel = o.activityLabel;
+ this.activityIcon = o.activityIcon;
+ this.colorPrimary = o.colorPrimary;
+ this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
+ this.isActive = o.isActive;
+ this.lockToThisTask = o.lockToThisTask;
+ this.lockToTaskEnabled = o.lockToTaskEnabled;
}
/** Set the callbacks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 98bf151b3fab..1e47b504baf4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -92,7 +92,10 @@ class FilteredTaskList {
/** Returns the index of this task in the list of filtered tasks */
int indexOf(Task t) {
- return mTaskIndices.get(t.key);
+ if (mTaskIndices.containsKey(t.key)) {
+ return mTaskIndices.get(t.key);
+ }
+ return -1;
}
/** Returns the size of the list of filtered tasks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 07a7e74cfdab..1dd484bd36c6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -408,14 +408,26 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int thumbnailHeight = transform.rect.height();
if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
- // Resize the thumbnail to the size of the view that we are animating from
- Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight,
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
- c.drawBitmap(task.thumbnail,
- new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()),
- new Rect(0, 0, thumbnailWidth, thumbnailHeight), null);
- c.setBitmap(null);
+ Bitmap b;
+ if (tv != null) {
+ // Disable any focused state before we draw the header
+ if (tv.isFocusedTask()) {
+ tv.unsetFocusedTask();
+ }
+
+ b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ b.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(b);
+ c.scale(tv.getScaleX(), tv.getScaleY());
+ tv.mHeaderView.draw(c);
+ c.setBitmap(null);
+ }
+ } else {
+ // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
+ b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+ }
ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@@ -434,7 +446,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
};
}
- opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView,
+ opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
b, offsetX, offsetY, animStartedListener);
}
@@ -472,7 +484,15 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
if (tv == null) {
post(launchRunnable);
} else {
- stackView.startLaunchTaskAnimation(tv, launchRunnable);
+ if (!task.group.isFrontMostTask(task)) {
+ // For affiliated tasks that are behind other tasks, we must animate the front cards
+ // out of view before starting the task transition
+ stackView.startLaunchTaskAnimation(tv, launchRunnable);
+ } else {
+ // Otherwise, we can start the task transition immediately
+ stackView.startLaunchTaskAnimation(tv, null);
+ postDelayed(launchRunnable, 17);
+ }
}
}
@@ -485,7 +505,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities(null,
- new UserHandle(t.userId));
+ new UserHandle(t.key.userId));
}
@Override
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 aee558f88f65..861011fb3546 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -460,7 +460,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/**
- * This is called with the full window width and height to allow stack view children to
+ * This is ONLY used from AlternateRecentsComponent to update the dummy stack view for purposes
+ * of getting the task rect to animate to.
+ */
+ public void updateMinMaxScrollForStack(TaskStack stack, boolean launchedWithAltTab,
+ boolean launchedFromHome) {
+ mStack = stack;
+ updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
+ }
+
+ /**
+ * This is called with the full window width and height to allow stack view children to
* perform the full screen transition down.
*/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index f0bdfa2046e8..31fc7014db3a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -33,7 +33,7 @@ import java.util.HashMap;
public class TaskStackViewLayoutAlgorithm {
// These are all going to change
- static final float StackPeekMinScale = 0.825f; // The min scale of the last card in the peek area
+ static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area
RecentsConfiguration mConfig;
@@ -157,7 +157,7 @@ public class TaskStackViewLayoutAlgorithm {
public TaskViewTransform getStackTransform(Task task, float stackScroll, TaskViewTransform transformOut,
TaskViewTransform prevTransform) {
// Return early if we have an invalid index
- if (task == null) {
+ if (task == null || !mTaskProgressMap.containsKey(task.key)) {
transformOut.reset();
return transformOut;
}
@@ -200,6 +200,15 @@ public class TaskStackViewLayoutAlgorithm {
}
/**
+ * Returns the untransformed task view size.
+ */
+ public Rect getUntransformedTaskViewSize() {
+ Rect tvSize = new Rect(mTaskRect);
+ tvSize.offsetTo(0, 0);
+ return tvSize;
+ }
+
+ /**
* Returns the scroll to such task top = 1f;
*/
float getStackScrollForTask(Task t) {
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 e514c90c0966..dfbcce1df8e4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -235,7 +235,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
int initialDim = getDim();
if (mConfig.launchedFromAppWithScreenshot) {
if (isTaskViewLaunchTargetTask) {
- mHeaderView.prepareEnterRecentsAnimation();
// Hide the footer during the transition in, and animate it out afterwards?
if (mFooterView != null) {
mFooterView.animateFooterVisibility(false, 0);
@@ -246,8 +245,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
} else if (mConfig.launchedFromAppWithThumbnail) {
if (isTaskViewLaunchTargetTask) {
- // Hide the front most task bar view so we can animate it in
- mHeaderView.prepareEnterRecentsAnimation();
// Hide the action button if it exists
mActionButtonView.setAlpha(0f);
// Set the dim to 0 so we can animate it in
@@ -306,7 +303,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
}
// Animate the task bar of the first task view
- mHeaderView.startEnterRecentsAnimation(0, null);
animate()
.scaleX(taskScale)
.scaleY(taskScale)
@@ -352,9 +348,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
} else if (mConfig.launchedFromAppWithThumbnail) {
if (mTask.isLaunchTarget) {
- // Animate the task bar of the first task view
- mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
- mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView));
+ // Enable the task bar clip
+ mThumbnailView.enableTaskBarClip(mHeaderView);
// Animate the dim/overlay
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
// Animate the thumbnail alpha before the dim animation (to prevent updating the
@@ -475,14 +470,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
/** Animates this task view as it exits recents */
- void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
+ void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
boolean occludesLaunchTarget) {
if (isLaunchingTask) {
- // Disable the thumbnail clip and animate the bar out for the window animation out
- mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r,
- mIsFocused);
+ // Disable the thumbnail clip
+ mThumbnailView.disableTaskBarClip();
// Animate the thumbnail alpha back into full opacity for the window animation out
- mThumbnailView.startLaunchTaskAnimation();
+ mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
// Animate the dim
if (mDim > 0) {
@@ -493,7 +487,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
// Animate the action button away
- mActionButtonView.animate().alpha(0f)
+ float toScale = 0.9f;
+ mActionButtonView.animate()
+ .alpha(0f)
+ .scaleX(toScale)
+ .scaleY(toScale)
.setStartDelay(0)
.setDuration(mConfig.taskBarExitAnimDuration)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
@@ -706,22 +704,30 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
/**
+ * Unsets the focused task explicitly.
+ */
+ void unsetFocusedTask() {
+ mIsFocused = false;
+ if (mFocusAnimationsEnabled) {
+ // Un-focus the header bar
+ mHeaderView.onTaskViewFocusChanged(false);
+ }
+
+ // Update the thumbnail alpha with the focus
+ mThumbnailView.onFocusChanged(false);
+ // Call the callback
+ mCb.onTaskViewFocusChanged(this, false);
+ invalidate();
+ }
+
+ /**
* Updates the explicitly focused state when the view focus changes.
*/
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (!gainFocus) {
- mIsFocused = false;
- if (mFocusAnimationsEnabled) {
- // Un-focus the header bar
- mHeaderView.onTaskViewFocusChanged(false);
- }
- // Update the thumbnail alpha with the focus
- mThumbnailView.onFocusChanged(false);
- // Call the callback
- mCb.onTaskViewFocusChanged(this, false);
- invalidate();
+ unsetFocusedTask();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index d39f64eec5d2..1743433a858e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -49,7 +49,7 @@ import com.android.systemui.recents.model.Task;
/* The task bar view */
-class TaskViewHeader extends FrameLayout {
+public class TaskViewHeader extends FrameLayout {
RecentsConfiguration mConfig;
@@ -156,8 +156,11 @@ class TaskViewHeader extends FrameLayout {
// Draw the highlight at the top edge (but put the bottom edge just out of view)
float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
float radius = mConfig.taskViewRoundedCornerRadiusPx;
+ int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+ canvas.restoreToCount(count);
}
}
@@ -178,7 +181,7 @@ class TaskViewHeader extends FrameLayout {
}
/** Binds the bar view to the task */
- void rebindToTask(Task t) {
+ public void rebindToTask(Task t) {
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
if (t.activityIcon != null) {
@@ -212,51 +215,6 @@ class TaskViewHeader extends FrameLayout {
mApplicationIcon.setImageDrawable(null);
}
- /** Prepares this task view for the enter-recents animations. This is called earlier in the
- * first layout because the actual animation into recents may take a long time. */
- void prepareEnterRecentsAnimation() {
- setVisibility(View.INVISIBLE);
- }
-
- /** Animates this task bar as it enters recents */
- void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
- // Animate the task bar of the first task view
- setVisibility(View.VISIBLE);
- setAlpha(0f);
- animate()
- .alpha(1f)
- .setStartDelay(delay)
- .setInterpolator(mConfig.linearOutSlowInInterpolator)
- .setDuration(mConfig.taskBarEnterAnimDuration)
- .withEndAction(postAnimRunnable)
- .withLayer()
- .start();
- }
-
- /** Animates this task bar as it exits recents */
- void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable,
- boolean isFocused) {
- if (isFocused) {
- onTaskViewFocusChanged(false);
- }
-
- // Animate the task bar out of the first task view
- animate()
- .alpha(0f)
- .setStartDelay(0)
- .setInterpolator(mConfig.linearOutSlowInInterpolator)
- .setDuration(mConfig.taskBarExitAnimDuration)
- .withStartAction(preAnimRunnable)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- post(postAnimRunnable);
- }
- })
- .withLayer()
- .start();
- }
-
/** Animates this task bar dismiss button when launching a task. */
void startLaunchTaskDismissAnimation() {
if (mDismissButton.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index f223bf3a990f..fe369879ad16 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -64,25 +64,10 @@ public class TaskViewThumbnail extends FixedSizeImageView {
setClipBounds(mClipRect);
}
- /** Convenience method to enable task bar clipping as a runnable. */
- Runnable enableTaskBarClipAsRunnable(final View taskBar) {
- return new Runnable() {
- @Override
- public void run() {
- enableTaskBarClip(taskBar);
- }
- };
- }
-
/** Disables the task bar clipping. */
- Runnable disableTaskBarClipAsRunnable() {
- return new Runnable() {
- @Override
- public void run() {
- mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
- setClipBounds(mClipRect);
- }
- };
+ void disableTaskBarClip() {
+ mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ setClipBounds(mClipRect);
}
/** Binds the thumbnail view to the screenshot. */
@@ -140,8 +125,8 @@ public class TaskViewThumbnail extends FixedSizeImageView {
}
/** Animates this task thumbnail as it exits recents */
- void startLaunchTaskAnimation() {
- startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null);
+ void startLaunchTaskAnimation(Runnable postAnimRunnable) {
+ startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
}
/** Animates the thumbnail alpha. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 0ddef48ae450..8b50a3673f91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
@@ -32,16 +31,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
@@ -579,7 +574,7 @@ public abstract class BaseStatusBar extends SystemUI implements
}
- protected void applyLegacyRowBackground(StatusBarNotification sbn,
+ protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
NotificationData.Entry entry) {
int version = 0;
try {
@@ -602,6 +597,14 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.row.setTintColor(color);
}
}
+
+ if (entry.icon != null) {
+ if (version >= Build.VERSION_CODES.L) {
+ entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
+ } else {
+ entry.icon.setColorFilter(null);
+ }
+ }
}
public boolean isMediaNotification(NotificationData.Entry entry) {
@@ -1250,7 +1253,7 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.expandedPublic = publicViewLocal;
entry.setBigContentView(bigContentViewLocal);
- applyLegacyRowBackground(sbn, entry);
+ applyColorsAndBackgrounds(sbn, entry);
// Restore previous flags.
if (hasUserChangedExpansion) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 50ddeb351bf2..f3930ba14014 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -79,6 +79,7 @@ public final class NavigationBarTransitions extends BarTransitions {
setKeyButtonViewQuiescentAlpha(mView.getHomeButton(), alpha, animate);
setKeyButtonViewQuiescentAlpha(mView.getRecentsButton(), alpha, animate);
setKeyButtonViewQuiescentAlpha(mView.getMenuButton(), alpha, animate);
+ setKeyButtonViewQuiescentAlpha(mView.getImeSwitchButton(), alpha, animate);
applyBackButtonQuiescentAlpha(mode, animate);
@@ -96,6 +97,7 @@ public final class NavigationBarTransitions extends BarTransitions {
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getHomeButton());
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getRecentsButton());
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getMenuButton());
+ backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getImeSwitchButton());
if (backAlpha > 0) {
setKeyButtonViewQuiescentAlpha(mView.getBackButton(), backAlpha, animate);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index c5f830358cee..b633453e7e59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -37,7 +37,7 @@ public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnG
public NavigationBarViewTaskSwitchHelper(Context context) {
ViewConfiguration configuration = ViewConfiguration.get(context);
- mScrollTouchSlop = configuration.getScaledTouchSlop();
+ mScrollTouchSlop = 4 * configuration.getScaledTouchSlop();
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mTaskSwitcherDetector = new GestureDetector(context, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e1beb0899052..387abc319335 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -58,7 +58,7 @@ public class NotificationPanelView extends PanelView implements
private static final int CAP_HEIGHT = 1456;
private static final int FONT_HEIGHT = 2163;
- private static final float HEADER_RUBBERBAND_FACTOR = 2.15f;
+ private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
private KeyguardAffordanceHelper mAfforanceHelper;
@@ -1665,7 +1665,7 @@ public class NotificationPanelView extends PanelView implements
@Override
protected boolean fullyExpandedClearAllVisible() {
return mNotificationStackScroller.isDismissViewNotGone()
- && mNotificationStackScroller.isScrolledToBottom();
+ && mNotificationStackScroller.isScrolledToBottom() && !mTwoFingerQsExpand;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 68a02cff4f63..82efd1d65c19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2150,7 +2150,15 @@ public class NotificationStackScrollLayout extends ViewGroup
}
public int getDismissViewHeight() {
- return mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+ int height = mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+
+ // Hack: Accommodate for additional distance when we only have one notification and the
+ // dismiss all button.
+ if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
+ && getFirstChildNotGone() instanceof ActivatableNotificationView) {
+ height += mCollapseSecondCardPadding;
+ }
+ return height;
}
public float getBottomMostNotificationBottom() {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index b1f19540060c..4e2f52c5e5b7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -124,6 +124,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// when that accessibility services are bound.
private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
+ private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
+
private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
"registerUiTestAutomationService";
@@ -1367,6 +1369,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (mWindowsForAccessibilityCallback != null) {
mWindowsForAccessibilityCallback = null;
mWindowManagerService.setWindowsForAccessibilityCallback(null);
+ // Drop all windows we know about.
+ mSecurityPolicy.clearWindowsLocked();
}
}
@@ -1631,16 +1635,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
pw.println("}]");
pw.println();
}
- final int windowCount = mSecurityPolicy.mWindows.size();
- for (int j = 0; j < windowCount; j++) {
- if (j > 0) {
- pw.append(',');
- pw.println();
+ if (mSecurityPolicy.mWindows != null) {
+ final int windowCount = mSecurityPolicy.mWindows.size();
+ for (int j = 0; j < windowCount; j++) {
+ if (j > 0) {
+ pw.append(',');
+ pw.println();
+ }
+ pw.append("Window[");
+ AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j);
+ pw.append(window.toString());
+ pw.append(']');
}
- pw.append("Window[");
- AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j);
- pw.append(window.toString());
- pw.append(']');
}
}
}
@@ -1821,6 +1827,39 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return -1;
}
+ private void ensureWindowsAvailableTimed() {
+ synchronized (mLock) {
+ if (mSecurityPolicy.mWindows != null) {
+ return;
+ }
+ // If we have no registered callback, update the state we
+ // we may have to register one but it didn't happen yet.
+ if (mWindowsForAccessibilityCallback == null) {
+ UserState userState = getCurrentUserStateLocked();
+ onUserStateChangedLocked(userState);
+ }
+ // We have no windows but do not care about them, done.
+ if (mWindowsForAccessibilityCallback == null) {
+ return;
+ }
+
+ // Wait for the windows with a timeout.
+ final long startMillis = SystemClock.uptimeMillis();
+ while (mSecurityPolicy.mWindows == null) {
+ final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+ final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
+ if (remainMillis <= 0) {
+ return;
+ }
+ try {
+ mLock.wait(remainMillis);
+ } catch (InterruptedException ie) {
+ /* ignore */
+ }
+ }
+ }
+ }
+
/**
* This class represents an accessibility service. It stores all per service
* data required for the service management, provides API for starting/stopping the
@@ -1876,9 +1915,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher();
- final SparseArray<AccessibilityWindowInfo> mIntrospectedWindows =
- new SparseArray<>();
-
boolean mWasConnectedAndDied;
// Handler only for dispatching accessibility events since we use event
@@ -1946,10 +1982,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
& AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
mRetrieveInteractiveWindows = (info.flags
& AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
-
- if (!mRetrieveInteractiveWindows) {
- clearIntrospectedWindows();
- }
}
/**
@@ -2065,6 +2097,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public List<AccessibilityWindowInfo> getWindows() {
+ ensureWindowsAvailableTimed();
synchronized (mLock) {
// We treat calls from a profile as if made by its perent as profiles
// share the accessibility state of the parent. The call below
@@ -2087,7 +2120,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityWindowInfo windowClone =
AccessibilityWindowInfo.obtain(window);
windowClone.setConnectionId(mId);
- mIntrospectedWindows.put(window.getId(), windowClone);
windows.add(windowClone);
}
return windows;
@@ -2096,6 +2128,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public AccessibilityWindowInfo getWindow(int windowId) {
+ ensureWindowsAvailableTimed();
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
@@ -2115,7 +2148,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (window != null) {
AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
windowClone.setConnectionId(mId);
- mIntrospectedWindows.put(windowId, windowClone);
return windowClone;
}
return null;
@@ -2607,19 +2639,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
public void notifyClearAccessibilityNodeInfoCache() {
- clearIntrospectedWindows();
mInvocationHandler.sendEmptyMessage(
InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
}
- private void clearIntrospectedWindows() {
- final int windowCount = mIntrospectedWindows.size();
- for (int i = windowCount - 1; i >= 0; i--) {
- mIntrospectedWindows.valueAt(i).recycle();
- mIntrospectedWindows.removeAt(i);
- }
- }
-
private void notifyGestureInternal(int gestureId) {
final IAccessibilityServiceClient listener;
synchronized (mLock) {
@@ -2955,6 +2978,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// Let the policy update the focused and active windows.
mSecurityPolicy.updateWindowsLocked(reportedWindows);
+
+ // Someone may be waiting for the windows - advertise it.
+ mLock.notifyAll();
}
}
@@ -3130,7 +3156,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
| AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
| AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
- public final List<AccessibilityWindowInfo> mWindows = new ArrayList<>();
+ public List<AccessibilityWindowInfo> mWindows;
public int mActiveWindowId = INVALID_WINDOW_ID;
public int mFocusedWindowId = INVALID_WINDOW_ID;
@@ -3185,7 +3211,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ public void clearWindowsLocked() {
+ List<AccessibilityWindowInfo> windows = Collections.emptyList();
+ updateWindowsLocked(windows);
+ mWindows = null;
+ }
+
public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
+ if (mWindows == null) {
+ mWindows = new ArrayList<>();
+ }
+
final int oldWindowCount = mWindows.size();
for (int i = oldWindowCount - 1; i >= 0; i--) {
mWindows.remove(i).recycle();
@@ -3231,6 +3267,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (window.getId() == mActiveWindowId) {
window.setActive(true);
}
+ if (window.getId() == mAccessibilityFocusedWindowId) {
+ window.setAccessibilityFocused(true);
+ }
}
}
@@ -3298,7 +3337,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (mAccessibilityFocusedWindowId != windowId) {
mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
mAccessibilityFocusedWindowId, 0).sendToTarget();
- mAccessibilityFocusedWindowId = windowId;
+ mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
mAccessibilityFocusNodeId = nodeId;
}
}
@@ -3354,11 +3393,28 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void setActiveWindowLocked(int windowId) {
if (mActiveWindowId != windowId) {
mActiveWindowId = windowId;
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = mWindows.get(i);
- window.setActive(window.getId() == windowId);
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = mWindows.get(i);
+ window.setActive(window.getId() == windowId);
+ }
+ }
+ notifyWindowsChanged();
+ }
+ }
+
+ private void setAccessibilityFocusedWindowLocked(int windowId) {
+ if (mAccessibilityFocusedWindowId != windowId) {
+ mAccessibilityFocusedWindowId = windowId;
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = mWindows.get(i);
+ window.setAccessibilityFocused(window.getId() == windowId);
+ }
}
+
notifyWindowsChanged();
}
}
@@ -3444,11 +3500,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
private AccessibilityWindowInfo findWindowById(int windowId) {
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == windowId) {
- return window;
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == windowId) {
+ return window;
+ }
}
}
return null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e794b83c281f..f315b74ed157 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7746,6 +7746,12 @@ public final class ActivityManagerService extends ActivityManagerNative
continue;
}
}
+ if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
+ if (tr.stack != null && tr.stack.isHomeStack()) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, home stack task: " + tr);
+ continue;
+ }
+ }
if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
// Don't include auto remove tasks that are finished or finishing.
if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, auto-remove without activity: "
@@ -17554,7 +17560,7 @@ public final class ActivityManagerService extends ActivityManagerNative
d.show();
}
- private boolean startUser(final int userId, boolean foreground) {
+ private boolean startUser(final int userId, final boolean foreground) {
if (checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: switchUser() from pid="
@@ -17678,7 +17684,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
- userInitialized(uss, userId);
+ onUserInitialized(uss, foreground, oldUserId, userId);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
true, false, MY_PID, Process.SYSTEM_UID,
@@ -17690,15 +17696,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (foreground) {
- boolean homeInFront = mStackSupervisor.switchUserLocked(userId, uss);
- if (homeInFront) {
- startHomeActivityLocked(userId);
- } else {
- mStackSupervisor.resumeTopActivitiesLocked();
+ if (!uss.initializing) {
+ moveUserToForeground(uss, oldUserId, userId);
}
- EventLogTags.writeAmSwitchUser(userId);
- getUserManagerLocked().userForeground(userId);
- sendUserSwitchBroadcastsLocked(oldUserId, userId);
} else {
mStackSupervisor.startBackgroundUserLocked(userId, uss);
}
@@ -17824,10 +17824,28 @@ public final class ActivityManagerService extends ActivityManagerNative
oldUserId, newUserId, uss));
}
- void userInitialized(UserStartedState uss, int newUserId) {
+ void onUserInitialized(UserStartedState uss, boolean foreground, int oldUserId, int newUserId) {
+ synchronized (this) {
+ if (foreground) {
+ moveUserToForeground(uss, oldUserId, newUserId);
+ }
+ }
+
completeSwitchAndInitalize(uss, newUserId, true, false);
}
+ void moveUserToForeground(UserStartedState uss, int oldUserId, int newUserId) {
+ boolean homeInFront = mStackSupervisor.switchUserLocked(newUserId, uss);
+ if (homeInFront) {
+ startHomeActivityLocked(newUserId);
+ } else {
+ mStackSupervisor.resumeTopActivitiesLocked();
+ }
+ EventLogTags.writeAmSwitchUser(newUserId);
+ getUserManagerLocked().userForeground(newUserId);
+ sendUserSwitchBroadcastsLocked(oldUserId, newUserId);
+ }
+
void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
completeSwitchAndInitalize(uss, newUserId, false, true);
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fcbe71ebb30b..39b6375dc4b9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -723,6 +723,22 @@ final class ActivityRecord {
+ pendingOptions.getThumbnail().getHeight()));
}
break;
+ case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
+ pendingOptions.getThumbnail(),
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getOnAnimationStartListener(),
+ (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX()
+ + pendingOptions.getThumbnail().getWidth(),
+ pendingOptions.getStartY()
+ + pendingOptions.getThumbnail().getHeight()));
+ }
+ break;
default:
Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
break;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8aec39232248..bd8501c430b9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2430,7 +2430,6 @@ public final class ActivityStackSupervisor implements DisplayListener {
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
}
- mWindowManager.addTask(taskId, stackId, false);
}
resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 949019ed1c41..9e169d9f6c18 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -152,7 +152,10 @@ public class SyncManager {
*/
private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
- private static final int INITIALIZATION_UNBIND_DELAY_MS = 5000;
+ /**
+ * How long to wait before considering an active sync to have timed-out, and cancelling it.
+ */
+ private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000; // 30 mins.
private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -851,6 +854,31 @@ public class SyncManager {
mSyncHandler.sendMessage(msg);
}
+ /**
+ * Post a delayed message to the handler that will result in the cancellation of the provided
+ * running sync's context.
+ */
+ private void postSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "posting MESSAGE_SYNC_EXPIRED in " +
+ (ACTIVE_SYNC_TIMEOUT_MILLIS/1000) + "s");
+ }
+ Message msg = mSyncHandler.obtainMessage();
+ msg.what = SyncHandler.MESSAGE_SYNC_EXPIRED;
+ msg.obj = activeSyncContext;
+ mSyncHandler.sendMessageDelayed(msg, ACTIVE_SYNC_TIMEOUT_MILLIS);
+ }
+
+ /**
+ * Remove any time-outs previously posted for the provided active sync.
+ */
+ private void removeSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "removing all MESSAGE_SYNC_EXPIRED for " + activeSyncContext.toString());
+ }
+ mSyncHandler.removeMessages(SyncHandler.MESSAGE_SYNC_EXPIRED, activeSyncContext);
+ }
+
class SyncHandlerMessagePayload {
public final ActiveSyncContext activeSyncContext;
public final SyncResult syncResult;
@@ -1902,6 +1930,8 @@ public class SyncManager {
private static final int MESSAGE_SERVICE_CONNECTED = 4;
private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
private static final int MESSAGE_CANCEL = 6;
+ /** Posted delayed in order to expire syncs that are long-running. */
+ private static final int MESSAGE_SYNC_EXPIRED = 7;
public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
private Long mAlarmScheduleTime = null;
@@ -2000,10 +2030,21 @@ public class SyncManager {
// to also take into account the periodic syncs.
earliestFuturePollTime = scheduleReadyPeriodicSyncs();
switch (msg.what) {
+ case SyncHandler.MESSAGE_SYNC_EXPIRED:
+ ActiveSyncContext expiredContext = (ActiveSyncContext) msg.obj;
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_EXPIRED: expiring "
+ + expiredContext);
+ }
+ cancelActiveSync(expiredContext.mSyncOperation.target,
+ expiredContext.mSyncOperation.extras);
+ nextPendingSyncTime = maybeStartNextSyncLocked();
+ break;
+
case SyncHandler.MESSAGE_CANCEL: {
SyncStorageEngine.EndPoint payload = (SyncStorageEngine.EndPoint) msg.obj;
Bundle extras = msg.peekData();
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CANCEL: "
+ payload + " bundle: " + extras);
}
@@ -2653,6 +2694,13 @@ public class SyncManager {
new ActiveSyncContext(op, insertStartSyncEvent(op), targetUid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
+ if (!activeSyncContext.mSyncOperation.isInitialization() &&
+ !activeSyncContext.mSyncOperation.isExpedited() &&
+ !activeSyncContext.mSyncOperation.isManual() &&
+ !activeSyncContext.mSyncOperation.isIgnoreSettings()) {
+ // Post message to expire this sync if it runs for too long.
+ postSyncExpiryMessage(activeSyncContext);
+ }
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
}
@@ -2757,9 +2805,7 @@ public class SyncManager {
} else {
Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
// the operation failed so increase the backoff time
- if (!syncResult.syncAlreadyInProgress) {
- increaseBackoffSetting(syncOperation);
- }
+ increaseBackoffSetting(syncOperation);
// reschedule the sync if so indicated by the syncResult
maybeRescheduleSync(syncResult, syncOperation);
historyMessage = ContentResolver.syncErrorToString(
@@ -2768,7 +2814,6 @@ public class SyncManager {
downstreamActivity = 0;
upstreamActivity = 0;
}
-
setDelayUntilTime(syncOperation, syncResult.delayUntil);
} else {
if (isLoggable) {
@@ -2794,7 +2839,6 @@ public class SyncManager {
stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
upstreamActivity, downstreamActivity, elapsedTime);
-
// Check for full-resync and schedule it after closing off the last sync.
if (info.target_provider) {
if (syncResult != null && syncResult.tooManyDeletions) {
@@ -2833,6 +2877,7 @@ public class SyncManager {
mActiveSyncContexts.remove(activeSyncContext);
mSyncStorageEngine.removeActiveSync(activeSyncContext.mSyncInfo,
activeSyncContext.mSyncOperation.target.userId);
+ removeSyncExpiryMessage(activeSyncContext);
}
/**
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 9a4abce7f4c8..35827cc59f9b 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -273,6 +273,14 @@ public class SyncOperation implements Comparable {
return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
}
+ public boolean isManual() {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+ }
+
+ public boolean isIgnoreSettings() {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
+ }
+
/** Changed in V3. */
public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index d1e03ec7510c..694669c09125 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -61,17 +61,7 @@ public final class Installer extends SystemService {
return -1;
}
- StringBuilder builder = new StringBuilder("patchoat");
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
- builder.append(uid);
- builder.append(isPublic ? " 1" : " 0");
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
+ return mInstaller.patchoat(apkPath, uid, isPublic, pkgName, instructionSet);
}
public int patchoat(String apkPath, int uid, boolean isPublic, String instructionSet) {
@@ -93,23 +83,13 @@ public final class Installer extends SystemService {
}
public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
- String instructionSet) {
+ String instructionSet, boolean vmSafeMode) {
if (!isValidInstructionSet(instructionSet)) {
Slog.e(TAG, "Invalid instruction set: " + instructionSet);
return -1;
}
- StringBuilder builder = new StringBuilder("dexopt");
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
- builder.append(uid);
- builder.append(isPublic ? " 1" : " 0");
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
+ return mInstaller.dexopt(apkPath, uid, isPublic, pkgName, instructionSet, vmSafeMode);
}
public int idmap(String targetApkPath, String overlayApkPath, int uid) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f06992a23bbb..ac0f48917d1f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4634,6 +4634,8 @@ public class PackageManagerService extends IPackageManager.Stub {
return DEX_OPT_SKIPPED;
}
+ final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
+
final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
boolean performedDexOpt = false;
// There are three basic cases here:
@@ -4657,10 +4659,11 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.packageName, dexCodeInstructionSet, defer);
if (forceDex || (!defer && isDexOptNeeded == DexFile.DEXOPT_NEEDED)) {
Log.i(TAG, "Running dexopt on: " + path + " pkg="
- + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet);
+ + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ + " vmSafeMode=" + vmSafeMode);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
- pkg.packageName, dexCodeInstructionSet);
+ pkg.packageName, dexCodeInstructionSet, vmSafeMode);
if (ret < 0) {
// Don't bother running dexopt again if we failed, it will probably
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 4dc76de6e119..aabb8f785067 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -19,7 +19,6 @@ package com.android.server.wm;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
@@ -111,11 +110,14 @@ public class AppTransition implements Dump {
* The new window will show briefly and then be gone. */
public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
+ /** Fraction of animation at which the recents thumbnail stays completely transparent */
+ private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f;
/** Fraction of animation at which the recents thumbnail becomes completely transparent */
- private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
+ private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.3f;
private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
- private static final int THUMBNAIL_APP_TRANSITION_DURATION = 275;
+ private static final int THUMBNAIL_APP_TRANSITION_DURATION = 300;
+ private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 325;
private final Context mContext;
private final Handler mH;
@@ -127,6 +129,8 @@ public class AppTransition implements Dump {
private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
+ private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
+ private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
// These are the possible states for the enter/exit activities during a thumbnail transition
@@ -146,6 +150,7 @@ public class AppTransition implements Dump {
private int mNextAppTransitionStartY;
private int mNextAppTransitionStartWidth;
private int mNextAppTransitionStartHeight;
+ private Rect mNextAppTransitionInsets = new Rect();
private Rect mTmpFromClipRect = new Rect();
private Rect mTmpToClipRect = new Rect();
@@ -158,7 +163,8 @@ public class AppTransition implements Dump {
private final int mConfigShortAnimTime;
private final Interpolator mDecelerateInterpolator;
- private final Interpolator mThumbnailFadeoutInterpolator;
+ private final Interpolator mThumbnailFadeInInterpolator;
+ private final Interpolator mThumbnailFadeOutInterpolator;
private final Interpolator mThumbnailFastOutSlowInInterpolator;
private int mCurrentUserId = 0;
@@ -172,14 +178,25 @@ public class AppTransition implements Dump {
com.android.internal.R.interpolator.decelerate_cubic);
mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
- mThumbnailFadeoutInterpolator = new Interpolator() {
+ mThumbnailFadeInInterpolator = new Interpolator() {
+ @Override
+ public float getInterpolation(float input) {
+ // Linear response for first fraction, then complete after that.
+ if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) {
+ return 0f;
+ }
+ return (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) /
+ (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION);
+ }
+ };
+ mThumbnailFadeOutInterpolator = new Interpolator() {
@Override
public float getInterpolation(float input) {
// Linear response for first fraction, then complete after that.
if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
}
- return 1.0f;
+ return 1f;
}
};
}
@@ -233,9 +250,23 @@ public class AppTransition implements Dump {
return mNextAppTransitionThumbnail;
}
- void getStartingPoint(Point outPoint) {
- outPoint.x = mNextAppTransitionStartX;
- outPoint.y = mNextAppTransitionStartY;
+ /** Returns whether the next thumbnail transition is aspect scaled up. */
+ boolean isNextThumbnailTransitionAspectScaled() {
+ return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+ mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+ }
+
+ /** Returns whether the next thumbnail transition is scaling up. */
+ boolean isNextThumbnailTransitionScaleUp() {
+ return mNextAppTransitionScaleUp;
+ }
+
+ int getStartingX() {
+ return mNextAppTransitionStartX;
+ }
+
+ int getStartingY() {
+ return mNextAppTransitionStartY;
}
void prepare() {
@@ -372,7 +403,7 @@ public class AppTransition implements Dump {
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
- alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
@@ -417,7 +448,9 @@ public class AppTransition implements Dump {
*/
Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
int duration, Interpolator interpolator) {
- a.setDuration(duration);
+ if (duration > 0) {
+ a.setDuration(duration);
+ }
a.setFillAfter(true);
a.setInterpolator(interpolator);
a.initialize(appWidth, appHeight, appWidth, appHeight);
@@ -468,50 +501,73 @@ public class AppTransition implements Dump {
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
* when a thumbnail is specified with the activity options.
*/
- Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+ Animation createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight,
+ int deviceWidth, int transit) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+ float scaleW = deviceWidth / thumbWidth;
+ float unscaledWidth = deviceWidth;
+ float unscaledHeight = thumbHeight * scaleW;
+ float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
if (mNextAppTransitionScaleUp) {
- // Animation for the thumbnail zooming from its initial size to the full screen
- float scaleW = appWidth / thumbWidth;
- float scaleH = appHeight / thumbHeight;
- Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
- scale.setInterpolator(mDecelerateInterpolator);
-
+ // Animation up from the thumbnail to the full screen
+ Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
+ mNextAppTransitionStartX + (thumbWidth / 2f),
+ mNextAppTransitionStartY + (thumbHeight / 2f));
+ scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1, 0);
- alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+ alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+ Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY +
+ mNextAppTransitionInsets.top);
+ translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
set.addAnimation(alpha);
+ set.addAnimation(translate);
a = set;
} else {
- // Animation for the thumbnail zooming down from the full screen to its final size
- float scaleW = appWidth / thumbWidth;
- float scaleH = appHeight / thumbHeight;
- a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
- }
+ // Animation down from the full screen to the thumbnail
+ Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
+ mNextAppTransitionStartX + (thumbWidth / 2f),
+ mNextAppTransitionStartY + (thumbHeight / 2f));
+ scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
+ Animation alpha = new AlphaAnimation(0f, 1f);
+ alpha.setInterpolator(mThumbnailFadeInInterpolator);
+ alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+ Animation translate = new TranslateAnimation(0, 0, -unscaledStartY +
+ mNextAppTransitionInsets.top, 0);
+ translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
- return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+ // This AnimationSet uses the Interpolators assigned above.
+ AnimationSet set = new AnimationSet(false);
+ set.addAnimation(scale);
+ set.addAnimation(alpha);
+ set.addAnimation(translate);
+ a = set;
+
+ }
+ return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0,
+ mThumbnailFastOutSlowInInterpolator);
}
/**
* This alternate animation is created when we are doing a thumbnail transition, for the
* activity that is leaving, and the activity that is entering.
*/
- Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
- int appHeight, int orientation, int transit,
- Rect containingFrame, Rect contentInsets,
- boolean isFullScreen) {
+ Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
+ int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
+ Rect contentInsets, boolean isFullScreen) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -524,7 +580,7 @@ public class AppTransition implements Dump {
switch (thumbTransitState) {
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
- // Entering app scales up with the thumbnail
+ // App window scaling up to become full screen
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
@@ -550,16 +606,15 @@ public class AppTransition implements Dump {
mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
mTmpToClipRect.set(containingFrame);
}
+ mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
- Animation alphaAnim = new AlphaAnimation(1, 1);
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
AnimationSet set = new AnimationSet(true);
- set.addAnimation(alphaAnim);
set.addAnimation(clipAnim);
set.addAnimation(scaleAnim);
set.addAnimation(translateAnim);
@@ -567,26 +622,29 @@ public class AppTransition implements Dump {
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
- // Exiting app while the thumbnail is scaling up should fade
+ // Previous app window during the scale up
if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
- // Fade out while bringing up selected activity. This keeps the
- // current activity from showing through a launching wallpaper
+ // Fade out the source activity if we are animating to a wallpaper
// activity.
a = new AlphaAnimation(1, 0);
} else {
- // noop animation
a = new AlphaAnimation(1, 1);
}
break;
}
case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
- // Entering the other app, it should just be visible while we scale the thumbnail
- // down above it
- a = new AlphaAnimation(1, 1);
+ // Target app window during the scale down
+ if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+ // Fade in the destination activity if we are animating from a wallpaper
+ // activity.
+ a = new AlphaAnimation(0, 1);
+ } else {
+ a = new AlphaAnimation(1, 1);
+ }
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
- // Exiting the current app, the app should scale down with the thumbnail
+ // App window scaling down from full screen
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
@@ -612,16 +670,15 @@ public class AppTransition implements Dump {
}
mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
}
+ mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
- Animation alphaAnim = new AlphaAnimation(1, 1);
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
AnimationSet set = new AnimationSet(true);
- set.addAnimation(alphaAnim);
set.addAnimation(clipAnim);
set.addAnimation(scaleAnim);
set.addAnimation(translateAnim);
@@ -639,6 +696,46 @@ public class AppTransition implements Dump {
}
/**
+ * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
+ * when a thumbnail is specified with the activity options.
+ */
+ Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+ Animation a;
+ final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
+ final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+
+ if (mNextAppTransitionScaleUp) {
+ // Animation for the thumbnail zooming from its initial size to the full screen
+ float scaleW = appWidth / thumbWidth;
+ float scaleH = appHeight / thumbHeight;
+ Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ scale.setInterpolator(mDecelerateInterpolator);
+
+ Animation alpha = new AlphaAnimation(1, 0);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+
+ // This AnimationSet uses the Interpolators assigned above.
+ AnimationSet set = new AnimationSet(false);
+ set.addAnimation(scale);
+ set.addAnimation(alpha);
+ a = set;
+ } else {
+ // Animation for the thumbnail zooming down from the full screen to its final size
+ float scaleW = appWidth / thumbWidth;
+ float scaleH = appHeight / thumbHeight;
+ a = new ScaleAnimation(scaleW, 1, scaleH, 1,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ }
+
+ return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+ }
+
+ /**
* This animation is created when we are doing a thumbnail transition, for the activity that is
* leaving, and the activity that is entering.
*/
@@ -747,12 +844,26 @@ public class AppTransition implements Dump {
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
- a = createAlternateThumbnailEnterExitAnimationLocked(
+ a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
+ appWidth, appHeight, transit);
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
+ String animName = mNextAppTransitionScaleUp ?
+ "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+ Slog.v(TAG, "applyAnimation:"
+ + " anim=" + a + " nextAppTransition=" + animName
+ + " transit=" + transit + " isEntrance=" + enter
+ + " Callers=" + Debug.getCallers(3));
+ }
+ } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+ mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
+ mNextAppTransitionScaleUp =
+ (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
+ a = createAspectScaledThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
transit, containingFrame, contentInsets, isFullScreen);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
- "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+ "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
Slog.v(TAG, "applyAnimation:"
+ " anim=" + a + " nextAppTransition=" + animName
+ " transit=" + transit + " isEntrance=" + enter
@@ -881,6 +992,23 @@ public class AppTransition implements Dump {
}
}
+ void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
+ IRemoteCallback startedCallback, boolean scaleUp) {
+ if (isTransitionSet()) {
+ mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
+ : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionScaleUp = scaleUp;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ postAnimationCallback();
+ mNextAppTransitionCallback = startedCallback;
+ } else {
+ postAnimationCallback();
+ }
+ }
+
@Override
public String toString() {
return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
@@ -966,6 +1094,10 @@ public class AppTransition implements Dump {
return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+ return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
+ return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
default:
return "unknown type=" + mNextAppTransitionType;
}
@@ -998,6 +1130,8 @@ public class AppTransition implements Dump {
break;
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
pw.print(" mNextAppTransitionThumbnail=");
pw.print(mNextAppTransitionThumbnail);
pw.print(" mNextAppTransitionStartX=");
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 5b05d534d1e6..ef742057f1b8 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -64,8 +64,17 @@ public class AppWindowAnimator {
int thumbnailX;
int thumbnailY;
int thumbnailLayer;
+ int thumbnailForceAboveLayer;
Animation thumbnailAnimation;
final Transformation thumbnailTransformation = new Transformation();
+ // This flag indicates that the destruction of the thumbnail surface is synchronized with
+ // another animation, so do not pre-emptively destroy the thumbnail surface when the animation
+ // completes
+ boolean deferThumbnailDestruction;
+ // This is the thumbnail surface that has been bestowed upon this animator, and when the
+ // surface for this animator's animation is complete, we will destroy the thumbnail surface
+ // as well. Do not animate or do anything with this surface.
+ SurfaceControl deferredThumbnail;
/** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
@@ -121,7 +130,9 @@ public class AppWindowAnimator {
animation = null;
animating = true;
}
- clearThumbnail();
+ if (!deferThumbnailDestruction) {
+ clearThumbnail();
+ }
if (mAppToken.deferClearAllDrawn) {
mAppToken.allDrawn = false;
mAppToken.deferClearAllDrawn = false;
@@ -135,6 +146,13 @@ public class AppWindowAnimator {
}
}
+ public void clearDeferredThumbnail() {
+ if (deferredThumbnail != null) {
+ deferredThumbnail.destroy();
+ deferredThumbnail = null;
+ }
+ }
+
void updateLayers() {
final int N = mAppToken.allAppWindows.size();
final int adj = animLayerAdjustment;
@@ -184,10 +202,14 @@ public class AppWindowAnimator {
+ "][" + tmpFloats[Matrix.MSKEW_X]
+ "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
thumbnail.setAlpha(thumbnailTransformation.getAlpha());
- // The thumbnail is layered below the window immediately above this
- // token's anim layer.
- thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
- - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+ if (thumbnailForceAboveLayer > 0) {
+ thumbnail.setLayer(thumbnailForceAboveLayer + 1);
+ } else {
+ // The thumbnail is layered below the window immediately above this
+ // token's anim layer.
+ thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+ - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+ }
thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
}
@@ -202,7 +224,9 @@ public class AppWindowAnimator {
TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
if (!more) {
animation = null;
- clearThumbnail();
+ if (!deferThumbnailDestruction) {
+ clearThumbnail();
+ }
if (WindowManagerService.DEBUG_ANIM) Slog.v(
TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 32f3707bcfaf..e144bdeb43a3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -95,7 +95,6 @@ import android.os.WorkSource;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
-import android.util.FloatMath;
import android.util.Log;
import android.util.SparseArray;
import android.util.Pair;
@@ -4038,6 +4037,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ synchronized(mWindowMap) {
+ mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
+ startY, startedCallback, scaleUp);
+ }
+ }
+
+ @Override
public void executeAppTransition() {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"executeAppTransition()")) {
@@ -8893,7 +8901,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
AppWindowToken topOpeningApp = null;
+ AppWindowToken topClosingApp = null;
int topOpeningLayer = 0;
+ int topClosingLayer = 0;
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
@@ -8901,8 +8911,8 @@ public class WindowManagerService extends IWindowManager.Stub
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
appAnimator.clearThumbnail();
- wtoken.inPendingTransaction = false;
appAnimator.animation = null;
+ wtoken.inPendingTransaction = false;
setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
@@ -8931,10 +8941,11 @@ public class WindowManagerService extends IWindowManager.Stub
NN = mClosingApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mClosingApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
- wtoken.mAppAnimator.clearThumbnail();
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
wtoken.inPendingTransaction = false;
- wtoken.mAppAnimator.animation = null;
setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToHide = false;
@@ -8943,14 +8954,30 @@ public class WindowManagerService extends IWindowManager.Stub
// gotten drawn.
wtoken.allDrawn = true;
wtoken.deferClearAllDrawn = false;
+
+ if (animLp != null) {
+ int layer = -1;
+ for (int j=0; j<wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topClosingApp == null || layer > topClosingLayer) {
+ topClosingApp = wtoken;
+ topClosingLayer = layer;
+ }
+ }
}
- boolean useAlternateThumbnailAnimation = true;
- AppWindowAnimator appAnimator =
- topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
+ AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
+ topOpeningApp.mAppAnimator;
+ AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+ topClosingApp.mAppAnimator;
Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
- if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
- && appAnimator != null && appAnimator.animation != null) {
+ if (nextAppTransitionThumbnail != null
+ && openingAppAnimator != null && openingAppAnimator.animation != null &&
+ nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
// This thumbnail animation is very special, we need to have
// an extra surface with the thumbnail included with the animation.
Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
@@ -8959,34 +8986,61 @@ public class WindowManagerService extends IWindowManager.Stub
// TODO(multi-display): support other displays
final DisplayContent displayContent = getDefaultDisplayContentLocked();
final Display display = displayContent.getDisplay();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+ // Create a new surface for the thumbnail
SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
- "thumbnail anim",
- dirty.width(), dirty.height(),
+ "thumbnail anim", dirty.width(), dirty.height(),
PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
surfaceControl.setLayerStack(display.getLayerStack());
- appAnimator.thumbnail = surfaceControl;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ }
+
+ // Draw the thumbnail onto the surface
Surface drawSurface = new Surface();
drawSurface.copyFrom(surfaceControl);
Canvas c = drawSurface.lockCanvas(dirty);
c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
drawSurface.unlockCanvasAndPost(c);
drawSurface.release();
- appAnimator.thumbnailLayer = topOpeningLayer;
- DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
- Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
- displayInfo.appWidth, displayInfo.appHeight, transit);
- appAnimator.thumbnailAnimation = anim;
+
+ // Get the thumbnail animation
+ Animation anim;
+ if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+ // For the new aspect-scaled transition, we want it to always show
+ // above the animating opening/closing window, and we want to
+ // synchronize its thumbnail surface with the surface for the
+ // open/close animation (only on the way down)
+ anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight,
+ displayInfo.logicalWidth, transit);
+ openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
+ topClosingLayer);
+ openingAppAnimator.deferThumbnailDestruction =
+ !mAppTransition.isNextThumbnailTransitionScaleUp();
+ if (openingAppAnimator.deferThumbnailDestruction) {
+ if (closingAppAnimator != null &&
+ closingAppAnimator.animation != null) {
+ closingAppAnimator.deferredThumbnail = surfaceControl;
+ }
+ }
+ } else {
+ anim = mAppTransition.createThumbnailScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight, transit);
+ }
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
- Point p = new Point();
- mAppTransition.getStartingPoint(p);
- appAnimator.thumbnailX = p.x;
- appAnimator.thumbnailY = p.y;
+
+ openingAppAnimator.thumbnail = surfaceControl;
+ openingAppAnimator.thumbnailLayer = topOpeningLayer;
+ openingAppAnimator.thumbnailAnimation = anim;
+ openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
+ openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
} catch (OutOfResourcesException e) {
Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
+ " h=" + dirty.height(), e);
- appAnimator.clearThumbnail();
+ openingAppAnimator.clearThumbnail();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 7bf090a35b99..38433ae9233b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -902,6 +902,11 @@ class WindowStateAnimator {
mWin.mHasSurface = false;
mDrawState = NO_SURFACE;
}
+
+ // Destroy any deferred thumbnail surfaces
+ if (mAppAnimator != null) {
+ mAppAnimator.clearDeferredThumbnail();
+ }
}
void destroyDeferredSurfaceLocked() {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 5954947fb4a5..85ceefd40f71 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -266,7 +266,7 @@ public class TelephonyIntents {
/**
* Activity Action: Start this activity to invoke the carrier setup app.
- * To filter the intent, see {@link #CATEGORY_MCCMNC_PREFIX}.
+ * The carrier app must be signed using a certificate that matches the UICC access rules.
*
* <p class="note">Callers of this should hold the android.permission.INVOKE_CARRIER_SETUP
* permission.</p>
@@ -274,13 +274,6 @@ public class TelephonyIntents {
public static final String ACTION_CARRIER_SETUP = "android.intent.action.ACTION_CARRIER_SETUP";
/**
- * A <em>prefix</em> for the MCC/MNC filtering used with {@link #ACTION_CARRIER_SETUP}.
- * The MCC/MNC will be concatenated (zero-padded to 3 digits each) to create a final
- * string of the form: {@code android.intent.category.MCCMNC_310260}
- */
- public static final String CATEGORY_MCCMNC_PREFIX = "android.intent.category.MCCMNC_";
-
- /**
* Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
* of the form {@code *#*#<code>#*#*}. The intent will have the data URI:
*
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 66337870feb1..78e360bdb831 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -20,6 +20,7 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.Color;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -199,6 +200,7 @@ public class FrameworkPerfActivity extends Activity
mLocalCheckBox = (CheckBox)findViewById(R.id.local);
mLog = (TextView)findViewById(R.id.log);
+ mLog.setTextColor(Color.RED);
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler");
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index 69a9c7feca99..32a0cd3d4872 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -255,6 +255,8 @@ void applyVersionForCompatibility(ConfigDescription* config) {
!= ResTable_config::SCREENLONG_ANY
|| config->density != ResTable_config::DENSITY_DEFAULT) {
minSdk = SDK_DONUT;
+ } else if ((config->density == ResTable_config::DENSITY_ANY)) {
+ minSdk = SDK_L;
}
if (minSdk > config->sdkVersion) {
@@ -477,6 +479,11 @@ bool parseDensity(const char* name, ResTable_config* out) {
return true;
}
+ if (strcmp(name, "anydpi") == 0) {
+ if (out) out->density = ResTable_config::DENSITY_ANY;
+ return true;
+ }
+
if (strcmp(name, "nodpi") == 0) {
if (out) out->density = ResTable_config::DENSITY_NONE;
return true;
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 1439f14b7fb6..af494618d6ce 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -24,6 +24,7 @@ enum {
SDK_HONEYCOMB_MR2 = 13,
SDK_ICE_CREAM_SANDWICH = 14,
SDK_ICE_CREAM_SANDWICH_MR1 = 15,
+ SDK_L = 21,
};
/*
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index b3946715c9c0..a0f0a08bf95c 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -2488,10 +2488,12 @@ int doPackage(Bundle* bundle)
if (bundle->getCustomPackage() == NULL) {
// Write the R.java file into the appropriate class directory
// e.g. gen/com/foo/app/R.java
- err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
+ err = writeResourceSymbols(bundle, assets, assets->getPackage(), true,
+ bundle->getBuildSharedLibrary());
} else {
const String8 customPkg(bundle->getCustomPackage());
- err = writeResourceSymbols(bundle, assets, customPkg, true);
+ err = writeResourceSymbols(bundle, assets, customPkg, true,
+ bundle->getBuildSharedLibrary());
}
if (err < 0) {
goto bail;
@@ -2505,7 +2507,7 @@ int doPackage(Bundle* bundle)
char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
while (packageString != NULL) {
// Write the R.java file out with the correct package name
- err = writeResourceSymbols(bundle, assets, String8(packageString), true);
+ err = writeResourceSymbols(bundle, assets, String8(packageString), true, false);
if (err < 0) {
goto bail;
}
@@ -2514,11 +2516,11 @@ int doPackage(Bundle* bundle)
libs.unlockBuffer();
}
} else {
- err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
+ err = writeResourceSymbols(bundle, assets, assets->getPackage(), false, false);
if (err < 0) {
goto bail;
}
- err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true);
+ err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true, false);
if (err < 0) {
goto bail;
}
diff --git a/tools/aapt/IndentPrinter.h b/tools/aapt/IndentPrinter.h
new file mode 100644
index 000000000000..6fc94bc927b8
--- /dev/null
+++ b/tools/aapt/IndentPrinter.h
@@ -0,0 +1,63 @@
+#ifndef __INDENT_PRINTER_H
+#define __INDENT_PRINTER_H
+
+class IndentPrinter {
+public:
+ IndentPrinter(FILE* stream, int indentSize=2)
+ : mStream(stream)
+ , mIndentSize(indentSize)
+ , mIndent(0)
+ , mNeedsIndent(true) {
+ }
+
+ void indent(int amount = 1) {
+ mIndent += amount;
+ if (mIndent < 0) {
+ mIndent = 0;
+ }
+ }
+
+ void print(const char* fmt, ...) {
+ doIndent();
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(mStream, fmt, args);
+ va_end(args);
+ }
+
+ void println(const char* fmt, ...) {
+ doIndent();
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(mStream, fmt, args);
+ va_end(args);
+ fputs("\n", mStream);
+ mNeedsIndent = true;
+ }
+
+ void println() {
+ doIndent();
+ fputs("\n", mStream);
+ mNeedsIndent = true;
+ }
+
+private:
+ void doIndent() {
+ if (mNeedsIndent) {
+ int numSpaces = mIndent * mIndentSize;
+ while (numSpaces > 0) {
+ fputs(" ", mStream);
+ numSpaces--;
+ }
+ mNeedsIndent = false;
+ }
+ }
+
+ FILE* mStream;
+ const int mIndentSize;
+ int mIndent;
+ bool mNeedsIndent;
+};
+
+#endif // __INDENT_PRINTER_H
+
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index 34c449687c56..dd40b2011dc8 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -49,7 +49,8 @@ extern android::status_t buildResources(Bundle* bundle,
const sp<AaptAssets>& assets, sp<ApkBuilder>& builder);
extern android::status_t writeResourceSymbols(Bundle* bundle,
- const sp<AaptAssets>& assets, const String8& pkgName, bool includePrivate);
+ const sp<AaptAssets>& assets, const String8& pkgName,
+ bool includePrivate, bool emitCallback);
extern android::status_t writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 1d93b895409a..7979a1ddf7ae 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -3,18 +3,17 @@
//
// Build resource files from raw assets.
//
-#include "Main.h"
#include "AaptAssets.h"
-#include "StringPool.h"
-#include "XMLNode.h"
-#include "ResourceTable.h"
-#include "Images.h"
-
+#include "CacheUpdater.h"
#include "CrunchCache.h"
#include "FileFinder.h"
-#include "CacheUpdater.h"
-
+#include "Images.h"
+#include "IndentPrinter.h"
+#include "Main.h"
+#include "ResourceTable.h"
+#include "StringPool.h"
#include "WorkQueue.h"
+#include "XMLNode.h"
#if HAVE_PRINTF_ZD
# define ZD "%zd"
@@ -1801,6 +1800,112 @@ static String16 getAttributeComment(const sp<AaptAssets>& assets,
return String16();
}
+static void writeResourceLoadedCallback(FILE* fp, int indent) {
+ IndentPrinter p(fp, 4);
+ p.indent(indent);
+ p.println("private static void rewriteIntArrayField(java.lang.reflect.Field field, int packageId) throws IllegalAccessException {");
+ {
+ p.indent();
+ p.println("int requiredModifiers = java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.PUBLIC;");
+ p.println("if ((field.getModifiers() & requiredModifiers) != requiredModifiers) {");
+ {
+ p.indent();
+ p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not rewritable\");");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println("if (field.getType() != int[].class) {");
+ {
+ p.indent();
+ p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not an int array\");");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println("int[] array = (int[]) field.get(null);");
+ p.println("for (int i = 0; i < array.length; i++) {");
+ {
+ p.indent();
+ p.println("array[i] = (array[i] & 0x00ffffff) | (packageId << 24);");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println();
+ p.println("private static void rewriteIntField(java.lang.reflect.Field field, int packageId) throws IllegalAccessException {");
+ {
+ p.indent();
+ p.println("int requiredModifiers = java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.PUBLIC;");
+ p.println("int bannedModifiers = java.lang.reflect.Modifier.FINAL;");
+ p.println("int mod = field.getModifiers();");
+ p.println("if ((mod & requiredModifiers) != requiredModifiers || (mod & bannedModifiers) != 0) {");
+ {
+ p.indent();
+ p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not rewritable\");");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println("if (field.getType() != int.class && field.getType() != Integer.class) {");
+ {
+ p.indent();
+ p.println("throw new IllegalArgumentException(\"Field \" + field.getName() + \" is not an int\");");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println("int resId = field.getInt(null);");
+ p.println("field.setInt(null, (resId & 0x00ffffff) | (packageId << 24));");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println();
+ p.println("public static void onResourcesLoaded(int assignedPackageId) throws Exception {");
+ {
+ p.indent();
+ p.println("Class<?>[] declaredClasses = R.class.getDeclaredClasses();");
+ p.println("for (Class<?> clazz : declaredClasses) {");
+ {
+ p.indent();
+ p.println("if (clazz.getSimpleName().equals(\"styleable\")) {");
+ {
+ p.indent();
+ p.println("for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {");
+ {
+ p.indent();
+ p.println("if (field.getType() == int[].class) {");
+ {
+ p.indent();
+ p.println("rewriteIntArrayField(field, assignedPackageId);");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("} else {");
+ {
+ p.indent();
+ p.println("for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {");
+ {
+ p.indent();
+ p.println("rewriteIntField(field, assignedPackageId);");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.indent(-1);
+ }
+ p.println("}");
+ p.println();
+}
+
static status_t writeLayoutClasses(
FILE* fp, const sp<AaptAssets>& assets,
const sp<AaptSymbols>& symbols, int indent, bool includePrivate, bool nonConstantId)
@@ -2138,7 +2243,7 @@ static status_t writeTextLayoutClasses(
static status_t writeSymbolClass(
FILE* fp, const sp<AaptAssets>& assets, bool includePrivate,
const sp<AaptSymbols>& symbols, const String8& className, int indent,
- bool nonConstantId)
+ bool nonConstantId, bool emitCallback)
{
fprintf(fp, "%spublic %sfinal class %s {\n",
getIndentSpace(indent),
@@ -2238,7 +2343,8 @@ static status_t writeSymbolClass(
if (nclassName == "styleable") {
styleableSymbols = nsymbols;
} else {
- err = writeSymbolClass(fp, assets, includePrivate, nsymbols, nclassName, indent, nonConstantId);
+ err = writeSymbolClass(fp, assets, includePrivate, nsymbols, nclassName,
+ indent, nonConstantId, false);
}
if (err != NO_ERROR) {
return err;
@@ -2252,6 +2358,10 @@ static status_t writeSymbolClass(
}
}
+ if (emitCallback) {
+ writeResourceLoadedCallback(fp, indent);
+ }
+
indent--;
fprintf(fp, "%s}\n", getIndentSpace(indent));
return NO_ERROR;
@@ -2299,7 +2409,7 @@ static status_t writeTextSymbolClass(
}
status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets,
- const String8& package, bool includePrivate)
+ const String8& package, bool includePrivate, bool emitCallback)
{
if (!bundle->getRClassDir()) {
return NO_ERROR;
@@ -2355,7 +2465,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets,
"package %s;\n\n", package.string());
status_t err = writeSymbolClass(fp, assets, includePrivate, symbols,
- className, 0, bundle->getNonConstantId());
+ className, 0, bundle->getNonConstantId(), emitCallback);
fclose(fp);
if (err != NO_ERROR) {
return err;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index f8bc2ae276c0..2604e970a42f 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -221,6 +221,12 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
+ public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub