Merge "Revert "Rename DisplayList->RenderNode""
diff --git a/api/current.txt b/api/current.txt
index c739dea..4f71a80 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6849,6 +6849,7 @@
field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
+ field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 268959744; // 0x10080000
field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
field public static final int FLAG_ACTIVITY_NO_ANIMATION = 65536; // 0x10000
field public static final int FLAG_ACTIVITY_NO_HISTORY = 1073741824; // 0x40000000
@@ -7645,6 +7646,7 @@
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
@@ -7668,7 +7670,7 @@
field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
- field public static final java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
+ field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
field public static final java.lang.String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct";
@@ -11294,6 +11296,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MAX_REGIONS;
field public static final android.hardware.camera2.CameraMetadata.Key FLASH_INFO_AVAILABLE;
+ field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
field public static final android.hardware.camera2.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL;
field public static final android.hardware.camera2.CameraMetadata.Key JPEG_AVAILABLE_THUMBNAIL_SIZES;
field public static final android.hardware.camera2.CameraMetadata.Key LENS_FACING;
@@ -11334,6 +11337,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_ORIENTATION;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
+ field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_MAX_FACE_COUNT;
field public static final android.hardware.camera2.CameraMetadata.Key SYNC_MAX_LATENCY;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MAX_CURVE_POINTS;
@@ -11628,6 +11632,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
@@ -11665,7 +11670,6 @@
field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key FLASH_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MAP;
field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_COORDINATES;
field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_PROCESSING_METHOD;
@@ -11702,6 +11706,8 @@
field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACES;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP;
+ field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_SCENE_FLICKER;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e71d47d..079cf7a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -878,7 +878,7 @@
}
/**
- * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
+ * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
*/
public int checkOpNoThrow(String op, int uid, String packageName) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 96479e2..0175d62 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3457,7 +3457,16 @@
*/
public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
/**
- * <strong>Do not use this flag unless you are implementing your own
+ * This flag is used to create a new task and launch an activity into it.
+ * This flag is always paired with either {@link #FLAG_ACTIVITY_NEW_DOCUMENT}
+ * or {@link #FLAG_ACTIVITY_NEW_TASK}. In both cases these flags alone would
+ * search through existing tasks for ones matching this Intent. Only if no such
+ * task is found would a new task be created. When paired with
+ * FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors are modified to skip
+ * the search for a matching task and unconditionally start a new task.
+ *
+ * <strong>When used with {@link #FLAG_ACTIVITY_NEW_TASK} do not use this
+ * flag unless you are implementing your own
* top-level application launcher.</strong> Used in conjunction with
* {@link #FLAG_ACTIVITY_NEW_TASK} to disable the
* behavior of bringing an existing task to the foreground. When set,
@@ -3469,12 +3478,18 @@
* you should not use this flag unless you provide some way for a user to
* return back to the tasks you have launched.</strong>
*
- * <p>This flag is ignored if
- * {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
+ * See {@link #FLAG_ACTIVITY_NEW_DOCUMENT} for details of this flag's use for
+ * creating new document tasks.
+ *
+ * <p>This flag is ignored if one of {@link #FLAG_ACTIVITY_NEW_TASK} or
+ * {@link #FLAG_ACTIVITY_NEW_TASK} is not also set.
*
* <p>See
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
* Stack</a> for more information about tasks.
+ *
+ * @see #FLAG_ACTIVITY_NEW_DOCUMENT
+ * @see #FLAG_ACTIVITY_NEW_TASK
*/
public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;
/**
@@ -3581,6 +3596,34 @@
*/
public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000;
/**
+ * This flag is used to break out "documents" into separate tasks that can
+ * be reached via the Recents mechanism. Such a document is any kind of
+ * item for which an application may want to maintain multiple simultaneous
+ * instances. Examples might be text files, web pages, spreadsheets, or
+ * emails. Each such document will be in a separate task in the Recents list.
+ *
+ * <p>When set, the activity specified by this Intent will launch into a
+ * separate task rooted at that activity. The activity launched must be
+ * defined with {@link android.R.attr#launchMode} "standard" or "singleTop".
+ *
+ * <p>If FLAG_ACTIVITY_NEW_DOCUMENT is used without
+ * {@link #FLAG_ACTIVITY_MULTIPLE_TASK} then the activity manager will
+ * search for an existing task with a matching target activity and Intent
+ * data URI and relaunch that task, first finishing all activities down to
+ * the root activity and then calling the root activity's
+ * {@link android.app.Activity#onNewIntent(Intent)} method. If no existing
+ * task's root activity matches the Intent's data URI then a new task will
+ * be launched with the target activity as root.
+ *
+ * <p>When paired with {@link #FLAG_ACTIVITY_MULTIPLE_TASK} this will
+ * always create a new task. Thus the same document may be made to appear
+ * more than one time in Recents.
+ *
+ * @see #FLAG_ACTIVITY_MULTIPLE_TASK
+ */
+ public static final int FLAG_ACTIVITY_NEW_DOCUMENT =
+ FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | FLAG_ACTIVITY_NEW_TASK;
+ /**
* If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint}
* callback from occurring on the current frontmost activity before it is
* paused as the newly-started activity is brought to the front.
@@ -6246,6 +6289,7 @@
* @see #FLAG_ACTIVITY_FORWARD_RESULT
* @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
* @see #FLAG_ACTIVITY_MULTIPLE_TASK
+ * @see #FLAG_ACTIVITY_NEW_DOCUMENT
* @see #FLAG_ACTIVITY_NEW_TASK
* @see #FLAG_ACTIVITY_NO_ANIMATION
* @see #FLAG_ACTIVITY_NO_HISTORY
@@ -7342,4 +7386,9 @@
String htmlText = htmlTexts != null ? htmlTexts.get(which) : null;
return new ClipData.Item(text, htmlText, null, uri);
}
+
+ /** @hide */
+ public boolean isDocument() {
+ return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT;
+ }
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2facef6..e86833b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1233,6 +1233,26 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports leanback UI. This is
+ * typically used in a living room television experience, but is a software
+ * feature unlike {@link #FEATURE_TELEVISION}. Devices running with this
+ * feature will use resources associated with the "television" UI mode.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_LEANBACK = "android.software.leanback";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports only leanback UI. Only
+ * applications designed for this experience should be run, though this is
+ * not enforced by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports WiFi (802.11) networking.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -1252,6 +1272,7 @@
* room television experience: displayed on a big screen, where the user
* is sitting far away from it, and the dominant form of input will be
* something like a DPAD, not through touch or mouse.
+ * @deprecated use {@link #FEATURE_LEANBACK} instead.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEVISION = "android.hardware.type.television";
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 875e8de..4a743a5 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -140,12 +140,33 @@
mContext.registerReceiver(mExternalReceiver, sdFilter);
}
+ private final void handlePackageEvent(Intent intent, int userId) {
+ // Don't regenerate the services map when the package is removed or its
+ // ASEC container unmounted as a step in replacement. The subsequent
+ // _ADDED / _AVAILABLE call will regenerate the map in the final state.
+ final String action = intent.getAction();
+ // it's a new-component action if it isn't some sort of removal
+ final boolean isRemoval = Intent.ACTION_PACKAGE_REMOVED.equals(action)
+ || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action);
+ // if it's a removal, is it part of an update-in-place step?
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+ if (isRemoval && replacing) {
+ // package is going away, but it's the middle of an upgrade: keep the current
+ // state and do nothing here. This clause is intentionally empty.
+ } else {
+ // either we're adding/changing, or it's a removal without replacement, so
+ // we need to recalculate the set of available services
+ generateServicesMap(userId);
+ }
+ }
+
private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
if (uid != -1) {
- generateServicesMap(UserHandle.getUserId(uid));
+ handlePackageEvent(intent, UserHandle.getUserId(uid));
}
}
};
@@ -154,7 +175,7 @@
@Override
public void onReceive(Context context, Intent intent) {
// External apps can't coexist with multi-user, so scan owner
- generateServicesMap(UserHandle.USER_OWNER);
+ handlePackageEvent(intent, UserHandle.USER_OWNER);
}
};
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index d27485b..4c04caa 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -148,7 +148,7 @@
* <p>All camera devices support ON, and all camera devices with
* flash units support ON_AUTO_FLASH and
* ON_ALWAYS_FLASH.</p>
- * <p>Full-capability camera devices always support OFF mode,
+ * <p>FULL mode camera devices always support OFF mode,
* which enables application control of camera exposure time,
* sensitivity, and frame duration.</p>
*
@@ -244,7 +244,7 @@
* given camera device. This entry lists the valid modes for
* {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} for this camera device.</p>
* <p>All camera devices will support ON mode.</p>
- * <p>Full-capability camera devices will always support OFF mode,
+ * <p>FULL mode camera devices will always support OFF mode,
* which enables application control of white balance, by using
* {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}({@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} must be set to TRANSFORM_MATRIX).</p>
*
@@ -280,6 +280,17 @@
new Key<Boolean>("android.flash.info.available", boolean.class);
/**
+ * <p>The set of hot pixel correction modes that are supported by this
+ * camera device.</p>
+ * <p>This tag lists valid modes for {@link CaptureRequest#HOT_PIXEL_MODE android.hotPixel.mode}.</p>
+ * <p>FULL mode camera devices will always support FAST.</p>
+ *
+ * @see CaptureRequest#HOT_PIXEL_MODE
+ */
+ public static final Key<byte[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES =
+ new Key<byte[]>("android.hotPixel.availableHotPixelModes", byte[].class);
+
+ /**
* <p>Supported resolutions for the JPEG thumbnail</p>
* <p>Below condiditions will be satisfied for this size list:</p>
* <ul>
@@ -1088,6 +1099,18 @@
new Key<Integer>("android.statistics.info.maxFaceCount", int.class);
/**
+ * <p>The set of hot pixel map output modes supported by this camera device.</p>
+ * <p>This tag lists valid output modes for {@link CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE android.statistics.hotPixelMapMode}.</p>
+ * <p>If no hotpixel map is available for this camera device, this will contain
+ * only OFF. If the hotpixel map is available, this should include both
+ * the ON and OFF options.</p>
+ *
+ * @see CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE
+ */
+ public static final Key<boolean[]> STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES =
+ new Key<boolean[]>("android.statistics.info.availableHotPixelMapModes", boolean[].class);
+
+ /**
* <p>Maximum number of supported points in the
* tonemap curve that can be used for {@link CaptureRequest#TONEMAP_CURVE_RED android.tonemap.curveRed}, or
* {@link CaptureRequest#TONEMAP_CURVE_GREEN android.tonemap.curveGreen}, or {@link CaptureRequest#TONEMAP_CURVE_BLUE android.tonemap.curveBlue}.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a62df0f..a3fbfbe 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1199,7 +1199,10 @@
/**
* <p>The frame rate must not be reduced relative to sensor raw output
* for this option.</p>
- * <p>No hot pixel correction is applied.</p>
+ * <p>No hot pixel correction is applied.
+ * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ *
+ * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
*/
public static final int HOT_PIXEL_MODE_OFF = 0;
@@ -1207,7 +1210,10 @@
/**
* <p>The frame rate must not be reduced relative to sensor raw output
* for this option.</p>
- * <p>Hot pixel correction is applied.</p>
+ * <p>Hot pixel correction is applied.
+ * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ *
+ * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
*/
public static final int HOT_PIXEL_MODE_FAST = 1;
@@ -1215,7 +1221,10 @@
/**
* <p>The frame rate may be reduced relative to sensor raw output
* for this option.</p>
- * <p>A high-quality hot pixel correction is applied.</p>
+ * <p>A high-quality hot pixel correction is applied.
+ * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ *
+ * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
*/
public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index a8caba0..fbac529 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -876,9 +876,13 @@
/**
* <p>Set operational mode for hot pixel correction.</p>
+ * <p>Valid modes for this camera device are listed in
+ * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}.</p>
* <p>Hotpixel correction interpolates out, or otherwise removes, pixels
* that do not accurately encode the incoming light (i.e. pixels that
* are stuck at an arbitrary value).</p>
+ *
+ * @see CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES
* @see #HOT_PIXEL_MODE_OFF
* @see #HOT_PIXEL_MODE_FAST
* @see #HOT_PIXEL_MODE_HIGH_QUALITY
@@ -1286,6 +1290,18 @@
new Key<Integer>("android.statistics.faceDetectMode", int.class);
/**
+ * <p>Operating mode for hotpixel map generation.</p>
+ * <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
+ * If set to OFF, no hotpixel map should be returned.</p>
+ * <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
+ *
+ * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
+ * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
+ */
+ public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
+ new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
+
+ /**
* <p>Whether the camera device will output the lens
* shading map in output result metadata.</p>
* <p>When set to ON,
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 0f2c7f7..ab1525e 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1166,24 +1166,14 @@
new Key<Integer>("android.flash.state", int.class);
/**
- * <p>List of <code>(x, y)</code> coordinates of hot/defective pixels on the
- * sensor, where <code>(x, y)</code> lies between <code>(0, 0)</code>, which is the top-left
- * of the pixel array, and the width,height of the pixel array given in
- * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}. This may include hot pixels
- * that lie outside of the active array bounds given by
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
- *
- * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
- * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
- */
- public static final Key<int[]> HOT_PIXEL_MAP =
- new Key<int[]>("android.hotPixel.map", int[].class);
-
- /**
* <p>Set operational mode for hot pixel correction.</p>
+ * <p>Valid modes for this camera device are listed in
+ * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}.</p>
* <p>Hotpixel correction interpolates out, or otherwise removes, pixels
* that do not accurately encode the incoming light (i.e. pixels that
* are stuck at an arbitrary value).</p>
+ *
+ * @see CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES
* @see #HOT_PIXEL_MODE_OFF
* @see #HOT_PIXEL_MODE_FAST
* @see #HOT_PIXEL_MODE_HIGH_QUALITY
@@ -1971,6 +1961,33 @@
new Key<Integer>("android.statistics.sceneFlicker", int.class);
/**
+ * <p>Operating mode for hotpixel map generation.</p>
+ * <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
+ * If set to OFF, no hotpixel map should be returned.</p>
+ * <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
+ *
+ * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
+ * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
+ */
+ public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
+ new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
+
+ /**
+ * <p>List of <code>(x, y)</code> coordinates of hot/defective pixels on the sensor.</p>
+ * <p>A coordinate <code>(x, y)</code> must lie between <code>(0, 0)</code>, and
+ * <code>(width - 1, height - 1)</code> (inclusive), which are the top-left and
+ * bottom-right of the pixel array, respectively. The width and
+ * height dimensions are given in {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.
+ * This may include hot pixels that lie outside of the active array
+ * bounds given by {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+ *
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+ */
+ public static final Key<int[]> STATISTICS_HOT_PIXEL_MAP =
+ new Key<int[]>("android.statistics.hotPixelMap", int[].class);
+
+ /**
* <p>Tonemapping / contrast / gamma curve for the blue
* channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
* CONTRAST_CURVE.</p>
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index b615600..806a89d8 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -475,6 +475,12 @@
* @param colorModes The color mode bit mask.
* @param defaultColorMode The default color mode.
* @return This builder.
+ * <p>
+ * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
+ * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
+ * crash. Hence, you should declare either both color modes or
+ * PrintAttributes#COLOR_MODE_COLOR.
+ * </p>
*
* @throws IllegalArgumentException If color modes contains an invalid
* mode bit or if the default color mode is invalid.
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 94c3f44..d8cf18e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -435,6 +435,14 @@
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
+ * CAUTION: when adding options in here, be careful not to put the
+ * char buffer inside a nested scope. Adding the buffer to the
+ * options using mOptions.add() does not copy the buffer, so if the
+ * buffer goes out of scope the option may be overwritten. It's best
+ * to put the buffer at the top of the function so that it is more
+ * unlikely that someone will surround it in a scope at a later time
+ * and thus introduce a bug.
+ *
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
@@ -469,7 +477,15 @@
kEMIntFast,
kEMJitCompiler,
} executionMode = kEMDefault;
-
+ char profile_period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+ char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+ char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+ char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+ char langOption[sizeof("-Duser.language=") + 3];
+ char regionOption[sizeof("-Duser.region=") + 3];
+ char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
+ char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
+ char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
@@ -670,7 +686,6 @@
//mOptions.add(opt);
}
- char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
property_get("dalvik.vm.lockprof.threshold", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
@@ -680,7 +695,6 @@
}
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
- char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.op", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitOpBuf, "-Xjitop:");
@@ -690,7 +704,6 @@
}
/* Force interpreter-only mode for selected methods */
- char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.method", propBuf, "");
if (strlen(propBuf) > 0) {
strcpy(jitMethodBuf, "-Xjitmethod:");
@@ -770,8 +783,6 @@
/* Set the properties for locale */
{
- char langOption[sizeof("-Duser.language=") + 3];
- char regionOption[sizeof("-Duser.region=") + 3];
strcpy(langOption, "-Duser.language=");
strcpy(regionOption, "-Duser.region=");
readLocale(langOption, regionOption);
@@ -786,35 +797,30 @@
* Set profiler options
*/
if (libart) {
- char period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
- char duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
- char interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
- char backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
-
// Number of seconds during profile runs.
- strcpy(period, "-Xprofile-period:");
- property_get("dalvik.vm.profile.period_secs", period+17, "10");
- opt.optionString = period;
+ strcpy(profile_period, "-Xprofile-period:");
+ property_get("dalvik.vm.profile.period_secs", profile_period+17, "10");
+ opt.optionString = profile_period;
mOptions.add(opt);
// Length of each profile run (seconds).
- strcpy(duration, "-Xprofile-duration:");
- property_get("dalvik.vm.profile.duration_secs", duration+19, "30");
- opt.optionString = duration;
+ strcpy(profile_duration, "-Xprofile-duration:");
+ property_get("dalvik.vm.profile.duration_secs", profile_duration+19, "30");
+ opt.optionString = profile_duration;
mOptions.add(opt);
// Polling interval during profile run (microseconds).
- strcpy(interval, "-Xprofile-interval:");
- property_get("dalvik.vm.profile.interval_us", interval+19, "10000");
- opt.optionString = interval;
+ strcpy(profile_interval, "-Xprofile-interval:");
+ property_get("dalvik.vm.profile.interval_us", profile_interval+19, "10000");
+ opt.optionString = profile_interval;
mOptions.add(opt);
// Coefficient for period backoff. The the period is multiplied
// by this value after each profile run.
- strcpy(backoff, "-Xprofile-backoff:");
- property_get("dalvik.vm.profile.backoff_coeff", backoff+18, "2.0");
- opt.optionString = backoff;
+ strcpy(profile_backoff, "-Xprofile-backoff:");
+ property_get("dalvik.vm.profile.backoff_coeff", profile_backoff+18, "2.0");
+ opt.optionString = profile_backoff;
mOptions.add(opt);
}
diff --git a/docs/html/images/screens_support/avds-config.png b/docs/html/images/screens_support/avds-config.png
index 97bd5f6..e609447 100644
--- a/docs/html/images/screens_support/avds-config.png
+++ b/docs/html/images/screens_support/avds-config.png
Binary files differ
diff --git a/docs/html/images/tools/as-camera-icon.png b/docs/html/images/tools/as-camera-icon.png
new file mode 100644
index 0000000..419a88d
--- /dev/null
+++ b/docs/html/images/tools/as-camera-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-error.png b/docs/html/images/tools/as-error.png
new file mode 100644
index 0000000..8865f54
--- /dev/null
+++ b/docs/html/images/tools/as-error.png
Binary files differ
diff --git a/docs/html/images/tools/as-fr-device.png b/docs/html/images/tools/as-fr-device.png
new file mode 100644
index 0000000..aec3bce
--- /dev/null
+++ b/docs/html/images/tools/as-fr-device.png
Binary files differ
diff --git a/docs/html/images/tools/as-fr-icon.png b/docs/html/images/tools/as-fr-icon.png
new file mode 100644
index 0000000..9252ca1
--- /dev/null
+++ b/docs/html/images/tools/as-fr-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-frag-ex.png b/docs/html/images/tools/as-frag-ex.png
new file mode 100644
index 0000000..775fa5e
--- /dev/null
+++ b/docs/html/images/tools/as-frag-ex.png
Binary files differ
diff --git a/docs/html/images/tools/as-grid-layout.png b/docs/html/images/tools/as-grid-layout.png
new file mode 100644
index 0000000..41b933a
--- /dev/null
+++ b/docs/html/images/tools/as-grid-layout.png
Binary files differ
diff --git a/docs/html/images/tools/as-i18n-icon.png b/docs/html/images/tools/as-i18n-icon.png
new file mode 100644
index 0000000..d35568f
--- /dev/null
+++ b/docs/html/images/tools/as-i18n-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-chrome.png b/docs/html/images/tools/as-preview-chrome.png
new file mode 100644
index 0000000..716b8d7
--- /dev/null
+++ b/docs/html/images/tools/as-preview-chrome.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-icon.png b/docs/html/images/tools/as-preview-icon.png
new file mode 100644
index 0000000..59c7644
--- /dev/null
+++ b/docs/html/images/tools/as-preview-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-nochrome.png b/docs/html/images/tools/as-preview-nochrome.png
new file mode 100644
index 0000000..1011e08
--- /dev/null
+++ b/docs/html/images/tools/as-preview-nochrome.png
Binary files differ
diff --git a/docs/html/images/tools/as-theme-db.png b/docs/html/images/tools/as-theme-db.png
new file mode 100644
index 0000000..beade0d
--- /dev/null
+++ b/docs/html/images/tools/as-theme-db.png
Binary files differ
diff --git a/docs/html/images/tools/as-theme-icon.png b/docs/html/images/tools/as-theme-icon.png
new file mode 100644
index 0000000..0e5fdf0
--- /dev/null
+++ b/docs/html/images/tools/as-theme-icon.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/adt-firstapp-setup.png b/docs/html/images/training/firstapp/adt-firstapp-setup.png
index bf95285..05e147d 100644
--- a/docs/html/images/training/firstapp/adt-firstapp-setup.png
+++ b/docs/html/images/training/firstapp/adt-firstapp-setup.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/adt-new-activity.png b/docs/html/images/training/firstapp/adt-new-activity.png
index c396793..2c32dcc 100644
--- a/docs/html/images/training/firstapp/adt-new-activity.png
+++ b/docs/html/images/training/firstapp/adt-new-activity.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_gravity.png b/docs/html/images/training/firstapp/edittext_gravity.png
index f78e676..bc4f7ee 100644
--- a/docs/html/images/training/firstapp/edittext_gravity.png
+++ b/docs/html/images/training/firstapp/edittext_gravity.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_wrap.png b/docs/html/images/training/firstapp/edittext_wrap.png
index 156776d..fe56731 100644
--- a/docs/html/images/training/firstapp/edittext_wrap.png
+++ b/docs/html/images/training/firstapp/edittext_wrap.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/firstapp.png b/docs/html/images/training/firstapp/firstapp.png
index d69cd20..581e000 100644
--- a/docs/html/images/training/firstapp/firstapp.png
+++ b/docs/html/images/training/firstapp/firstapp.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 5d1788a..e901652 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -22,12 +22,13 @@
<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<div style="box-shadow: 3px 10px 18px 1px #999;width:600px;height:336px">
<div id="ytapiplayer">
- <a href="http://www.youtube.com/watch?v=WWArLD6nqrk"><img width=600 src="{@docRoot}images/video-kiwi.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
+ <a href="http://www.youtube.com/watch?v=i2uvYI6blEE"><img width=600
+ src="https://i1.ytimg.com/vi/i2uvYI6blEE/maxresdefault.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
</div>
<script type="text/javascript">
var params = { allowScriptAccess: "always" };
var atts = { id: "ytapiplayer" };
- swfobject.embedSWF("//www.youtube.com/v/WWArLD6nqrk?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
+ swfobject.embedSWF("//www.youtube.com/v/i2uvYI6blEE?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
"ytapiplayer", "600", "336", "8", null, null, params, atts);
// Callback used to pause/resume carousel based on video state
@@ -56,9 +57,8 @@
</div>
</div>
<div class="content-right col-4">
- <h1 style="white-space:nowrap;line-height:1.2em;">Developer Story: <br />Kiwi, Inc.</h1>
- <p>Game developer Kiwi has had five titles in the top 25 grossing on Google Play. Hear how Google Play
- has helped them double revenue every six months.</p>
+ <h1 style="white-space:nowrap;line-height:1.2em;">Developer Story: <br />Box Inc.</h1>
+ <p>Box is a cloud-based platform and app for users to share business information. See how they got over 5 million downloads by leveraging the flexibility in the Android platform.</p>
<p><a href="{@docRoot}distribute/googleplay/spotlight/index.html" class="button">Watch more videos </a></p>
</div>
</li>
diff --git a/docs/html/sdk/installing/studio-layout.jd b/docs/html/sdk/installing/studio-layout.jd
new file mode 100644
index 0000000..f0e5d59
--- /dev/null
+++ b/docs/html/sdk/installing/studio-layout.jd
@@ -0,0 +1,148 @@
+page.title=Using the Layout Editor
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>See also</h2>
+<ul>
+<li><a href="{@docRoot}sdk/installing/studio.html">
+Getting Started with Android Studio</a></li>
+<li><a href="{@docRoot}sdk/installing/studio-tips.html">
+Android Studio Tips and Tricks</a></li>
+<li><a href="{@docRoot}sdk/installing/migrate.html">
+Migrating from Eclipse</a></li>
+</div>
+</div>
+
+<a class="notice-developers-video"
+href="https://developers.google.com/events/io/sessions/324603352">
+<div>
+ <h3>Video</h3>
+ <p>What's New in Android Developer Tools</p>
+</div>
+</a>
+
+<p>Android Studio offers an advanced layout editor that allows you to drag-and-drop widgets
+into your layout and preview your layout while editing the XML.</p>
+
+<p>Within the layout editor, you can switch between the <strong>Text</strong> view, where
+you edit the XML file as text, and the <strong>Design</strong> view. Just click the
+appropriate tab at the bottom of the window to display the desired editor.</p>
+
+<h2>Editing in the Text View</h2>
+
+<p>You can use the <strong>Text</strong> view to edit your layout file. This section describes
+some of the features that are available in the <strong>Text</strong> view.</p>
+
+<h3>Preview</h3>
+
+<p>While editing in the <strong>Text</strong> view, you can preview the layout on devices
+by opening the <strong>Preview</strong> pane available on the right side of the window.
+Within the <strong>Preview</strong> pane, you can modify the preview by changing various
+options at the top of the pane, including the preview device, layout theme, platform
+version and more. To see a preview of how your app would look with a particular device
+skin, click the preview icon
+<img src="{@docRoot}images/tools/as-preview-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+and choose the desired device, such as Nexus 4:</p>
+
+<img src="{@docRoot}images/tools/as-preview-chrome.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> Previewing your app.</p>
+
+<p>To preview the layout on multiple devices simultaneously, select <strong>Preview All
+Screen Sizes</strong> from the device drop-down. </p>
+
+<p>When you click in the preview image, the layout editor highlights the corresponding
+section in the XML, and vice-versa.</p>
+
+<h3>Interactive error detection and recovery</h3>
+
+<p>As you edit the <strong>Text</strong> view of your layout XML file, Android Studio flags
+typos and offers assistance.</p>
+
+<p>For example, suppose you are adding a button, and you misspell it as "Buttonn".
+Android Studio helps you to correct it by displaying an error such as the following,
+where you can click on "Change to Button" to fix the error in the XML file:</p>
+
+<img src="{@docRoot}images/tools/as-error.png" alt="" />
+
+<p class="img-caption"><strong>Figure 2.</strong> Flagging errors.</p>
+
+<p>Android Studio also prompts you to supply missing information. For example, suppose you
+start adding a fragment to your layout XML file. First of all, Android Studio displays
+auto-complete suggestions as you type. Once it becomes clear that you are adding a fragment,
+Android Studio displays an error panel with links that you can click to supply the missing
+attributes. Clicking "Automatically add all missing attributes" in this case
+does just that—it completes the fragment definition in your layout XML file:</p>
+
+<img src="{@docRoot}images/tools/as-frag-ex.png" alt="" />
+
+<p class="img-caption"><strong>Figure 3.</strong> Supplying missing information</p>
+
+<h3>Picking a theme</h3>
+
+<p>To pick a theme for your app, click the Theme icon
+<img src="{@docRoot}images/tools/as-theme-icon.png" style="vertical-align:bottom;margin:0;height:19px" />.
+</p>
+
+<p>This displays the <strong>Select Theme</strong> dialog, where you can search for a
+particular theme and/or select one from the list on the right hand side. The theme you
+choose will be reflected in the previewed image.</p>
+
+<img src="{@docRoot}images/tools/as-theme-db.png" alt="" />
+
+<p class="img-caption"><strong>Figure 4.</strong> Specifying a theme.</p>
+
+<h3>Localization</h3>
+
+<p>Android Studio provides built-in localization support. When you click the
+localization icon
+<img src="{@docRoot}images/tools/as-i18n-icon.png" style="vertical-align:bottom;margin:0;height:19px" />,
+you can select a particular locale, add and edit translations, preview the locales your
+app supports (all locales or just a single locale), and preview right-to-left layout for
+languages that are RTL.</p>
+
+<p>See <a href="{@docRoot}training/basics/supporting-devices/languages.html">Supporting
+Different Languages</a> for a description of how to support different locales in your app.</p>
+<p>For example, here is a preview of a "Hello World" app for the
+<img src="{@docRoot}images/tools/as-fr-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+locale:</p>
+
+<img src="{@docRoot}images/tools/as-fr-device.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> Previewing locales.</p>
+
+<h2>Editing in the Design View</h2>
+
+<p>You can switch to the graphical editor by clicking <strong>Design</strong> at the
+bottom of the window. While editing in the <strong>Design</strong> view, you can show and
+hide the widgets available to drag-and-drop by clicking <strong>Palette</strong> on the
+left side of the window. Clicking <strong>Designer</strong> on the right side of the
+window reveals a panel with a layout hierarchy and a list of properties for each view in
+the layout.</p>
+
+<p>When you drag a widget into the graphical layout for your app, the display changes to
+help you place the widget. What you see depends on the type of layout. For example, if
+you're dragging a widget into a {@link android.widget.FrameLayout}, it displays a grid to
+help you place the widget, as shown in figure 6:</p>
+
+<img src="{@docRoot}images/tools/as-grid-layout.png" alt="" />
+
+<p class="img-caption"><strong>Figure 6.</strong> Using the grid layout to place a widget.</p>
+
+<p>Within the graphical editor, you can rearrange your app's UI by dragging widgets to
+the desired location.</p>
+
+<h3>Taking a snapshot</h3>
+
+<p>When you run your app on a connected device, you can take a snapshot of it by clicking
+the camera icon
+<img src="{@docRoot}images/tools/as-camera-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+to the left of the logging
+panel (at the bottom of the window by default). This takes a snapshot of your running app
+(or whatever is currently displayed on your device) and displays it in a window. Check
+<strong>Frame Screenshot</strong> to show your screenshot within the device skin of your
+choice. You can also specify whether you want the image to have screen glare and/or a drop
+shadow. Once you have the desired effect, you can save the image.</p>
+
+<p>You can use the same process to create a snapshot of your app's preview. Just click the
+camera icon in the preview area and follow the steps for adding a device skin.</p>
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 5a7e270..feb7a6e 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -318,6 +318,12 @@
<h2 id="Installing">Installing Android Studio</h2>
+<p>Android Studio requires JDK 6 or greater (JRE alone is not sufficient). To check if you
+have JDK installed (and which version), open a terminal and type <code>javac -version</code>.
+If JDK is not available or the version is lower than 6,
+<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">download
+JDK from here</a>.</p>
+<p>To install Android Studio:</p>
<ol>
<li>Download the <strong>Android Studio</strong> package from above.</li>
<li>Install Android Studio and the SDK tools:
diff --git a/docs/html/tools/help/logcat.jd b/docs/html/tools/help/logcat.jd
index ede1905..b30971e 100644
--- a/docs/html/tools/help/logcat.jd
+++ b/docs/html/tools/help/logcat.jd
@@ -45,7 +45,7 @@
<tr>
<td><code>-b <buffer></code></td>
- <td>Loads an alternate log buffer for viewing, such as <code>event</code> or
+ <td>Loads an alternate log buffer for viewing, such as <code>events</code> or
<code>radio</code>. The <code>main</code> buffer is used by default. See <a href=
"{@docRoot}tools/debugging/debugging-log.html#alternativeBuffers">Viewing Alternative Log Buffers</a>.</td>
</tr>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index a8424e6..382165c 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -34,7 +34,9 @@
Migrating from Eclipse</a></li>
<li><a href="<?cs var:toroot ?>sdk/installing/studio-tips.html">
Tips and Tricks</a></li>
- </ul>
+ <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
+ Using the Layout Editor</a></li>
+ </ul>
</li>
<li><a href="<?cs var:toroot ?>sdk/exploring.html">
<span class="en">Exploring the SDK</span></a></li>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 2615bee..179b3ac 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -75,16 +75,16 @@
<h2 id="LinearLayout">Create a Linear Layout</h2>
-<p>Open the <code>activity_main.xml</code> file from the <code>res/layout/</code>
+<p>Open the <code>fragment_main.xml</code> file from the <code>res/layout/</code>
directory.</p>
<p class="note"><strong>Note:</strong> In Eclipse, when you open a layout file, you’re first shown
the Graphical Layout editor. This is an editor that helps you build layouts using WYSIWYG tools. For this
-lesson, you’re going to work directly with the XML, so click the <em>activity_main.xml</em> tab at
+lesson, you’re going to work directly with the XML, so click the <em>fragment_main.xml</em> tab at
the bottom of the screen to open the XML editor.</p>
<p>The BlankActivity template you chose when you created this project includes the
-<code>activity_main.xml</code> file with a {@link
+<code>fragment_main.xml</code> file with a {@link
android.widget.RelativeLayout} root view and a {@link android.widget.TextView} child view.</p>
<p>First, delete the {@link android.widget.TextView <TextView>} element and change the {@link
@@ -95,7 +95,6 @@
The result looks like this:</p>
<pre>
-<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 9516e37..50485db 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -120,8 +120,8 @@
<strong>Finish</strong>.</li>
</ol>
-<p>Your Android project is now set up with some default files and you’re ready to begin
-building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
+To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
@@ -155,8 +155,8 @@
projects.</p></li>
</ol>
-<p>Your Android project is now set up with several default configurations and you’re ready to begin
-building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
+To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
<p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
<code>tools/</code> directory to your <code>PATH</code> environment variable.</p>
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 999d399..23cedba 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -62,7 +62,7 @@
attributes. For your first app, it should look like this:</p>
<pre>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" />
...
</manifest>
</pre>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 712eabc..9aa25a3 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -45,7 +45,7 @@
<h2 id="RespondToButton">Respond to the Send Button</h2>
-<p>To respond to the button's on-click event, open the <code>activity_main.xml</code>
+<p>To respond to the button's on-click event, open the <code>fragment_main.xml</code>
layout file and add the <a
href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>
attribute to the {@link android.widget.Button <Button>} element:</p>
@@ -73,14 +73,6 @@
}
</pre>
-<p>This requires that you import the {@link android.view.View} class:</p>
-<pre>
-import android.view.View;
-</pre>
-
-<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes
-(Cmd + Shift + O on Mac).</p>
-
<p>In order for the system to match this method to the method name given to <a
href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>,
the signature must be exactly as shown. Specifically, the method must:</p>
@@ -111,6 +103,14 @@
Intent intent = new Intent(this, DisplayMessageActivity.class);
</pre>
+<p>This requires that you import the {@link android.content.Intent} class:</p>
+<pre>
+import android.content.Intent;
+</pre>
+
+<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes
+(Cmd + Shift + O on Mac).</p>
+
<p>The constructor used here takes two parameters:</p>
<ul>
<li>A {@link
@@ -151,9 +151,8 @@
</pre>
<p class="note"><strong>Note:</strong>
-You now need import statements for <code>android.content.Intent</code>
-and <code>android.widget.EditText</code>. You'll define the <code>EXTRA_MESSAGE</code>
-constant in a moment.</p>
+You now need an import statement for <code>android.widget.EditText</code>.
+You'll define the <code>EXTRA_MESSAGE</code> constant in a moment.</p>
<p>An {@link android.content.Intent} can carry a collection of various data types as key-value
pairs called <em>extras</em>. The {@link android.content.Intent#putExtra putExtra()} method takes the
@@ -165,7 +164,7 @@
MainActivity} class:</p>
<pre>
-public class MainActivity extends Activity {
+public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
...
}
@@ -223,6 +222,7 @@
<li><strong>Project</strong>: MyFirstApp</li>
<li><strong>Activity Name</strong>: DisplayMessageActivity</li>
<li><strong>Layout Name</strong>: activity_display_message</li>
+ <li><strong>Fragment Layout Name</strong>: fragment_display_message</li>
<li><strong>Title</strong>: My Message</li>
<li><strong>Hierarchial Parent</strong>: com.example.myfirstapp.MainActivity</li>
<li><strong>Navigation Type</strong>: None</li>
@@ -240,49 +240,65 @@
<ul>
<li>The class
already includes an implementation of the required {@link android.app.Activity#onCreate onCreate()}
-method.</li>
+method. You will update the implementation of this method later.</li>
<li>There's also an implementation of the {@link android.app.Activity#onCreateOptionsMenu
onCreateOptionsMenu()} method, but
you won't need it for this app so you can remove it.</li>
<li>There's also an implementation of {@link android.app.Activity#onOptionsItemSelected
onOptionsItemSelected()} which handles the behavior for the action bar's <em>Up</em> behavior.
Keep this one the way it is.</li>
+ <li>There's also a <code>PlaceholderFragment</code> class that extends
+{@link android.app.Fragment}. You will not need this class in the final version of this
+activity.</li>
</ul>
-<p>Because the {@link android.app.ActionBar} APIs are available only on {@link
-android.os.Build.VERSION_CODES#HONEYCOMB} (API level 11) and higher, you must add a condition
-around the {@link android.app.Activity#getActionBar()} method to check the current platform version.
-Additionally, you must add the {@code @SuppressLint("NewApi")} tag to the
-{@link android.app.Activity#onCreate onCreate()} method to avoid <a
-href="{@docRoot}tools/help/lint.html">lint</a> errors.</p>
+<p>Fragments decompose application functionality and UI into reusable modules. For more
+information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments
+API Guide</a>. The final version of this activity does not use fragments.</p>
<p>The {@code DisplayMessageActivity} class should now look like this:</p>
<pre>
-public class DisplayMessageActivity extends Activity {
+public class DisplayMessageActivity extends ActionBarActivity {
- @SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
- // Make sure we're running on Honeycomb or higher to use ActionBar APIs
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- // Show the Up button in the action bar.
- getActionBar().setDisplayHomeAsUpEnabled(true);
+ if (savedInstanceState == null) {
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.container, new PlaceholderFragment()).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- NavUtils.navigateUpFromSameTask(this);
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+
+ public PlaceholderFragment() { }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_display_message,
+ container, false);
+ return rootView;
+ }
+ }
}
</pre>
@@ -422,7 +438,7 @@
<img src="{@docRoot}images/training/firstapp/firstapp.png" />
<p class="img-caption"><strong>Figure 2.</strong> Both activities in the final app, running
-on Android 4.0.
+on Android 4.4.
<p>That's it, you've built your first Android app!</p>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index b3d9ccf..db95193 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
@@ -36,20 +37,20 @@
/** Logs a key */
public static void log(String key) {
- Console.log(true, key, "", AnsiReset);
+ log(true, key, "", AnsiReset);
}
/** Logs a conditioned key */
public static void log(boolean condition, String key) {
if (condition) {
- Console.log(condition, key, "", AnsiReset);
+ log(condition, key, "", AnsiReset);
}
}
/** Logs a key in a specific color */
public static void log(boolean condition, String key, Object data) {
if (condition) {
- Console.log(condition, key, data, AnsiReset);
+ log(condition, key, data, AnsiReset);
}
}
@@ -74,6 +75,50 @@
}
}
+ /** Logs a stack trace */
+ public static void logStackTrace() {
+ logStackTrace("", 99);
+ }
+
+ /** Logs a stack trace to a certain depth */
+ public static void logStackTrace(int depth) {
+ logStackTrace("", depth);
+ }
+
+ /** Logs a stack trace to a certain depth with a key */
+ public static void logStackTrace(String key, int depth) {
+ int offset = 0;
+ StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+ String tinyStackTrace = "";
+ // Skip over the known stack trace classes
+ for (int i = 0; i < callStack.length; i++) {
+ StackTraceElement el = callStack[i];
+ String className = el.getClassName();
+ if (className.indexOf("dalvik.system.VMStack") == -1 &&
+ className.indexOf("java.lang.Thread") == -1 &&
+ className.indexOf("recents.Console") == -1) {
+ break;
+ } else {
+ offset++;
+ }
+ }
+ // Build the pretty stack trace
+ int start = Math.min(offset + depth, callStack.length);
+ int end = offset;
+ String indent = "";
+ for (int i = start - 1; i >= end; i--) {
+ StackTraceElement el = callStack[i];
+ tinyStackTrace += indent + " -> " + el.getClassName() +
+ "[" + el.getLineNumber() + "]." + el.getMethodName();
+ if (i > end) {
+ tinyStackTrace += "\n";
+ indent += " ";
+ }
+ }
+ log(true, key, tinyStackTrace, AnsiRed);
+ }
+
+
/** Returns the stringified MotionEvent action */
public static String motionEventActionToString(int action) {
switch (action) {
@@ -93,4 +138,25 @@
return "" + action;
}
}
+
+ public static String trimMemoryLevelToString(int level) {
+ switch (level) {
+ case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+ return "UI Hidden";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+ return "Running Moderate";
+ case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+ return "Background";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+ return "Running Low";
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ return "Moderate";
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+ return "Critical";
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ return "Complete";
+ default:
+ return "" + level;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index aeae4ab..57ebbc2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -30,9 +30,11 @@
public static final boolean EnableTaskStackClipping = false;
public static final boolean EnableBackgroundTaskLoading = true;
public static final boolean ForceDisableBackgroundCache = false;
+
public static final boolean TaskDataLoader = false;
public static final boolean SystemUIHandshake = false;
public static final boolean TimeSystemCalls = false;
+ public static final boolean Memory = false;
}
public static class UI {
@@ -41,7 +43,7 @@
public static final boolean TouchEvents = false;
public static final boolean MeasureAndLayout = false;
public static final boolean Clipping = false;
- public static final boolean HwLayers = true;
+ public static final boolean HwLayers = false;
}
public static class TaskStack {
@@ -55,13 +57,16 @@
public static class Values {
public static class Window {
+ // The dark background dim is set behind the empty recents view
public static final float DarkBackgroundDim = 0.5f;
+ // The background dim is set behind the card stack
public static final float BackgroundDim = 0.35f;
}
public static class RecentsTaskLoader {
// XXX: This should be calculated on the first load
public static final int PreloadFirstTasksCount = 5;
+ // For debugging, this allows us to multiply the number of cards for each task
public static final int TaskEntryMultiplier = 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d050847..fc4d819 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -23,6 +23,7 @@
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.RecentsView;
@@ -168,6 +169,14 @@
}
@Override
+ public void onTrimMemory(int level) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ if (loader != null) {
+ loader.onTrimMemory(level);
+ }
+ }
+
+ @Override
public void onBackPressed() {
if (!mRecentsView.unfilterFilteredStacks()) {
super.onBackPressed();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index f3881ae..ed981ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -30,7 +30,6 @@
DisplayMetrics mDisplayMetrics;
- public boolean layoutVerticalStack;
public Rect systemInsets = new Rect();
/** Private constructor */
@@ -56,7 +55,6 @@
boolean isPortrait = context.getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT;
- layoutVerticalStack = isPortrait || Constants.LANDSCAPE_LAYOUT_VERTICAL_STACK;
}
public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 522ab0f..13a3424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -57,8 +57,9 @@
tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top);
tsv.boundScroll();
TaskViewTransform transform = tsv.getStackTransform(0);
+ Rect taskRect = new Rect(transform.rect);
- data.putParcelable("taskRect", transform.rect);
+ data.putParcelable("taskRect", taskRect);
Message reply = Message.obtain(null, MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
reply.setData(data);
msg.replyTo.send(reply);
@@ -100,4 +101,12 @@
Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsService|onDestroy]");
super.onDestroy();
}
+
+ @Override
+ public void onTrimMemory(int level) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ if (loader != null) {
+ loader.onTrimMemory(level);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index c303ca7..96efed4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -233,7 +235,7 @@
@Override
protected int sizeOf(Task t, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than number of items
- return bitmap.getByteCount() / 1024;
+ return bitmap.getAllocationByteCount() / 1024;
}
}
@@ -247,17 +249,28 @@
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
+ int mMaxThumbnailCacheSize;
+ int mMaxIconCacheSize;
+
BitmapDrawable mDefaultIcon;
Bitmap mDefaultThumbnail;
/** Private Constructor */
private RecentsTaskLoader(Context context) {
+ // Calculate the cache sizes
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
- int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 16;
- int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 8;
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ mMaxThumbnailCacheSize = maxMemory / 8;
+ mMaxIconCacheSize = mMaxThumbnailCacheSize / 4;
+ int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+ mMaxIconCacheSize;
+ int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+ mMaxThumbnailCacheSize;
+
+ Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
"[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
" iconCache: " + iconCacheSize);
+
+ // Initialize the cache and loaders
mLoadQueue = new TaskResourceLoadQueue();
mIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -293,7 +306,7 @@
/** Reload the set of recent tasks */
SpaceNode reload(Context context, int preloadCount) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|reload]");
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
TaskStack stack = new TaskStack(context);
SpaceNode root = new SpaceNode(context);
root.setStack(stack);
@@ -310,7 +323,7 @@
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
"[RecentsTaskLoader|getRecentTasks]",
"" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
"[RecentsTaskLoader|tasks]", "" + tasks.size());
// Remove home/recents tasks
@@ -335,35 +348,51 @@
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
-
- // Load the label, icon and thumbnail
ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
PackageManager.GET_META_DATA);
String title = info.loadLabel(pm).toString();
- Drawable icon = null;
- Bitmap thumbnail = null;
Task task;
- if (i >= (taskCount - preloadCount) || !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ // Preload the specified number of apps
+ if (i >= (taskCount - preloadCount) ||
+ !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
"[RecentsTaskLoader|preloadTask]",
"i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
- icon = info.loadIcon(pm);
- thumbnail = am.getTaskTopThumbnail(t.id);
- for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
- task = new Task(t.persistentId, t.baseIntent, title, icon, thumbnail);
+
+ task = new Task(t.persistentId, t.baseIntent, title, null, null);
+
+ // Load the icon (if possible from the cache)
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ task.icon = mIconCache.get(task);
+ }
+ if (task.icon == null) {
+ task.icon = info.loadIcon(pm);
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- if (thumbnail != null) mThumbnailCache.put(task, thumbnail);
- if (icon != null) {
- mIconCache.put(task, icon);
- }
+ mIconCache.put(task, task.icon);
}
+ }
+
+ // Load the thumbnail (if possible from the cache)
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ task.thumbnail = mThumbnailCache.get(task);
+ }
+ if (task.thumbnail == null) {
+ task.thumbnail = am.getTaskTopThumbnail(t.id);
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ mThumbnailCache.put(task, task.thumbnail);
+ }
+ }
+
+ // Create as many tasks a we want to multiply by
+ for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
stack.addTask(task);
}
} else {
+ // Create as many tasks a we want to multiply by
for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
task = new Task(t.persistentId, t.baseIntent, title, null, null);
stack.addTask(task);
@@ -388,9 +417,9 @@
t1 = System.currentTimeMillis();
List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
for (ActivityManager.StackInfo s : stackInfos) {
- Console.log(Constants.DebugFlags.App.SystemUIHandshake, " [RecentsTaskLoader|stack]", s.toString());
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
if (stacks.containsKey(s.stackId)) {
stacks.get(s.stackId).setRect(s.bounds);
}
@@ -403,45 +432,46 @@
return root;
}
- /** Acquires the task resource data from the pool.
- * XXX: Move this into Task? */
+ /** Acquires the task resource data from the pool. */
public void loadTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
- t.icon = mIconCache.get(t);
- t.thumbnail = mThumbnailCache.get(t);
+ Drawable icon = mIconCache.get(t);
+ Bitmap thumbnail = mThumbnailCache.get(t);
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
- t + " icon: " + t.icon + " thumbnail: " + t.thumbnail);
+ t + " icon: " + icon + " thumbnail: " + thumbnail +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
boolean requiresLoad = false;
- if (t.icon == null) {
- t.icon = mDefaultIcon;
+ if (icon == null) {
+ icon = mDefaultIcon;
requiresLoad = true;
}
- if (t.thumbnail == null) {
- t.thumbnail = mDefaultThumbnail;
+ if (thumbnail == null) {
+ thumbnail = mDefaultThumbnail;
requiresLoad = true;
}
if (requiresLoad) {
mLoadQueue.addTask(t);
}
+ t.notifyTaskLoaded(thumbnail, icon);
}
}
- /** Releases the task resource data back into the pool.
- * XXX: Move this into Task? */
+ /** Releases the task resource data back into the pool. */
public void unloadTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
Console.log(Constants.DebugFlags.App.TaskDataLoader,
- "[RecentsTaskLoader|unloadTask]", t);
+ "[RecentsTaskLoader|unloadTask]", t +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
mLoadQueue.removeTask(t);
- t.icon = mDefaultIcon;
- t.thumbnail = mDefaultThumbnail;
+ t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+ } else {
+ t.notifyTaskUnloaded(null, null);
}
}
- /** Completely removes the resource data from the pool.
- * XXX: Move this into Task? */
+ /** Completely removes the resource data from the pool. */
public void deleteTaskData(Task t) {
if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -449,9 +479,10 @@
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t);
mIconCache.remove(t);
+ t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+ } else {
+ t.notifyTaskUnloaded(null, null);
}
- t.icon = mDefaultIcon;
- t.thumbnail = mDefaultThumbnail;
}
/** Stops the task loader */
@@ -460,4 +491,51 @@
mLoader.stop();
mLoadQueue.clearTasks();
}
+
+ void onTrimMemory(int level) {
+ Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
+ Console.trimMemoryLevelToString(level));
+
+ if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+ // If we are hidden, then we should unload each of the task keys
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|unloadTasks]"
+ );
+ // Unload each of the keys in the thumbnail cache
+ Map<Task, Bitmap> thumbnailCache = mThumbnailCache.snapshot();
+ for (Task t : thumbnailCache.keySet()) {
+ unloadTaskData(t);
+ }
+ // As well as the keys in the icon cache
+ Map<Task, Drawable> iconCache = mIconCache.snapshot();
+ for (Task t : iconCache.keySet()) {
+ unloadTaskData(t);
+ }
+ }
+
+ switch (level) {
+ case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+ case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+ // We are leaving recents, so trim the data a bit
+ mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
+ mIconCache.trimToSize(mMaxIconCacheSize / 2);
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ // We are going to be low on memory
+ mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
+ mIconCache.trimToSize(mMaxIconCacheSize / 4);
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ // We are low on memory, so release everything
+ mThumbnailCache.evictAll();
+ mIconCache.evictAll();
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 9b03c5d..378984c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -54,6 +54,24 @@
}
}
+ /** Notifies the callback listeners that this task has been loaded */
+ public void notifyTaskLoaded(Bitmap thumbnail, Drawable icon) {
+ this.icon = icon;
+ this.thumbnail = thumbnail;
+ if (mCb != null) {
+ mCb.onTaskBound();
+ }
+ }
+
+ /** Notifies the callback listeners that this task has been unloaded */
+ public void notifyTaskUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) {
+ icon = defaultIcon;
+ thumbnail = defaultThumbnail;
+ if (mCb != null) {
+ mCb.onTaskUnbound();
+ }
+ }
+
@Override
public boolean equals(Object o) {
// If we have multiple task entries for the same task, then we do the simple object
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
index 169f56c..712580d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
@@ -20,4 +20,8 @@
public interface TaskCallbacks {
/* Notifies when a task's data has been updated */
public void onTaskDataChanged(Task task);
+ /* Notifies when a task has been bound */
+ public void onTaskBound();
+ /* Notifies when a task has been unbound */
+ public void onTaskUnbound();
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index fe661bc..21ef9ff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -28,6 +28,8 @@
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.LinearInterpolator;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
/**
* This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -176,6 +178,9 @@
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[SwipeHelper|interceptTouchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
final int action = ev.getAction();
switch (action) {
@@ -200,7 +205,7 @@
if (Math.abs(delta) > mPagingTouchSlop) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
- mInitialTouchPos = getPos(ev) - getTranslation(mCurrView);
+ mInitialTouchPos = pos - getTranslation(mCurrView);
}
}
break;
@@ -286,6 +291,10 @@
}
public boolean onTouchEvent(MotionEvent ev) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[SwipeHelper|touchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+
if (!mDragging) {
if (!onInterceptTouchEvent(ev)) {
return mCanCurrViewBeDimissed;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 9dd6c0b..7753d69 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -435,19 +435,12 @@
mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
// Compute the task rect
- if (RecentsConfiguration.getInstance().layoutVerticalStack) {
- int minHeight = (int) (mStackRect.height() -
- (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
- int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
- int centerX = mStackRect.centerX();
- mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
- centerX + size / 2, mStackRectSansPeek.top + size);
- } else {
- int size = Math.min(mStackRect.width(), mStackRect.height());
- int centerY = mStackRect.centerY();
- mTaskRect.set(mStackRectSansPeek.top, centerY - size / 2,
- mStackRectSansPeek.top + size, centerY + size / 2);
- }
+ int minHeight = (int) (mStackRect.height() -
+ (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
+ int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
+ int centerX = mStackRect.centerX();
+ mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
+ centerX + size / 2, mStackRectSansPeek.top + size);
// Update the scroll bounds
updateMinMaxScroll(false);
@@ -589,7 +582,6 @@
// Report that this tasks's data is no longer being used
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.unloadTaskData(task);
- tv.unbindFromTask();
// Detach the view from the hierarchy
detachViewFromParent(tv);
@@ -610,7 +602,6 @@
// Request that this tasks's data be filled
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.loadTaskData(task);
- tv.syncToTask();
// Find the index where this task should be placed in the children
int insertIndex = -1;
@@ -678,14 +669,13 @@
}
/* Handles touch events */
-class TaskStackViewTouchHandler {
+class TaskStackViewTouchHandler implements SwipeHelper.Callback {
static int INACTIVE_POINTER_ID = -1;
TaskStackView mSv;
VelocityTracker mVelocityTracker;
boolean mIsScrolling;
- boolean mIsSwiping;
int mInitialMotionX, mInitialMotionY;
int mLastMotionX, mLastMotionY;
@@ -697,21 +687,24 @@
int mMaximumVelocity;
// The scroll touch slop is used to calculate when we start scrolling
int mScrollTouchSlop;
- // The swipe touch slop is used to calculate when we start swiping left/right, this takes
- // precendence over the scroll touch slop in case the user makes a gesture that starts scrolling
- // but is intended to be a swipe
- int mSwipeTouchSlop;
- // After a certain amount of scrolling, we should start ignoring checks for swiping
- int mMaxScrollMotionToRejectSwipe;
+ // The page touch slop is used to calculate when we start swiping
+ float mPagingTouchSlop;
+
+ SwipeHelper mSwipeHelper;
+ boolean mInterceptedBySwipeHelper;
public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mScrollTouchSlop = configuration.getScaledTouchSlop();
- mSwipeTouchSlop = 2 * mScrollTouchSlop;
- mMaxScrollMotionToRejectSwipe = 4 * mScrollTouchSlop;
+ mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
mSv = sv;
+
+
+ float densityScale = context.getResources().getDisplayMetrics().density;
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
+ mSwipeHelper.setMinAlpha(1f);
}
/** Velocity tracker helpers */
@@ -754,11 +747,18 @@
"[TaskStackViewTouchHandler|interceptTouchEvent]",
Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ // Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
return false;
}
+ // Pass through to swipe helper if we are swiping
+ mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
+ if (mInterceptedBySwipeHelper) {
+ return true;
+ }
+
boolean wasScrolling = !mSv.mScroller.isFinished() ||
(mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
int action = ev.getAction();
@@ -777,7 +777,8 @@
mVelocityTracker.addMovement(ev);
// Check if the scroller is finished yet
mIsScrolling = !mSv.mScroller.isFinished();
- mIsSwiping = false;
+ // Enable HW layers
+ mSv.addHwLayersRefCount();
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -786,25 +787,7 @@
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
int x = (int) ev.getX(activePointerIndex);
- if (mActiveTaskView != null &&
- mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
- Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
- Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
- // Start swiping and stop scrolling
- mIsScrolling = false;
- mIsSwiping = true;
- System.out.println("SWIPING: " + mActiveTaskView);
- // Initialize the velocity tracker if necessary
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount();
- } else if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+ if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
// Save the touch move info
mIsScrolling = true;
// Initialize the velocity tracker if necessary
@@ -815,8 +798,6 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // Enable HW layers
- mSv.addHwLayersRefCount();
}
mLastMotionX = x;
@@ -829,16 +810,17 @@
mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
// Reset the drag state and the velocity tracker
mIsScrolling = false;
- mIsSwiping = false;
mActivePointerId = INACTIVE_POINTER_ID;
mActiveTaskView = null;
mTotalScrollMotion = 0;
recycleVelocityTracker();
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
break;
}
}
- return wasScrolling || mIsScrolling || mIsSwiping;
+ return wasScrolling || mIsScrolling;
}
/** Handles touch events once we have intercepted them */
@@ -853,6 +835,11 @@
return false;
}
+ // Pass through to swipe helper if we are swiping
+ if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
+ return true;
+ }
+
// Update the velocity tracker
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
@@ -871,7 +858,6 @@
// Initialize the velocity tracker
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
- // XXX: Set mIsScrolling or mIsSwiping?
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
@@ -886,28 +872,7 @@
int x = (int) ev.getX(activePointerIndex);
int y = (int) ev.getY(activePointerIndex);
int deltaY = mLastMotionY - y;
- int deltaX = x - mLastMotionX;
- if (!mIsSwiping) {
- if (mActiveTaskView != null &&
- mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
- Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
- Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
- mIsScrolling = false;
- mIsSwiping = true;
- System.out.println("SWIPING: " + mActiveTaskView);
- // Initialize the velocity tracker if necessary
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount();
- }
- }
- if (!mIsSwiping && !mIsScrolling) {
+ if (!mIsScrolling) {
if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
mIsScrolling = true;
// Initialize the velocity tracker
@@ -927,8 +892,6 @@
if (mSv.isScrollOutOfBounds()) {
mVelocityTracker.clear();
}
- } else if (mIsSwiping) {
- mActiveTaskView.setTranslationX(mActiveTaskView.getTranslationX() + deltaX);
}
mLastMotionX = x;
mLastMotionY = y;
@@ -936,107 +899,33 @@
break;
}
case MotionEvent.ACTION_UP: {
- if (mIsScrolling || mIsSwiping) {
- final TaskView activeTv = mActiveTaskView;
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if (mIsSwiping) {
- int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
- if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
- // Fling to dismiss
- int newScrollX = (int) (Math.signum(initialVelocity) *
- activeTv.getMeasuredWidth());
- int duration = Math.min(Constants.Values.TaskStackView.Animation.SwipeDismissDuration,
- (int) (Math.abs(newScrollX - activeTv.getScrollX()) *
- 1000f / Math.abs(initialVelocity)));
- activeTv.animate()
- .translationX(newScrollX)
- .alpha(0f)
- .setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- Task task = activeTv.getTask();
- Activity activity = (Activity) mSv.getContext();
-
- // We have to disable the listener to ensure that we
- // don't hit this again
- activeTv.animate().setListener(null);
-
- // Remove the task from the view
- mSv.mStack.removeTask(task);
-
- // Remove any stored data from the loader
- RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
- loader.deleteTaskData(task);
-
- // Remove the task from activity manager
- final ActivityManager am = (ActivityManager)
- activity.getSystemService(Context.ACTIVITY_SERVICE);
- if (am != null) {
- am.removeTask(activeTv.getTask().id,
- ActivityManager.REMOVE_TASK_KILL_PROCESS);
- }
-
- // If there are no remaining tasks, then just close the activity
- if (mSv.mStack.getTaskCount() == 0) {
- activity.finish();
- }
-
- // Disable HW layers
- mSv.decHwLayersRefCount();
- }
- })
- .start();
- // Enable HW layers
- mSv.addHwLayersRefCount();
- } else {
- // Animate it back into place
- // XXX: Make this animation a function of the velocity OR distance
- int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
- activeTv.animate()
- .translationX(0)
- .setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Disable HW layers
- mSv.decHwLayersRefCount();
- }
- })
- .start();
- // Enable HW layers
- mSv.addHwLayersRefCount();
- }
- } else {
- int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if ((Math.abs(velocity) > mMinimumVelocity)) {
- Console.log(Constants.DebugFlags.UI.TouchEvents,
- "[TaskStackViewTouchHandler|fling]",
- "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
- Console.AnsiGreen);
- // Enable HW layers on the stack
- mSv.addHwLayersRefCount();
- // Fling scroll
- mSv.mScroller.fling(0, mSv.getStackScroll(),
- 0, -velocity,
- 0, 0,
- mSv.mMinScroll, mSv.mMaxScroll,
- 0, 0);
- // Invalidate to kick off computeScroll
- mSv.invalidate();
- } else if (mSv.isScrollOutOfBounds()) {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
- }
- }
+ if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|fling]",
+ "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
+ Console.AnsiGreen);
+ // Enable HW layers on the stack
+ mSv.addHwLayersRefCount();
+ // Fling scroll
+ mSv.mScroller.fling(0, mSv.getStackScroll(),
+ 0, -velocity,
+ 0, 0,
+ mSv.mMinScroll, mSv.mMaxScroll,
+ 0, 0);
+ // Invalidate to kick off computeScroll
+ mSv.invalidate();
+ } else if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
- mIsSwiping = false;
mTotalScrollMotion = 0;
recycleVelocityTracker();
// Disable HW layers
@@ -1044,25 +933,14 @@
break;
}
case MotionEvent.ACTION_CANCEL: {
- if (mIsScrolling || mIsSwiping) {
- if (mIsSwiping) {
- // Animate it back into place
- // XXX: Make this animation a function of the velocity OR distance
- int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
- mActiveTaskView.animate()
- .translationX(0)
- .setDuration(duration)
- .start();
- } else {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
- }
+ if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
- mIsSwiping = false;
mTotalScrollMotion = 0;
recycleVelocityTracker();
// Disable HW layers
@@ -1072,4 +950,72 @@
}
return true;
}
+
+ /**** SwipeHelper Implementation ****/
+
+ @Override
+ public View getChildAtPosition(MotionEvent ev) {
+ return findViewAtPoint((int) ev.getX(), (int) ev.getY());
+ }
+
+ @Override
+ public boolean canChildBeDismissed(View v) {
+ return true;
+ }
+
+ @Override
+ public void onBeginDrag(View v) {
+ // Enable HW layers
+ mSv.addHwLayersRefCount();
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ @Override
+ public void onChildDismissed(View v) {
+ TaskView tv = (TaskView) v;
+ Task task = tv.getTask();
+ Activity activity = (Activity) mSv.getContext();
+
+ // We have to disable the listener to ensure that we
+ // don't hit this again
+ tv.animate().setListener(null);
+
+ // Remove the task from the view
+ mSv.mStack.removeTask(task);
+
+ // Remove any stored data from the loader
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ loader.deleteTaskData(task);
+
+ // Remove the task from activity manager
+ final ActivityManager am = (ActivityManager)
+ activity.getSystemService(Context.ACTIVITY_SERVICE);
+ if (am != null) {
+ am.removeTask(tv.getTask().id,
+ ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ }
+
+ // If there are no remaining tasks, then just close the activity
+ if (mSv.mStack.getTaskCount() == 0) {
+ activity.finish();
+ }
+
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
+ }
+
+ @Override
+ public void onSnapBackCompleted(View v) {
+ // Do Nothing
+ }
+
+ @Override
+ public void onDragCancelled(View v) {
+ // Disable HW layers
+ mSv.decHwLayersRefCount();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b1d0d13..9ef74ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -255,13 +255,13 @@
}
/** Actually synchronizes the model data into the views */
- void syncToTask() {
+ private void syncToTask() {
mThumbnailView.rebindToTask(mTask, false);
mIconView.rebindToTask(mTask, false);
}
/** Unset the task and callback */
- void unbindFromTask() {
+ private void unbindFromTask() {
mTask.setCallbacks(null);
mThumbnailView.unbindFromTask();
mIconView.unbindFromTask();
@@ -357,16 +357,16 @@
/** Enable the hw layers on this task view */
void enableHwLayers() {
- Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|enableHwLayers]");
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
/** Disable the hw layers on this task view */
void disableHwLayers() {
- Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|disableHwLayers]");
mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
}
+ /**** TaskCallbacks Implementation ****/
+
@Override
public void onTaskDataChanged(Task task) {
Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
@@ -380,6 +380,16 @@
}
@Override
+ public void onTaskBound() {
+ syncToTask();
+ }
+
+ @Override
+ public void onTaskUnbound() {
+ unbindFromTask();
+ }
+
+ @Override
public void onClick(View v) {
mCb.onTaskIconClicked(this);
}
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index b9b87b1..e45b98c 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -340,6 +340,13 @@
getWindowManager());
// Get the crop
RectF cropRect = mCropView.getCrop();
+
+ // Due to rounding errors in the cropview renderer the edges can be slightly offset
+ // therefore we ensure that the boundaries are sanely defined
+ cropRect.left = Math.max(0, cropRect.left);
+ cropRect.right = Math.min(mCropView.getWidth(), cropRect.right);
+ cropRect.top = Math.max(0, cropRect.top);
+ cropRect.bottom = Math.min(mCropView.getHeight(), cropRect.bottom);
int cropRotation = mCropView.getImageRotation();
float cropScale = mCropView.getWidth() / (float) cropRect.width();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 15a68ef..1cca164 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3417,18 +3417,22 @@
&& attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
- if (showWhenLocked && !mHideWindowBehindKeyguard) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
- mHideLockScreen = true;
- mForceStatusBarFromKeyguard = false;
- }
- if ((fl & FLAG_DISMISS_KEYGUARD) != 0
- && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
- mDismissKeyguard = mWinDismissingKeyguard == win ?
- DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
- mWinDismissingKeyguard = win;
- mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+ if (!mHideWindowBehindKeyguard) {
+ if (showWhenLocked) {
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ "Setting mHideLockScreen to true by win " + win);
+ mHideLockScreen = true;
+ mForceStatusBarFromKeyguard = false;
+ }
+ if ((fl & FLAG_DISMISS_KEYGUARD) != 0
+ && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+ if (DEBUG_LAYOUT) Slog.v(TAG,
+ "Setting mDismissKeyguard true by win " + win);
+ mDismissKeyguard = mWinDismissingKeyguard == win ?
+ DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+ mWinDismissingKeyguard = win;
+ mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+ }
}
if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
mAllowLockscreenWhenOn = true;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 3dcb488..e6163bd 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -457,6 +457,9 @@
* @param userId the new active user's UserId
*/
private void switchUser(int userId) {
+ if (mCurrentUserId == userId) {
+ return;
+ }
mBlacklist.switchUser(userId);
mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index ad693d0..94f699f 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -173,7 +173,9 @@
mDeskModeKeepsScreenOn = (context.getResources().getInteger(
com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
mTelevision = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEVISION);
+ PackageManager.FEATURE_TELEVISION) ||
+ context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK);
mNightMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cd9c920..ab7d60a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3319,20 +3319,35 @@
return;
}
// Remove any existing entries that are the same kind of task.
+ final Intent intent = task.intent;
+ final boolean document = intent != null && intent.isDocument();
for (int i=0; i<N; i++) {
TaskRecord tr = mRecentTasks.get(i);
- if (task.userId == tr.userId
- && ((task.affinity != null && task.affinity.equals(tr.affinity))
- || (task.intent != null && task.intent.filterEquals(tr.intent)))) {
- tr.disposeThumbnail();
- mRecentTasks.remove(i);
- i--;
- N--;
- if (task.intent == null) {
- // If the new recent task we are adding is not fully
- // specified, then replace it with the existing recent task.
- task = tr;
+ if (task != tr) {
+ if (task.userId != tr.userId) {
+ continue;
}
+ final Intent trIntent = tr.intent;
+ if ((task.affinity == null || !task.affinity.equals(tr.affinity)) &&
+ (intent == null || !intent.filterEquals(trIntent))) {
+ continue;
+ }
+ if (document || trIntent != null && trIntent.isDocument()) {
+ // Document tasks do not match other tasks.
+ continue;
+ }
+ }
+
+ // Either task and tr are the same or, their affinities match or their intents match
+ // and neither of them is a document.
+ tr.disposeThumbnail();
+ mRecentTasks.remove(i);
+ i--;
+ N--;
+ if (task.intent == null) {
+ // If the new recent task we are adding is not fully
+ // specified, then replace it with the existing recent task.
+ task = tr;
}
}
if (N >= MAX_RECENT_TASKS) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 34cc22a..25292a0 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -492,6 +492,9 @@
cls = new ComponentName(info.packageName, info.targetActivity);
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
+ boolean isDocument = intent != null & intent.isDocument();
+ // If documentData is non-null then it must match the existing task data.
+ Uri documentData = isDocument ? intent.getData() : null;
if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -508,23 +511,39 @@
continue;
}
+ final Intent taskIntent = task.intent;
+ final Intent affinityIntent = task.affinityIntent;
+ final boolean taskIsDocument;
+ final Uri taskDocumentData;
+ if (taskIntent != null && taskIntent.isDocument()) {
+ taskIsDocument = true;
+ taskDocumentData = taskIntent.getData();
+ } else if (affinityIntent != null && affinityIntent.isDocument()) {
+ taskIsDocument = true;
+ taskDocumentData = affinityIntent.getData();
+ } else {
+ taskIsDocument = false;
+ taskDocumentData = null;
+ }
+
if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
- + r.task.intent.getComponent().flattenToShortString()
+ + taskIntent.getComponent().flattenToShortString()
+ "/aff=" + r.task.affinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
- if (task.affinity != null) {
- if (task.affinity.equals(info.taskAffinity)) {
+ if (!isDocument && !taskIsDocument && task.affinity != null) {
+ if (task.affinity.equals(target.taskAffinity)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
return r;
}
- } else if (task.intent != null && task.intent.getComponent().equals(cls)) {
+ } else if (taskIntent != null && taskIntent.getComponent().equals(cls) &&
+ Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
- } else if (task.affinityIntent != null
- && task.affinityIntent.getComponent().equals(cls)) {
+ } else if (affinityIntent != null && affinityIntent.getComponent().equals(cls) &&
+ Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
@@ -1857,7 +1876,7 @@
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags()
- &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+ & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
@@ -2006,14 +2025,7 @@
+ " out to new task " + target.task);
}
- if (clearWhenTaskReset) {
- // This is the start of a new sub-task.
- if (target.thumbHolder == null) {
- target.thumbHolder = new ThumbnailHolder();
- }
- } else {
- target.thumbHolder = newThumbHolder;
- }
+ target.thumbHolder = newThumbHolder;
final int targetTaskId = targetTask.taskId;
mWindowManager.setAppGroupId(target.appToken, targetTaskId);
@@ -2484,7 +2496,7 @@
final int index = activities.indexOf(r);
if (index < (activities.size() - 1)) {
task.setFrontOfTask();
- if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
+ if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
// If the caller asked that this activity (and all above it)
// be cleared when the task is reset, don't lose that information,
// but propagate it up to the next activity.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9315648..3555993 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.Manifest.permission.START_ANY_ACTIVITY;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -1202,6 +1203,19 @@
resultRecord.removeResultsLocked(
sourceRecord, resultWho, requestCode);
}
+ if (sourceRecord.launchedFromUid == callingUid) {
+ // The new activity is being launched from the same uid as the previous
+ // activity in the flow, and asking to forward its result back to the
+ // previous. In this case the activity is serving as a trampoline between
+ // the two, so we also want to update its launchedFromPackage to be the
+ // same as the previous activity. Note that this is safe, since we know
+ // these two packages come from the same uid; the caller could just as
+ // well have supplied that same package name itself. This specifially
+ // deals with the case of an intent picker/chooser being launched in the app
+ // flow to redirect to an activity picked by the user, where we want the final
+ // activity to consider it to have been launched by the previous app activity.
+ callingPackage = sourceRecord.launchedFromPackage;
+ }
}
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
@@ -1430,14 +1444,20 @@
}
}
+ final boolean newDocument = intent.isDocument();
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
- if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+ if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
"Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
+ } else if (newDocument) {
+ if (r.launchMode != ActivityInfo.LAUNCH_MULTIPLE) {
+ Slog.w(TAG, "FLAG_ACTIVITY_NEW_DOCUMENT and launchMode != \"standard\"");
+ r.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+ }
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
@@ -1460,7 +1480,7 @@
// so we don't want to blindly throw it in to that task. Instead we will take
// the NEW_TASK flow and try to find a task for it. But save the task information
// so it can be used when creating the new task.
- if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+ if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from finishing " + sourceRecord
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -1476,7 +1496,7 @@
sourceStack = null;
}
- if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
// is pretty messed up, so instead immediately send back a cancel
@@ -1493,8 +1513,8 @@
boolean movedHome = false;
TaskRecord reuseTask = null;
ActivityStack targetStack;
- if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
- (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
+ if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
+ (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// If bring to front is requested, and no result is requested, and
@@ -1683,7 +1703,7 @@
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
- if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
+ if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b925856..efbfb33 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -90,6 +90,7 @@
private static final int MSG_SYSTEM_READY = 3;
private static final int MSG_BOOT_COMPLETED = 4;
private static final int MSG_USER_SWITCHED = 5;
+ private static final int MSG_START_ACCESSORY_MODE = 6;
private static final int AUDIO_MODE_NONE = 0;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -152,7 +153,7 @@
mHandler.updateState(state);
} else if ("START".equals(accessory)) {
if (DEBUG) Slog.d(TAG, "got accessory start");
- startAccessoryMode();
+ mHandler.sendEmptyMessage(MSG_START_ACCESSORY_MODE);
}
}
};
@@ -170,7 +171,7 @@
if (nativeIsStartRequested()) {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");
- startAccessoryMode();
+ mHandler.sendEmptyMessage(MSG_START_ACCESSORY_MODE);
}
boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
@@ -232,6 +233,8 @@
functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
}
+ if (DEBUG) Slog.d(TAG, "startAccessoryMode: " + functions);
+
if (functions != null) {
mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
setCurrentFunctions(functions, false);
@@ -306,6 +309,7 @@
// current USB state
private boolean mConnected;
private boolean mConfigured;
+ private boolean mAccessoryStartPending;
private String mCurrentFunctions;
private String mDefaultFunctions;
private UsbAccessory mCurrentAccessory;
@@ -612,6 +616,11 @@
case MSG_UPDATE_STATE:
mConnected = (msg.arg1 == 1);
mConfigured = (msg.arg2 == 1);
+
+ if (!mConnected) {
+ mAccessoryStartPending = false;
+ }
+
updateUsbNotification();
updateAdbNotification();
if (containsFunction(mCurrentFunctions,
@@ -625,6 +634,10 @@
updateUsbState();
updateAudioSourceFunction();
}
+ if (mConnected && mConfigured && mAccessoryStartPending) {
+ startAccessoryMode();
+ mAccessoryStartPending = false;
+ }
break;
case MSG_ENABLE_ADB:
setAdbEnabled(msg.arg1 == 1);
@@ -661,6 +674,16 @@
mCurrentUser = msg.arg1;
break;
}
+ case MSG_START_ACCESSORY_MODE:
+ if (mConnected && mConfigured) {
+ startAccessoryMode();
+ } else {
+ // we sometimes receive the kernel "accessory start" uevent
+ // before the "configured" uevent. In this case we need to defer
+ // handling this event until after we received the configured event
+ mAccessoryStartPending = true;
+ }
+ break;
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 6666385..b235408 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -142,6 +142,13 @@
}
@LayoutlibDelegate
+ /*package*/ static boolean native_isConvex(long nPath) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Path.isConvex is not supported.", null, null);
+ return true;
+ }
+
+ @LayoutlibDelegate
/*package*/ static int native_getFillType(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index d40352f..b16b4aa 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -18,6 +18,7 @@
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.ibm.icu.text.DateTimePatternGenerator;
+import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ULocale;
import java.util.Locale;
@@ -117,6 +118,11 @@
}
@LayoutlibDelegate
+ /*package*/ static int getCurrencyNumericCode(String currencyCode) {
+ return Currency.getInstance(currencyCode).getNumericCode();
+ }
+
+ @LayoutlibDelegate
/*package*/ static String getCurrencySymbol(String locale, String currencyCode) {
return "";
}
@@ -231,7 +237,7 @@
result.percent = '%';
result.perMill = '\u2030';
result.monetarySeparator = ' ';
- result.minusSign = '-';
+ result.minusSign = "-";
result.exponentSeparator = "e";
result.infinity = "\u221E";
result.NaN = "NaN";