Merge "Don't wait for the MountService to be ready when encrypting"
diff --git a/Android.mk b/Android.mk
index fad3f13..f0828b7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,12 @@
core/java/android/content/pm/IPackageMoveObserver.aidl \
core/java/android/content/pm/IPackageStatsObserver.aidl \
core/java/android/database/IContentObserver.aidl \
+ core/java/android/hardware/ICameraService.aidl \
+ core/java/android/hardware/ICameraServiceListener.aidl \
+ core/java/android/hardware/ICamera.aidl \
+ core/java/android/hardware/ICameraClient.aidl \
+ core/java/android/hardware/IProCameraUser.aidl \
+ core/java/android/hardware/IProCameraCallbacks.aidl \
core/java/android/hardware/ISerialManager.aidl \
core/java/android/hardware/display/IDisplayManager.aidl \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index f13c80aa2..224a529c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -642,6 +642,7 @@
field public static final int layout = 16842994; // 0x10100f2
field public static final int layoutAnimation = 16842988; // 0x10100ec
field public static final int layoutDirection = 16843698; // 0x10103b2
+ field public static final int layoutMode = 16843738; // 0x10103da
field public static final int layout_above = 16843140; // 0x1010184
field public static final int layout_alignBaseline = 16843142; // 0x1010186
field public static final int layout_alignBottom = 16843146; // 0x101018a
@@ -3845,6 +3846,23 @@
field public static final int DEFAULT_LIGHTS = 4; // 0x4
field public static final int DEFAULT_SOUND = 1; // 0x1
field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
+ field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
+ field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
+ field public static final java.lang.String EXTRA_PEOPLE = "android.people";
+ field public static final java.lang.String EXTRA_PICTURE = "android.picture";
+ field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
+ field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
+ field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
+ field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
+ field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
+ field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
+ field public static final java.lang.String EXTRA_SUB_TEXT = "android.subText";
+ field public static final java.lang.String EXTRA_SUMMARY_TEXT = "android.summaryText";
+ field public static final java.lang.String EXTRA_TEXT = "android.text";
+ field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final java.lang.String EXTRA_TITLE = "android.title";
+ field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
@@ -3859,12 +3877,14 @@
field public static final int PRIORITY_MAX = 2; // 0x2
field public static final int PRIORITY_MIN = -2; // 0xfffffffe
field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+ field public android.app.Notification.Action[] actions;
field public int audioStreamType;
field public android.widget.RemoteViews bigContentView;
field public android.app.PendingIntent contentIntent;
field public android.widget.RemoteViews contentView;
field public int defaults;
field public android.app.PendingIntent deleteIntent;
+ field public android.os.Bundle extras;
field public int flags;
field public android.app.PendingIntent fullScreenIntent;
field public int icon;
@@ -3882,6 +3902,18 @@
field public long when;
}
+ public static class Notification.Action implements android.os.Parcelable {
+ ctor public Notification.Action();
+ ctor public Notification.Action(int, java.lang.CharSequence, android.app.PendingIntent);
+ method public android.app.Notification.Action clone();
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public android.app.PendingIntent actionIntent;
+ field public int icon;
+ field public java.lang.CharSequence title;
+ }
+
public static class Notification.BigPictureStyle extends android.app.Notification.Style {
ctor public Notification.BigPictureStyle();
ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
@@ -3914,6 +3946,7 @@
method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
method public android.app.Notification.Builder setDefaults(int);
method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
+ method public android.app.Notification.Builder setExtras(android.os.Bundle);
method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
method public android.app.Notification.Builder setLights(int, int, int);
@@ -5703,6 +5736,7 @@
field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth";
+ field public static final java.lang.String CAMERA_SERVICE = "camera";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -8970,8 +9004,10 @@
field public static final int JPEG = 256; // 0x100
field public static final int NV16 = 16; // 0x10
field public static final int NV21 = 17; // 0x11
+ field public static final int RAW_SENSOR = 513; // 0x201
field public static final int RGB_565 = 4; // 0x4
field public static final int UNKNOWN = 0; // 0x0
+ field public static final int YUV_420_888 = 35; // 0x23
field public static final int YUY2 = 20; // 0x14
field public static final int YV12 = 842094169; // 0x32315659
}
@@ -9099,6 +9135,7 @@
}
public class NinePatch {
+ ctor public NinePatch(android.graphics.Bitmap, byte[]);
ctor public NinePatch(android.graphics.Bitmap, byte[], java.lang.String);
method public void draw(android.graphics.Canvas, android.graphics.RectF);
method public void draw(android.graphics.Canvas, android.graphics.Rect);
@@ -9859,6 +9896,7 @@
method public synchronized boolean canConstantState();
method protected void computeConstantSize();
method public int getChangingConfigurations();
+ method public final android.graphics.drawable.Drawable getChild(int);
method public final int getChildCount();
method public final android.graphics.drawable.Drawable[] getChildren();
method public final int getConstantHeight();
@@ -10593,6 +10631,133 @@
}
+package android.hardware.photography {
+
+ public class CameraAccessException extends java.lang.Exception {
+ ctor public CameraAccessException(int);
+ ctor public CameraAccessException(int, java.lang.String);
+ ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable);
+ ctor public CameraAccessException(int, java.lang.Throwable);
+ method public final int getReason();
+ field public static final int CAMERA_DISABLED = 3; // 0x3
+ field public static final int CAMERA_DISCONNECTED = 4; // 0x4
+ field public static final int CAMERA_IN_USE = 1; // 0x1
+ field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2
+ }
+
+ public final class CameraDevice implements java.lang.AutoCloseable {
+ ctor public CameraDevice();
+ method public void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public void close();
+ method public void configureOutputs(java.util.List<android.view.Surface>);
+ method public android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
+ method public android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
+ method public void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
+ method public void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public void stopRepeating() throws android.hardware.photography.CameraAccessException;
+ method public void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
+ field public static final int TEMPLATE_MANUAL = 5; // 0x5
+ field public static final int TEMPLATE_PREVIEW = 1; // 0x1
+ field public static final int TEMPLATE_RECORD = 2; // 0x2
+ field public static final int TEMPLATE_STILL_CAPTURE = 3; // 0x3
+ field public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; // 0x4
+ }
+
+ public static abstract interface CameraDevice.CaptureListener {
+ method public abstract void onCaptureComplete(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest, android.hardware.photography.CaptureResult);
+ method public abstract void onCaptureFailed(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest);
+ }
+
+ public static abstract interface CameraDevice.ErrorListener {
+ method public abstract void onCameraDeviceError(android.hardware.photography.CameraDevice, int);
+ field public static final int DEVICE_DISCONNECTED = 1; // 0x1
+ field public static final int DEVICE_ERROR = 2; // 0x2
+ field public static final int SERVICE_ERROR = 3; // 0x3
+ }
+
+ public final class CameraManager {
+ method public android.hardware.photography.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.photography.CameraAccessException;
+ method public java.lang.String[] getDeviceIdList();
+ method public android.hardware.photography.CameraDevice openCamera(java.lang.String) throws android.hardware.photography.CameraAccessException;
+ method public void registerCameraListener(android.hardware.photography.CameraManager.CameraListener);
+ method public void unregisterCameraListener(android.hardware.photography.CameraManager.CameraListener);
+ }
+
+ public static abstract interface CameraManager.CameraListener {
+ method public abstract void onCameraAvailable(java.lang.String);
+ method public abstract void onCameraUnavailable(java.lang.String);
+ }
+
+ public class CameraMetadata implements android.os.Parcelable {
+ ctor public CameraMetadata();
+ method public int describeContents();
+ method public T get(android.hardware.photography.CameraMetadata.Key<T>);
+ method public void set(android.hardware.photography.CameraMetadata.Key<T>, T);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public static class CameraMetadata.Key {
+ ctor public CameraMetadata.Key(java.lang.String);
+ method public final boolean equals(java.lang.Object);
+ method public final java.lang.String getName();
+ method public final int hashCode();
+ }
+
+ public final class CameraProperties extends android.hardware.photography.CameraMetadata {
+ ctor public CameraProperties();
+ field public static final android.hardware.photography.CameraMetadata.Key INFO_IDENTIFIER;
+ field public static final android.hardware.photography.CameraMetadata.Key INFO_MODEL;
+ field public static final android.hardware.photography.CameraMetadata.Key INFO_REMOVABLE;
+ field public static final android.hardware.photography.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL;
+ field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
+ field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
+ field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_FORMATS;
+ field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_JPEG_SIZES;
+ field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_PROCESSED_SIZES;
+ field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_RAW_SIZES;
+ field public static final android.hardware.photography.CameraMetadata.Key SENSOR_ACTIVE_ARRAY_SIZE;
+ field public static final android.hardware.photography.CameraMetadata.Key SENSOR_PIXEL_ARRAY_SIZE;
+ }
+
+ public final class CaptureRequest extends android.hardware.photography.CameraMetadata {
+ method public void addTarget(android.view.Surface);
+ method public void removeTarget(android.view.Surface);
+ field public static final android.hardware.photography.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
+ field public static final android.hardware.photography.CameraMetadata.Key SENSOR_SENSITIVITY;
+ }
+
+ public final class CaptureResult extends android.hardware.photography.CameraMetadata {
+ field public static final android.hardware.photography.CameraMetadata.Key CONTROL_AE_STATE;
+ field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2
+ field public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4; // 0x4
+ field public static final int CONTROL_AE_STATE_INACTIVE = 0; // 0x0
+ field public static final int CONTROL_AE_STATE_LOCKED = 3; // 0x3
+ field public static final int CONTROL_AE_STATE_PRECAPTURE = 5; // 0x5
+ field public static final int CONTROL_AE_STATE_SEARCHING = 1; // 0x1
+ field public static final android.hardware.photography.CameraMetadata.Key SENSOR_TIMESTAMP;
+ field public static final android.hardware.photography.CameraMetadata.Key STATISTICS_DETECTED_FACES;
+ }
+
+ public static class CaptureResult.Face {
+ ctor public CaptureResult.Face();
+ method public android.graphics.Rect getBounds();
+ method public int getId();
+ method public android.graphics.Point getLeftEye();
+ method public android.graphics.Point getMouth();
+ method public android.graphics.Point getRightEye();
+ method public int getScore();
+ }
+
+ public final class Size {
+ method public final int getHeight();
+ method public final int getWidth();
+ }
+
+}
+
package android.hardware.usb {
public class UsbAccessory implements android.os.Parcelable {
@@ -11629,6 +11794,40 @@
field public static final int EULER_Z = 2; // 0x2
}
+ public abstract class Image implements java.lang.AutoCloseable {
+ ctor public Image();
+ method public abstract void close();
+ method protected final void finalize();
+ method public int getFormat();
+ method public int getHeight();
+ method public android.media.Image.Plane[] getPlanes();
+ method public long getTimestamp();
+ method public int getWidth();
+ }
+
+ public static final class Image.Plane {
+ ctor public Image.Plane();
+ method public java.nio.ByteBuffer getBuffer();
+ method public int getPixelStride();
+ method public int getRowStride();
+ }
+
+ public final class ImageReader {
+ ctor public ImageReader(int, int, int, int);
+ method public int getHeight();
+ method public int getImageFormat();
+ method public int getMaxImages();
+ method public android.media.Image getNextImage();
+ method public android.view.Surface getSurface();
+ method public int getWidth();
+ method public void releaseImage(android.media.Image);
+ method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener);
+ }
+
+ public static abstract interface ImageReader.OnImageAvailableListener {
+ method public abstract void onImageAvailable(android.media.ImageReader);
+ }
+
public class JetPlayer {
method public boolean clearQueue();
method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -11952,6 +12151,7 @@
ctor public MediaExtractor();
method public boolean advance();
method public long getCachedDuration();
+ method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
method public long getSampleTime();
@@ -21551,6 +21751,7 @@
public final class SynthesisRequest {
ctor public SynthesisRequest(java.lang.String, android.os.Bundle);
+ method public int getCallerUid();
method public java.lang.String getCountry();
method public java.lang.String getLanguage();
method public android.os.Bundle getParams();
@@ -25565,6 +25766,7 @@
}
public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
+ method public static java.lang.String actionToString(int);
method public final void addBatch(long, float, float, float, float, int);
method public final void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
method public static int axisFromString(java.lang.String);
@@ -26143,6 +26345,7 @@
method public float getY();
method public boolean hasFocus();
method public boolean hasFocusable();
+ method public boolean hasLayout();
method public boolean hasOnClickListeners();
method public boolean hasOverlappingRendering();
method public boolean hasTransientState();
@@ -26155,6 +26358,7 @@
method public void invalidate();
method public void invalidateDrawable(android.graphics.drawable.Drawable);
method public boolean isActivated();
+ method public boolean isAttachedToWindow();
method public boolean isClickable();
method public boolean isDirty();
method public boolean isDrawingCacheEnabled();
@@ -27279,6 +27483,7 @@
method public int describeContents();
method public static java.lang.String eventTypeToString(int);
method public int getAction();
+ method public int getContentChangeType();
method public long getEventTime();
method public int getEventType();
method public int getMovementGranularity();
@@ -27290,11 +27495,14 @@
method public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
method public static android.view.accessibility.AccessibilityEvent obtain();
method public void setAction(int);
+ method public void setContentChangeType(int);
method public void setEventTime(long);
method public void setEventType(int);
method public void setMovementGranularity(int);
method public void setPackageName(java.lang.CharSequence);
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CONTENT_CHANGE_TYPE_NODE = 1; // 0x1
+ field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0; // 0x0
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int INVALID_POSITION = -1; // 0xffffffff
field public static final deprecated int MAX_TEXT_LENGTH = 500; // 0x1f4
@@ -27356,10 +27564,12 @@
method public int getActions();
method public void getBoundsInParent(android.graphics.Rect);
method public void getBoundsInScreen(android.graphics.Rect);
+ method public android.os.Bundle getBundle();
method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
method public int getChildCount();
method public java.lang.CharSequence getClassName();
method public java.lang.CharSequence getContentDescription();
+ method public int getInputType();
method public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
method public int getMovementGranularities();
@@ -27403,6 +27613,7 @@
method public void setEnabled(boolean);
method public void setFocusable(boolean);
method public void setFocused(boolean);
+ method public void setInputType(int);
method public void setLabelFor(android.view.View);
method public void setLabelFor(android.view.View, int);
method public void setLabeledBy(android.view.View);
@@ -27763,10 +27974,10 @@
method public void setAlpha(float);
method public void setTransformationType(int);
method public java.lang.String toShortString();
- field public static int TYPE_ALPHA;
- field public static int TYPE_BOTH;
- field public static int TYPE_IDENTITY;
- field public static int TYPE_MATRIX;
+ field public static final int TYPE_ALPHA = 1; // 0x1
+ field public static final int TYPE_BOTH = 3; // 0x3
+ field public static final int TYPE_IDENTITY = 0; // 0x0
+ field public static final int TYPE_MATRIX = 2; // 0x2
field protected float mAlpha;
field protected android.graphics.Matrix mMatrix;
field protected int mTransformationType;
@@ -28195,7 +28406,15 @@
public class Crossfade extends android.view.transition.Transition {
ctor public Crossfade();
method protected void captureValues(android.view.transition.TransitionValues, boolean);
+ method public int getFadeBehavior();
+ method public int getResizeBehavior();
method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
+ method public void setFadeBehavior(int);
+ method public void setResizeBehavior(int);
+ field public static final int FADE_BEHAVIOR_CROSSFADE = 0; // 0x0
+ field public static final int FADE_BEHAVIOR_REVEAL = 1; // 0x1
+ field public static final int RESIZE_BEHAVIOR_NONE = 0; // 0x0
+ field public static final int RESIZE_BEHAVIOR_SCALE = 1; // 0x1
}
public class Fade extends android.view.transition.Visibility {
@@ -28297,6 +28516,7 @@
public class TransitionManager {
ctor public TransitionManager();
+ method public static void beginDelayedTransition(android.view.ViewGroup, android.view.transition.Transition);
method public android.view.transition.Transition getDefaultTransition();
method public static void go(android.view.transition.Scene);
method public static void go(android.view.transition.Scene, android.view.transition.Transition);
@@ -33148,7 +33368,7 @@
method protected final void setSigners(java.lang.Class<?>, java.lang.Object[]);
}
- public class ClassNotFoundException extends java.lang.Exception {
+ public class ClassNotFoundException extends java.lang.ReflectiveOperationException {
ctor public ClassNotFoundException();
ctor public ClassNotFoundException(java.lang.String);
ctor public ClassNotFoundException(java.lang.String, java.lang.Throwable);
@@ -33290,7 +33510,7 @@
ctor public IllegalAccessError(java.lang.String);
}
- public class IllegalAccessException extends java.lang.Exception {
+ public class IllegalAccessException extends java.lang.ReflectiveOperationException {
ctor public IllegalAccessException();
ctor public IllegalAccessException(java.lang.String);
}
@@ -33339,7 +33559,7 @@
ctor public InstantiationError(java.lang.String);
}
- public class InstantiationException extends java.lang.Exception {
+ public class InstantiationException extends java.lang.ReflectiveOperationException {
ctor public InstantiationException();
ctor public InstantiationException(java.lang.String);
}
@@ -33516,7 +33736,7 @@
ctor public NoSuchFieldError(java.lang.String);
}
- public class NoSuchFieldException extends java.lang.Exception {
+ public class NoSuchFieldException extends java.lang.ReflectiveOperationException {
ctor public NoSuchFieldException();
ctor public NoSuchFieldException(java.lang.String);
}
@@ -33526,7 +33746,7 @@
ctor public NoSuchMethodError(java.lang.String);
}
- public class NoSuchMethodException extends java.lang.Exception {
+ public class NoSuchMethodException extends java.lang.ReflectiveOperationException {
ctor public NoSuchMethodException();
ctor public NoSuchMethodException(java.lang.String);
}
@@ -33621,6 +33841,13 @@
method public abstract int read(java.nio.CharBuffer) throws java.io.IOException;
}
+ public class ReflectiveOperationException extends java.lang.Exception {
+ ctor public ReflectiveOperationException();
+ ctor public ReflectiveOperationException(java.lang.String);
+ ctor public ReflectiveOperationException(java.lang.Throwable);
+ ctor public ReflectiveOperationException(java.lang.String, java.lang.Throwable);
+ }
+
public abstract interface Runnable {
method public abstract void run();
}
@@ -34387,7 +34614,7 @@
method public abstract java.lang.Object invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) throws java.lang.Throwable;
}
- public class InvocationTargetException extends java.lang.Exception {
+ public class InvocationTargetException extends java.lang.ReflectiveOperationException {
ctor protected InvocationTargetException();
ctor public InvocationTargetException(java.lang.Throwable);
ctor public InvocationTargetException(java.lang.Throwable, java.lang.String);
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index de58a33..059945f 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -58,6 +58,18 @@
* developer guide.</p>
* </div>
*
+ * @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes
+ * @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType
+ * @attr ref android.R.styleable#AccessibilityService_accessibilityFlags
+ * @attr ref android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility
+ * @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
+ * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
+ * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent
+ * @attr ref android.R.styleable#AccessibilityService_description
+ * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
+ * @attr ref android.R.styleable#AccessibilityService_packageNames
+ * @attr ref android.R.styleable#AccessibilityService_settingsActivity
+ *
* @see AccessibilityService
* @see android.view.accessibility.AccessibilityEvent
* @see android.view.accessibility.AccessibilityManager
@@ -68,23 +80,27 @@
/**
* Capability: This accessibility service can retrieve the active window content.
+ * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent
*/
public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001;
/**
* Capability: This accessibility service can request touch exploration mode in which
* touched items are spoken aloud and the UI can be explored via gestures.
+ * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
*/
public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002;
/**
* Capability: This accessibility service can request enhanced web accessibility
* enhancements. For example, installing scripts to make app content more accessible.
+ * @see android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility
*/
public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004;
/**
- * Capability: This accessibility service can request to filter the key event stream.
+ * Capability: This accessibility service can request to filter the key event stream.
+ * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
*/
public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008;
@@ -213,6 +229,7 @@
* the first time they are run, if this flag is specified, a dialog is
* shown to the user to confirm enabling explore by touch.
* </p>
+ * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
*/
public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
@@ -232,6 +249,7 @@
* true, otherwise this flag will be ignored. For how to declare the meta-data
* of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
* </p>
+ * @see android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility
*/
public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008;
@@ -260,6 +278,7 @@
* otherwise this flag will be ignored. For how to declare the meta-data
* of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
* </p>
+ * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents
*/
public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3fc82fa..7968431 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -49,6 +49,7 @@
import android.hardware.ISerialManager;
import android.hardware.SerialManager;
import android.hardware.SystemSensorManager;
+import android.hardware.photography.CameraManager;
import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.hardware.usb.IUsbManager;
@@ -513,12 +514,16 @@
}});
registerService(WINDOW_SERVICE, new ServiceFetcher() {
+ Display mDefaultDisplay;
public Object getService(ContextImpl ctx) {
Display display = ctx.mDisplay;
if (display == null) {
- DisplayManager dm = (DisplayManager)ctx.getOuterContext().getSystemService(
- Context.DISPLAY_SERVICE);
- display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ if (mDefaultDisplay == null) {
+ DisplayManager dm = (DisplayManager)ctx.getOuterContext().
+ getSystemService(Context.DISPLAY_SERVICE);
+ mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ }
+ display = mDefaultDisplay;
}
return new WindowManagerImpl(display);
}});
@@ -536,6 +541,11 @@
IAppOpsService service = IAppOpsService.Stub.asInterface(b);
return new AppOpsManager(ctx, service);
}});
+
+ registerService(CAMERA_SERVICE, new StaticServiceFetcher() {
+ public Object createStaticService() {
+ return new CameraManager();
+ }});
}
static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 634fa30..cda2c5f 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -306,6 +306,7 @@
* method to do cleanup when the dialog is dismissed, instead implement
* that in {@link #onStop}.
*/
+ @Override
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
@@ -325,7 +326,7 @@
}
try {
- mWindowManager.removeView(mDecor);
+ mWindowManager.removeViewImmediate(mDecor);
} finally {
if (mActionMode != null) {
mActionMode.finish();
@@ -334,7 +335,7 @@
mWindow.closeAllPanels();
onStop();
mShowing = false;
-
+
sendDismissMessage();
}
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 10ea109..72c9156 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1169,7 +1169,7 @@
if (!fragment.mHidden) {
fragment.mHidden = true;
if (fragment.mView != null) {
- Animator anim = loadAnimator(fragment, transition, true,
+ Animator anim = loadAnimator(fragment, transition, false,
transitionStyle);
if (anim != null) {
anim.setTarget(fragment.mView);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fb28ae3..bffbb51 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -432,51 +432,32 @@
/**
* Additional semantic data to be carried around with this Notification.
- * @hide
*/
public Bundle extras = new Bundle();
// extras keys for Builder inputs
- /** @hide */
public static final String EXTRA_TITLE = "android.title";
- /** @hide */
public static final String EXTRA_TITLE_BIG = EXTRA_TITLE + ".big";
- /** @hide */
public static final String EXTRA_TEXT = "android.text";
- /** @hide */
public static final String EXTRA_SUB_TEXT = "android.subText";
- /** @hide */
public static final String EXTRA_INFO_TEXT = "android.infoText";
- /** @hide */
public static final String EXTRA_SUMMARY_TEXT = "android.summaryText";
- /** @hide */
public static final String EXTRA_SMALL_ICON = "android.icon";
- /** @hide */
public static final String EXTRA_LARGE_ICON = "android.largeIcon";
- /** @hide */
public static final String EXTRA_LARGE_ICON_BIG = EXTRA_LARGE_ICON + ".big";
- /** @hide */
public static final String EXTRA_PROGRESS = "android.progress";
- /** @hide */
public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
- /** @hide */
public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
- /** @hide */
public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
- /** @hide */
public static final String EXTRA_SHOW_WHEN = "android.showWhen";
- /** @hide from BigPictureStyle */
public static final String EXTRA_PICTURE = "android.picture";
- /** @hide from InboxStyle */
public static final String EXTRA_TEXT_LINES = "android.textLines";
// extras keys for other interesting pieces of information
- /** @hide */
public static final String EXTRA_PEOPLE = "android.people";
/**
* Structure to encapsulate an "action", including title and icon, that can be attached to a Notification.
- * @hide
*/
public static class Action implements Parcelable {
public int icon;
@@ -530,9 +511,6 @@
};
}
- /**
- * @hide
- */
public Action[] actions;
/**
@@ -1450,7 +1428,6 @@
* called.
*
* @see Notification#extras
- * @hide
*/
public Builder setExtras(Bundle bag) {
mExtras = bag;
@@ -1719,6 +1696,9 @@
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
+ if (mLargeIcon != null) {
+ extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
+ }
}
/**
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 3a355f9..f104d71 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -109,7 +109,7 @@
break;
}
case HANDLE_PROVIDERS_CHANGED: {
- onProvidersChanged(msg.arg1);
+ onProvidersChanged();
break;
}
case HANDLE_VIEW_DATA_CHANGED: {
@@ -396,14 +396,6 @@
* are added, updated or removed, or widget components are enabled or disabled.)
*/
protected void onProvidersChanged() {
- onProvidersChanged(mContext.getUserId());
- }
-
- /**
- * Private method containing a userId
- * @hide
- */
- protected void onProvidersChanged(int userId) {
// Does nothing
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 81d6f0b..35e51a6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2284,6 +2284,16 @@
public static final String APP_OPS_SERVICE = "appops";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.hardware.photography.CameraManager} for interacting with
+ * camera devices.
+ *
+ * @see #getSystemService
+ * @see android.hardware.camera.CameraManager
+ */
+ public static final String CAMERA_SERVICE = "camera";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/SyncResult.java b/core/java/android/content/SyncResult.java
index 8b0afbd..6cb0d02 100644
--- a/core/java/android/content/SyncResult.java
+++ b/core/java/android/content/SyncResult.java
@@ -56,7 +56,7 @@
/**
* Used to indicate that the SyncAdapter experienced a hard error due to an error it
- * received from interacting with the storage later. The SyncManager will record that
+ * received from interacting with the storage layer. The SyncManager will record that
* the sync request failed and it will not reschedule the request.
*/
public boolean databaseError;
diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/hardware/CameraInfo.aidl
new file mode 100644
index 0000000..e21e694
--- /dev/null
+++ b/core/java/android/hardware/CameraInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+parcelable CameraInfo;
diff --git a/core/java/android/hardware/CameraInfo.java b/core/java/android/hardware/CameraInfo.java
new file mode 100644
index 0000000..53da0ce
--- /dev/null
+++ b/core/java/android/hardware/CameraInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information about a camera
+ *
+ * @hide
+ */
+public class CameraInfo implements Parcelable {
+ // Can't parcel nested classes, so make this a top level class that composes
+ // CameraInfo.
+ public Camera.CameraInfo info = new Camera.CameraInfo();
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(info.facing);
+ out.writeInt(info.orientation);
+ }
+
+ public void readFromParcel(Parcel in) {
+ info.facing = in.readInt();
+ info.orientation = in.readInt();
+ }
+
+ public static final Parcelable.Creator<CameraInfo> CREATOR =
+ new Parcelable.Creator<CameraInfo>() {
+ @Override
+ public CameraInfo createFromParcel(Parcel in) {
+ CameraInfo info = new CameraInfo();
+ info.readFromParcel(in);
+
+ return info;
+ }
+
+ @Override
+ public CameraInfo[] newArray(int size) {
+ return new CameraInfo[size];
+ }
+ };
+};
diff --git a/core/java/android/hardware/ICamera.aidl b/core/java/android/hardware/ICamera.aidl
new file mode 100644
index 0000000..d4f64f8
--- /dev/null
+++ b/core/java/android/hardware/ICamera.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface ICamera
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/ICamera.h
+ */
+ void disconnect();
+}
diff --git a/core/java/android/hardware/ICameraClient.aidl b/core/java/android/hardware/ICameraClient.aidl
new file mode 100644
index 0000000..d7877b4
--- /dev/null
+++ b/core/java/android/hardware/ICameraClient.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface ICameraClient
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/ICameraClient.h
+ */
+ // TODO: consider implementing this.
+}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
new file mode 100644
index 0000000..b8fbfdb
--- /dev/null
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.hardware.ICamera;
+import android.hardware.ICameraClient;
+import android.hardware.IProCameraUser;
+import android.hardware.IProCameraCallbacks;
+import android.hardware.ICameraServiceListener;
+import android.hardware.CameraInfo;
+
+/** @hide */
+interface ICameraService
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/ICameraService.h
+ */
+ int getNumberOfCameras();
+
+ // rest of 'int' return values in this file are actually status_t
+
+ int getCameraInfo(int cameraId, out CameraInfo info);
+
+ ICamera connect(ICameraClient client, int cameraId,
+ String clientPackageName,
+ int clientUid);
+
+ IProCameraUser connectPro(IProCameraCallbacks callbacks, int cameraId,
+ String clientPackageName,
+ int clientUid);
+
+ int addListener(ICameraServiceListener listener);
+ int removeListener(ICameraServiceListener listener);
+}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/android/hardware/ICameraServiceListener.aidl
new file mode 100644
index 0000000..c5484965
--- /dev/null
+++ b/core/java/android/hardware/ICameraServiceListener.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface ICameraServiceListener
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
+ */
+ void onStatusChanged(int status, int cameraId);
+}
diff --git a/core/java/android/hardware/IProCameraCallbacks.aidl b/core/java/android/hardware/IProCameraCallbacks.aidl
new file mode 100644
index 0000000..a09b452
--- /dev/null
+++ b/core/java/android/hardware/IProCameraCallbacks.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface IProCameraCallbacks
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/IProCameraCallbacks.h
+ */
+ // TODO: consider implementing this.
+}
diff --git a/core/java/android/hardware/IProCameraUser.aidl b/core/java/android/hardware/IProCameraUser.aidl
new file mode 100644
index 0000000..eacb0f4
--- /dev/null
+++ b/core/java/android/hardware/IProCameraUser.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/** @hide */
+interface IProCameraUser
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/IProCameraUser.h
+ */
+ void disconnect();
+}
diff --git a/core/java/android/hardware/TriggerEventListener.java b/core/java/android/hardware/TriggerEventListener.java
index 76b2796..8fa9702 100644
--- a/core/java/android/hardware/TriggerEventListener.java
+++ b/core/java/android/hardware/TriggerEventListener.java
@@ -21,15 +21,14 @@
* Trigger Sensors are sensors that trigger an event and are automatically
* disabled. {@link Sensor#TYPE_SIGNIFICANT_MOTION} is one such example.
* <p>
- * SensorManager lets you access the device's {@link android.hardware.Sensor
- * sensors}. Get an instance of this class by calling
+ * {@link SensorManager} lets you access the device's {@link android.hardware.Sensor
+ * sensors}. Get an instance of {@link SensorManager} by calling
* {@link android.content.Context#getSystemService(java.lang.String)
* Context.getSystemService()} with the argument
* {@link android.content.Context#SENSOR_SERVICE}.
- * Usage details are explained in the example below.
- * </p>
+ * <p>Here's an example setup for a TriggerEventListener:
*
- * <pre class="prettyprint">
+ * <pre>
* class TriggerListener extends TriggerEventListener {
* public void onTrigger(TriggerEvent event) {
* // Do Work.
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 2fd52b8..339fd6b 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -33,6 +33,7 @@
private final String mDeviceAddress;
private final String mDeviceName;
private final String mDeviceAlias;
+ private final boolean mCanConnect;
public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
@@ -41,7 +42,9 @@
String deviceAddress = in.readString();
String deviceName = in.readString();
String deviceAlias = in.readString();
- return new WifiDisplay(deviceAddress, deviceName, deviceAlias);
+ boolean canConnect = (in.readInt() != 0);
+ return new WifiDisplay(deviceAddress, deviceName,
+ deviceAlias, canConnect);
}
public WifiDisplay[] newArray(int size) {
@@ -50,6 +53,11 @@
};
public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) {
+ this(deviceAddress, deviceName, deviceAlias, false);
+ }
+
+ public WifiDisplay(String deviceAddress, String deviceName,
+ String deviceAlias, boolean canConnect) {
if (deviceAddress == null) {
throw new IllegalArgumentException("deviceAddress must not be null");
}
@@ -60,6 +68,7 @@
mDeviceAddress = deviceAddress;
mDeviceName = deviceName;
mDeviceAlias = deviceAlias;
+ mCanConnect = canConnect;
}
/**
@@ -88,6 +97,13 @@
}
/**
+ * Gets the availability of the Wifi display device.
+ */
+ public boolean canConnect() {
+ return mCanConnect;
+ }
+
+ /**
* Gets the name to show in the UI.
* Uses the device alias if available, otherwise uses the device name.
*/
@@ -104,7 +120,8 @@
return other != null
&& mDeviceAddress.equals(other.mDeviceAddress)
&& mDeviceName.equals(other.mDeviceName)
- && Objects.equal(mDeviceAlias, other.mDeviceAlias);
+ && Objects.equal(mDeviceAlias, other.mDeviceAlias)
+ && (mCanConnect == other.mCanConnect);
}
/**
@@ -127,6 +144,7 @@
dest.writeString(mDeviceAddress);
dest.writeString(mDeviceName);
dest.writeString(mDeviceAlias);
+ dest.writeInt(mCanConnect ? 1 : 0);
}
@Override
@@ -141,6 +159,7 @@
if (mDeviceAlias != null) {
result += ", alias " + mDeviceAlias;
}
+ result += ", canConnect " + mCanConnect;
return result;
}
}
diff --git a/core/java/android/hardware/photography/CameraAccessException.java b/core/java/android/hardware/photography/CameraAccessException.java
new file mode 100644
index 0000000..01114df
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraAccessException.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+/**
+ * <p><code>CameraAccessException</code> is thrown if a camera device could not
+ * be queried or opened by the {@link CameraManager}, or if the connection to an
+ * opened {@link CameraDevice} is no longer valid.</p>
+ *
+ * @see CameraManager
+ * @see CameraDevice
+ */
+public class CameraAccessException extends Exception {
+ /**
+ * The camera device is in use already
+ */
+ public static final int CAMERA_IN_USE = 1;
+
+ /**
+ * The system-wide limit for number of open cameras has been reached,
+ * and more camera devices cannot be opened until previous instances are
+ * closed.
+ */
+ public static final int MAX_CAMERAS_IN_USE = 2;
+
+ /**
+ * The camera is disabled due to a device policy, and cannot be opened.
+ *
+ * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
+ */
+ public static final int CAMERA_DISABLED = 3;
+
+ /**
+ * The camera device is removable and has been disconnected from the Android
+ * device, or the camera service has shut down the connection due to a
+ * higher-priority access request for the camera device.
+ */
+ public static final int CAMERA_DISCONNECTED = 4;
+
+ private int mReason;
+
+ /**
+ * The reason for the failure to access the camera.
+ *
+ * @see #CAMERA_IN_USE
+ * @see #MAX_CAMERAS_IN_USE
+ * @see #CAMERA_DISABLED
+ * @see #CAMERA_DISCONNECTED
+ */
+ public final int getReason() {
+ return mReason;
+ }
+
+ public CameraAccessException(int problem) {
+ mReason = problem;
+ }
+
+ public CameraAccessException(int problem, String message) {
+ super(message);
+ mReason = problem;
+ }
+
+ public CameraAccessException(int problem, String message, Throwable cause) {
+ super(message, cause);
+ mReason = problem;
+ }
+
+ public CameraAccessException(int problem, Throwable cause) {
+ super(cause);
+ mReason = problem;
+ }
+}
diff --git a/core/java/android/hardware/photography/CameraDevice.java b/core/java/android/hardware/photography/CameraDevice.java
new file mode 100644
index 0000000..2062db2
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraDevice.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.ImageFormat;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.view.Surface;
+
+import java.lang.AutoCloseable;
+import java.util.List;
+
+/**
+ * <p>The CameraDevice class is an interface to a single camera connected to an
+ * Android device, allowing for fine-grain control of image capture and
+ * post-processing at high frame rates.</p>
+ *
+ * <p>Your application must declare the
+ * {@link android.Manifest.permission#CAMERA Camera} permission in its manifest
+ * in order to access camera devices.</p>
+ *
+ * <p>A given camera device may provide support at one of two levels: limited or
+ * full. If a device only supports the limited level, then Camera2 exposes a
+ * feature set that is roughly equivalent to the older
+ * {@link android.hardware.Camera Camera} API, although with a cleaner and more
+ * efficient interface. Devices that implement the full level of support
+ * provide substantially improved capabilities over the older camera
+ * API. Applications that target the limited level devices will run unchanged on
+ * the full-level devices; if your application requires a full-level device for
+ * proper operation, declare the "android.hardware.camera2.full" feature in your
+ * manifest.</p>
+ *
+ * @see CameraManager#openCamera
+ * @see android.Manifest.permission#CAMERA
+ */
+public final class CameraDevice implements AutoCloseable {
+
+ /**
+ * Create a request suitable for a camera preview window. Specifically, this
+ * means that high frame rate is given priority over the highest-quality
+ * post-processing. These requests would normally be used with the
+ * {@link #setRepeatingRequest} method.
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_PREVIEW = 1;
+
+ /**
+ * Create a request suitable for video recording. Specifically, this means
+ * that a stable frame rate is used, and post-processing is set for
+ * recording quality. These requests would commonly be used with the
+ * {@link #setRepeatingRequest} method.
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_RECORD = 2;
+
+ /**
+ * Create a request suitable for still image capture. Specifically, this
+ * means prioritizing image quality over frame rate. These requests would
+ * commonly be used with the {@link #capture} method.
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_STILL_CAPTURE = 3;
+
+ /**
+ * Create a request suitable for still image capture while recording
+ * video. Specifically, this means maximizing image quality without
+ * disrupting the ongoing recording. These requests would commonly be used
+ * with the {@link #capture} method while a request based on
+ * {@link #TEMPLATE_RECORD} is is in use with {@link #setRepeatingRequest}.
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_VIDEO_SNAPSHOT = 4;
+
+ /**
+ * A basic template for direct application control of capture
+ * parameters. All automatic control is disabled (auto-exposure, auto-white
+ * balance, auto-focus), and post-processing parameters are set to preview
+ * quality. The manual capture parameters (exposure, sensitivity, and so on)
+ * are set to reasonable defaults, but should be overriden by the
+ * application depending on the intended use case.
+ *
+ * @see #createCaptureRequest
+ */
+ public static final int TEMPLATE_MANUAL = 5;
+
+ /**
+ * Get the static properties for this camera. These are identical to the
+ * properties returned by {@link CameraManager#getCameraProperties}.
+ *
+ * @return the static properties of the camera.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ *
+ * @see CameraManager#getCameraProperties
+ */
+ public CameraProperties getProperties() throws CameraAccessException {
+ return null;
+ }
+
+ /**
+ * <p>Set up a new output set of Surfaces for the camera device.</p>
+ *
+ * <p>The configuration determines the set of potential output Surfaces for
+ * the camera device for each capture request. A given request may use all
+ * or a only some of the outputs. This method must be called before requests
+ * can be submitted to the camera with {@link #capture capture},
+ * {@link #captureBurst captureBurst},
+ * {@link #setRepeatingRequest setRepeatingRequest}, or
+ * {@link #setRepeatingBurst setRepeatingBurst}.</p>
+ *
+ * <p>Surfaces suitable for inclusion as a camera output can be created for
+ * various use cases and targets:</p>
+ *
+ * <ul>
+ *
+ * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set
+ * the size of the Surface with
+ * {@link android.view.SurfaceHolder#setFixedSize} to be one of the
+ * supported
+ * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * before calling {@link android.view.SurfaceHolder#getSurface}.</li>
+ *
+ * <li>For accessing through an OpenGL texture via a
+ * {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
+ * the SurfaceTexture with
+ * {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
+ * of the supported
+ * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * before creating a Surface from the SurfaceTexture with
+ * {@link Surface#Surface}.</li>
+ *
+ * <li>For recording with {@link android.media.MediaCodec}: Call
+ * {@link android.media.MediaCodec#createInputSurface} after configuring
+ * the media codec to use one of the
+ * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * </li>
+ *
+ * <li>For recording with {@link android.media.MediaRecorder}: TODO</li>
+ *
+ * <li>For efficient YUV processing with {@link android.renderscript}:
+ * Create a RenderScript
+ * {@link android.renderscript.Allocation Allocation} with a supported YUV
+ * type, the IO_INPUT flag, and one of the supported
+ * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}. Then
+ * obtain the Surface with
+ * {@link android.renderscript.Allocation#getSurface}.</li>
+ *
+ * <li>For access to uncompressed, JPEG, or raw sensor data in the
+ * application: Create a {@link android.media.ImageReader} object with the
+ * desired {@link CameraProperties#SCALER_AVAILABLE_FORMATS image format},
+ * and a size from the matching
+ * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed},
+ * {@link CameraProperties#SCALER_AVAILABLE_JPEG_SIZES jpeg}, or
+ * {@link CameraProperties#SCALER_AVAILABLE_RAW_SIZES raw} sizes. Then
+ * obtain a Surface from it.</li>
+ *
+ * </ul>
+ *
+ * </p>
+ *
+ * <p>This function can take several hundred milliseconds to execute, since
+ * camera hardware may need to be powered on or reconfigured.</p>
+ *
+ * <p>To change the configuration after requests have been submitted to the
+ * device, the camera device must be idle. To idle the device, stop any
+ * repeating requests with {@link #stopRepeating stopRepeating}, and then
+ * call {@link #waitUntilIdle waitUntilIdle}.</p>
+ *
+ * <p>Using larger resolution outputs, or more outputs, can result in slower
+ * output rate from the device.</p>
+ *
+ * @param outputs the new set of Surfaces that should be made available as
+ * targets for captured image data.
+ *
+ * @throws IllegalArgumentException if the set of output Surfaces do not
+ * meet the requirements
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device is not idle, or has
+ * encountered a fatal error
+ */
+ public void configureOutputs(List<Surface> outputs) {
+ }
+
+ /**
+ * <p>Create a {@link CaptureRequest} initialized with template for a target
+ * use case. The settings are chosen to be the best options for the specific
+ * camera device, so it is not recommended to reuse the same request for a
+ * different camera device; create a request for that device and override
+ * the settings as desired, instead.</p>
+ *
+ * @param templateType An enumeration selecting the use case for this
+ * request; one of the CameraDevice.TEMPLATE_ values.
+ * @return a filled-in CaptureRequest, except for output streams.
+ *
+ * @throws IllegalArgumentException if the templateType is not in the list
+ * of supported templates.
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #TEMPLATE_PREVIEW
+ * @see #TEMPLATE_RECORD
+ * @see #TEMPLATE_STILL_CAPTURE
+ * @see #TEMPLATE_VIDEO_SNAPSHOT
+ * @see #TEMPLATE_MANUAL
+ */
+ public CaptureRequest createCaptureRequest(int templateType)
+ throws CameraAccessException {
+ return null;
+ }
+
+ /**
+ * <p>Submit a request for an image to be captured by this CameraDevice.</p>
+ *
+ * <p>The request defines all the parameters for capturing the single image,
+ * including sensor, lens, flash, and post-processing settings.</p>
+ *
+ * <p>Each request will produce one {@link CaptureResult} and produce new
+ * frames for one or more target Surfaces, as defined by the request's .</p>
+ *
+ * <p>Multiple requests can be in progress at once. They are processed in
+ * first-in, first-out order, with minimal delays between each
+ * capture. Requests submitted through this method have higher priority than
+ * those submitted through {@link #setRepeatingRequest} or
+ * {@link #setRepeatingBurst}, and will be processed as soon as the current
+ * repeat/repeatBurst processing completes.</p>
+ *
+ * @param request the settings for this capture.
+ * @param listener the callback object to notify once this request has been
+ * processed. If null, no metadata will be produced for this capture,
+ * although image data will still be produced.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #captureBurst
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ */
+ public void capture(CaptureRequest request, CaptureListener listener)
+ throws CameraAccessException {
+ }
+
+ /**
+ * <p>Submit a list of requests to be captured in sequence as a burst. The
+ * burst will be captured in the minimum amount of time possible, and will
+ * not be interleaved with requests submitted by other capture or repeat
+ * calls.</p>
+ *
+ * <p>The requests will be captured in order, each capture producing one
+ * {@link CaptureResult} and frames for one or more
+ * target {@link android.view.Surface surfaces}.</p>
+ *
+ * <p>The main difference between this method and simply calling
+ * {@link #capture} repeatedly is that this method guarantees that no
+ * other requests will be interspersed with the burst.</p>
+ *
+ * @param requests the list of settings for this burst capture.
+ * @param listener the callback object to notify each time one of the
+ * requests in the burst has been processed. If null, no metadata will be
+ * produced for any requests in this burst, although image data will still
+ * be produced.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #capture
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ */
+ public void captureBurst(List<CaptureRequest> requests,
+ CaptureListener listener) throws CameraAccessException {
+ }
+
+ /**
+ * <p>Request endlessly repeating capture of images by this
+ * CameraDevice.</p>
+ *
+ * <p>With this method, the CameraDevice will continually capture
+ * images using the settings in the provided {@link
+ * CaptureRequest}, at the maximum rate possible.</p>
+ *
+ * <p>Repeat requests have lower priority than those submitted
+ * through {@link #capture} or {@link #captureBurst}, so if
+ * capture() is called when a repeating request is active, the
+ * capture request will be processed before any further repeating
+ * requests are processed.<p>
+ *
+ * <p>Repeating requests are a simple way for an application to maintain a
+ * preview or other continuous stream of frames, without having to submit
+ * requests through {@link #capture} at video rates.</p>
+ *
+ * <p>To stop the repeating capture, call {@link #stopRepeating}</p>
+ *
+ * <p>Calling repeat will replace a burst set up by {@link
+ * #setRepeatingBurst}, although any in-progress burst will be
+ * completed before the new repeat request will be used.</p>
+ *
+ * @param request the request to repeat indefinitely
+ * @param listener the callback object to notify every time the
+ * request finishes processing. If null, no metadata will be
+ * produced for this stream of requests, although image data will
+ * still be produced.
+ *
+ * @throws CameraAccessException if the camera device is no longer
+ * connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #capture
+ * @see #captureBurst
+ * @see #setRepeatingBurst
+ */
+ public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
+ throws CameraAccessException {
+ }
+
+ /**
+ * <p>Request endlessly repeating capture of a sequence of images by this
+ * CameraDevice.</p>
+ *
+ * <p>With this method, the CameraDevice will continually capture images,
+ * cycling through the settings in the provided list of
+ * {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p>
+ *
+ * <p>If a request is submitted through {@link #capture} or
+ * {@link #captureBurst}, the current repetition of the request list will be
+ * completed before the higher-priority request is handled. This guarantees
+ * that the application always receives a complete repeat burst captured in
+ * minimal time, instead of bursts interleaved with higher-priority
+ * captures, or incomplete captures.</p>
+ *
+ * <p>Repeating burst requests are a simple way for an application to
+ * maintain a preview or other continuous stream of frames where each
+ * request is different in a predicatable way, without having to submit
+ * requests through {@link #capture} at video rates.</p>
+ *
+ * <p>To stop the repeating capture, call {@link #stopRepeating}. Any
+ * ongoing burst will still be completed, however.</p>
+ *
+ * <p>Calling repeatBurst will replace a repeating request set up by
+ * {@link #setRepeatingRequest}, although any in-progress capture will be completed
+ * before the new repeat burst will be used.</p>
+ *
+ * @param requests the list of requests to cycle through indefinitely.
+ * @param listener the callback object to notify each time one of the
+ * requests in the repeating bursts has finished processing. If null, no
+ * metadata will be produced for this stream of requests, although image
+ * data will still be produced.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #capture
+ * @see #captureBurst
+ * @see #setRepeatingRequest
+ */
+ public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
+ throws CameraAccessException {
+ }
+
+ /**
+ * <p>Cancel any ongoing repeating capture set by either
+ * {@link #setRepeatingRequest setRepeatingRequest} or
+ * {@link #setRepeatingBurst}. Has no effect on requests submitted through
+ * {@link #capture capture} or {@link #captureBurst captureBurst}.</p>
+ *
+ * <p>Any currently in-flight captures will still complete, as will any
+ * burst that is mid-capture. To ensure that the device has finished
+ * processing all of its capture requests and is in idle state, use the
+ * {@link #waitUntilIdle waitUntilIdle} method.</p>
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed or the
+ * device has encountered a fatal error.
+ *
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ * @see #waitUntilIdle
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed, the
+ * device has encountered a fatal error, or if there is an active repeating
+ * request or burst.
+ */
+ public void stopRepeating() throws CameraAccessException {
+ }
+
+ /**
+ * <p>Wait until all the submitted requests have finished processing</p>
+ *
+ * <p>This method blocks until all the requests that have been submitted to
+ * the camera device, either through {@link #capture capture},
+ * {@link #captureBurst captureBurst},
+ * {@link #setRepeatingRequest setRepeatingRequest}, or
+ * {@link #setRepeatingBurst setRepeatingBurst}, have completed their
+ * processing.</p>
+ *
+ * <p>Once this call returns successfully, the device is in an idle state,
+ * and can be reconfigured with {@link #configureOutputs configureOutputs}.</p>
+ *
+ * <p>This method cannot be used if there is an active repeating request or
+ * burst, set with {@link #setRepeatingRequest setRepeatingRequest} or
+ * {@link #setRepeatingBurst setRepeatingBurst}. Call
+ * {@link #stopRepeating stopRepeating} before calling this method.</p>
+ *
+ * @throws CameraAccessException if the camera device is no longer connected
+ * @throws IllegalStateException if the camera device has been closed, the
+ * device has encountered a fatal error, or if there is an active repeating
+ * request or burst.
+ */
+ public void waitUntilIdle() throws CameraAccessException {
+ }
+
+ /**
+ * Set the error listener object to call when an asynchronous error
+ * occurs. The errors reported here are only device-wide errors; errors
+ * about individual requests or frames are reported through
+ * {@link CaptureListener#onCaptureFailed}.
+ *
+ * @param listener the ErrorListener to send asynchronous error
+ * notifications to. Setting this to null will stop notifications about
+ * asynchronous errors.
+ */
+ public void setErrorListener(ErrorListener listener) {
+ }
+
+ /**
+ * Close the connection to this camera device. After this call, all calls to
+ * the camera device interface will throw a {@link IllegalStateException},
+ * except for calls to close().
+ */
+ public void close() {
+ }
+
+ /**
+ * A listener for receiving metadata about completed image captures. The
+ * metadata includes, among other things, the final capture settings and the
+ * state of the control algorithms.
+ */
+ public interface CaptureListener {
+ /**
+ * <p>Called when a capture request has been processed by a
+ * {@link CameraDevice}.</p>
+ *
+ * @param camera The CameraDevice sending the callback.
+ * @param request The request that was given to the CameraDevice
+ * @param result The output metadata from the capture, including the
+ * final capture parameters and the state of the camera system during
+ * capture.
+ *
+ * @see #capture
+ * @see #captureBurst
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ */
+ public void onCaptureComplete(CameraDevice camera,
+ CaptureRequest request, CaptureResult result);
+
+ /**
+ * <p>Called instead of onCaptureComplete when the camera device failed
+ * to produce a CaptureResult for the request. Other requests are
+ * unaffected, and some or all image buffers from the capture may have
+ * been pushed to their respective output streams.</p>
+ *
+ * @param camera The CameraDevice sending the callback.
+ * @param request The request that was given to the CameraDevice
+ *
+ * @see #capture
+ * @see #captureBurst
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ */
+ public void onCaptureFailed(CameraDevice camera,
+ CaptureRequest request);
+ }
+
+ /**
+ * <p>A listener for asynchronous errors from the camera device. Errors
+ * about specific {@link CaptureRequest CaptureRequests} are sent through
+ * the capture {@link CaptureListener#onCaptureFailed listener}
+ * interface. Errors reported through this listener affect the device as a
+ * whole.</p>
+ */
+ public interface ErrorListener {
+ /**
+ * <p>This camera device has been disconnected by the camera
+ * service. Any attempt to call methods on this CameraDevice will throw
+ * a {@link CameraAccessException}. The disconnection could be due to a
+ * change in security policy or permissions; the physical disconnection
+ * of a removable camera device; or the camera being needed for a
+ * higher-priority use case.</p>
+ *
+ * <p>There may still be capture completion or camera stream listeners
+ * that will be called after this error is received.</p>
+ */
+ public static final int DEVICE_DISCONNECTED = 1;
+
+ /**
+ * <p>The camera device has encountered a fatal error. Any attempt to
+ * call methods on this CameraDevice will throw a
+ * {@link java.lang.IllegalStateException}.</p>
+ *
+ * <p>There may still be capture completion or camera stream listeners
+ * that will be called after this error is received.</p>
+ *
+ * <p>The application needs to re-open the camera device to use it
+ * again.</p>
+ */
+ public static final int DEVICE_ERROR = 2;
+
+ /**
+ * <p>The camera service has encountered a fatal error. Any attempt to
+ * call methods on this CameraDevice in the future will throw a
+ * {@link java.lang.IllegalStateException}.</p>
+ *
+ * <p>There may still be capture completion or camera stream listeners
+ * that will be called after this error is received.</p>
+ *
+ * <p>The device may need to be shut down and restarted to restore
+ * camera function, or there may be a persistent hardware problem.</p>
+ */
+ public static final int SERVICE_ERROR = 3;
+
+ /**
+ * The method to call when a camera device has encountered an error.
+ *
+ * @param camera The device reporting the error
+ * @param error The error code, one of the ErrorListener.ERROR_ values.
+ */
+ public void onCameraDeviceError(CameraDevice camera, int error);
+ }
+
+}
diff --git a/core/java/android/hardware/photography/CameraManager.java b/core/java/android/hardware/photography/CameraManager.java
new file mode 100644
index 0000000..328ba4b
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraManager.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+/**
+ * <p>An interface for iterating, listing, and connecting to
+ * {@link CameraDevice CameraDevices}.</p>
+ *
+ * <p>You can get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p>
+ *
+ * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre>
+ *
+ * <p>For more details about communicating with camera devices, read the Camera
+ * developer guide or the {@link android.hardware.photography photography}
+ * package documentation.</p>
+ */
+public final class CameraManager {
+
+ /**
+ * @hide
+ */
+ public CameraManager() {
+ }
+
+ /**
+ * <p>Return the list of currently connected camera devices by
+ * identifier. Non-removable cameras use integers starting at 0 for their
+ * identifiers, while removable cameras have a unique identifier for each
+ * individual device, even if they are the same model.</p>
+ *
+ * @return The list of currently connected camera devices.
+ */
+ public String[] getDeviceIdList() {
+ return null;
+ }
+
+ /**
+ * Register a listener to be notified about camera device availability.
+ *
+ * @param listener the new listener to send camera availablity notices to.
+ */
+ public void registerCameraListener(CameraListener listener) {
+ }
+
+ /**
+ * Remove a previously-added listener; the listener will no longer receive
+ * connection and disconnection callbacks.
+ *
+ * @param listener the listener to remove from the notification list
+ */
+ public void unregisterCameraListener(CameraListener listener) {
+ }
+
+ /**
+ * <p>Query the capabilities of a camera device. These capabilities are
+ * immutable for a given camera.</p>
+ *
+ * @param cameraId The id of the camera device to query
+ * @return The properties of the given camera
+ *
+ * @throws IllegalArgumentException if the cameraId does not match any
+ * currently connected camera device.
+ * @throws CameraAccessException if the camera is disabled by device policy.
+ * @throws SecurityException if the application does not have permission to
+ * access the camera
+ *
+ * @see #getDeviceIdList
+ * @see android.app.admin.DevicePolicyManager#setCameraDisabled
+ */
+ public CameraProperties getCameraProperties(String cameraId)
+ throws CameraAccessException {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Open a connection to a camera with the given ID. Use
+ * {@link #getDeviceIdList} to get the list of available camera
+ * devices. Note that even if an id is listed, open may fail if the device
+ * is disconnected between the calls to {@link #getDeviceIdList} and
+ * {@link #openCamera}.
+ *
+ * @param cameraId The unique identifier of the camera device to open
+ *
+ * @throws IllegalArgumentException if the cameraId does not match any
+ * currently connected camera device.
+ * @throws CameraAccessException if the camera is disabled by device policy,
+ * or too many camera devices are already open.
+ * @throws SecurityException if the application does not have permission to
+ * access the camera
+ *
+ * @see #getDeviceIdList
+ * @see android.app.admin.DevicePolicyManager#setCameraDisabled
+ */
+ public CameraDevice openCamera(String cameraId) throws CameraAccessException {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Interface for listening to cameras becoming available or unavailable.
+ * Cameras become available when they are no longer in use, or when a new
+ * removable camera is connected. They become unavailable when some
+ * application or service starts using a camera, or when a removable camera
+ * is disconnected.
+ */
+ public interface CameraListener {
+ /**
+ * A new camera has become available to use.
+ *
+ * @param cameraId The unique identifier of the new camera.
+ */
+ public void onCameraAvailable(String cameraId);
+
+ /**
+ * A previously-available camera has become unavailable for use. If an
+ * application had an active CameraDevice instance for the
+ * now-disconnected camera, that application will receive a {@link
+ * CameraDevice.ErrorListener#DEVICE_DISCONNECTED disconnection error}.
+ *
+ * @param cameraId The unique identifier of the disconnected camera.
+ */
+ public void onCameraUnavailable(String cameraId);
+ }
+}
diff --git a/core/java/android/hardware/photography/CameraMetadata.java b/core/java/android/hardware/photography/CameraMetadata.java
new file mode 100644
index 0000000..385a1b9
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraMetadata.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The base class for camera controls and information.
+ *
+ * This class defines the basic key/value map used for querying for camera
+ * characteristics or capture results, and for setting camera request
+ * parameters.
+ *
+ * @see CameraDevice
+ * @see CameraManager
+ * @see CameraProperties
+ **/
+public class CameraMetadata implements Parcelable {
+
+ public CameraMetadata() {
+ mMetadataMap = new HashMap<Key<?>, Object>();
+ }
+
+ private CameraMetadata(Parcel in) {
+
+ }
+
+ public static final Parcelable.Creator<CameraMetadata> CREATOR =
+ new Parcelable.Creator<CameraMetadata>() {
+ public CameraMetadata createFromParcel(Parcel in) {
+ return new CameraMetadata(in);
+ }
+
+ public CameraMetadata[] newArray(int size) {
+ return new CameraMetadata[size];
+ }
+ };
+
+ /**
+ * Set a camera metadata field to a value. The field definitions can be
+ * found in {@link CameraProperties}, {@link CaptureResult}, and
+ * {@link CaptureRequest}.
+ *
+ * @param key the metadata field to write.
+ * @param value the value to set the field to, which must be of a matching
+ * type to the key.
+ */
+ public <T> void set(Key<T> key, T value) {
+ mMetadataMap.put(key, value);
+ }
+
+ /**
+ * Get a camera metadata field value. The field definitions can be
+ * found in {@link CameraProperties}, {@link CaptureResult}, and
+ * {@link CaptureRequest}.
+ *
+ * @param key the metadata field to read.
+ * @return the value of that key, or {@code null} if the field is not set.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T get(Key<T> key) {
+ return (T) mMetadataMap.get(key);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+
+ }
+
+ public static class Key<T> {
+ public Key(String name) {
+ if (name == null) {
+ throw new NullPointerException("Key needs a valid name");
+ }
+ mName = name;
+ }
+
+ public final String getName() {
+ return mName;
+ }
+
+ @Override
+ public final int hashCode() {
+ return mName.hashCode();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof Key)) {
+ return false;
+ }
+
+ Key lhs = (Key) o;
+
+ return mName.equals(lhs.mName);
+ }
+
+ private final String mName;
+ }
+
+ private Map<Key<?>, Object> mMetadataMap;
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CameraProperties.java b/core/java/android/hardware/photography/CameraProperties.java
new file mode 100644
index 0000000..1bfd712
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraProperties.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.Rect;
+
+import java.util.List;
+
+/**
+ * <p>The properties describing a
+ * {@link CameraDevice CameraDevice}.</p>
+ *
+ * <p>These properties are fixed for a given CameraDevice, and can be queried
+ * through the {@link CameraManager CameraManager}
+ * interface in addition to through the CameraDevice interface.</p>
+ *
+ * @see CameraDevice
+ * @see CameraManager
+ */
+public final class CameraProperties extends CameraMetadata {
+ /**
+ * The model name of the camera. For fixed (non-removable) cameras, this is
+ * the manufacturer's name. For removable cameras, this is a string that
+ * uniquely identifies the camera model and manufacturer. The
+ * {@link #INFO_IDENTIFIER} can be used to distinguish between multiple
+ * removable cameras of the same model.
+ */
+ public static final Key INFO_MODEL =
+ new Key<String>("android.info.model");
+
+ /**
+ * A unique identifier for this camera. For removable cameras, every
+ * camera will have a unique identifier, including two cameras of the
+ * same model and manufacturer. For non-removable cameras, the
+ * identifier is equal to the the device's id.
+ */
+ public static final Key INFO_IDENTIFIER =
+ new Key<String>("android.info.identifier");
+
+ /**
+ * <p>Whether this camera is removable or not.</p>
+ *
+ * <p>Applications using a removable camera must be prepared for the camera
+ * to be disconnected during use. Use the {@link #INFO_IDENTIFIER} field to
+ * determine if this camera is a match for a camera device seen earlier.</p>
+ */
+ public static final Key INFO_REMOVABLE =
+ new Key<Boolean>("android.info.isRemovable");
+
+ /**
+ * <p>The hardware operational model of this device. One of the
+ * INFO_SUPPORTED_HARDWARE_LEVEL_* constants.</p>
+ *
+ * <p>Limited-capability devices have a number of limitations relative to
+ * full-capability cameras. Roughly, they have capabilities comparable to
+ * those provided by the deprecated {@link android.hardware.Camera}
+ * class.</p>
+ *
+ * <p>Specifically, limited-mode devices:</p>
+ *
+ * <ol>
+ *
+ * <li>Do not provide per-frame result metadata for repeating
+ * captures. This means that a CaptureListener will not be called for
+ * captures done through {@link CameraDevice#setRepeatingRequest
+ * setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst
+ * setRepeatingBurst}.</li>
+ *
+ * <li>Do not support complete result metadata. Only a few fields are
+ * provided, such as the timestamp (TODO).</li>
+ *
+ * <li>Do not support manual capture controls. Only the (TODO)
+ * ANDROID_CONTROL_* fields and TODO controls are used, and the various
+ * AE/AF/AWB_OFF control values cannot be used.</li>
+ *
+ * <li>Do not support high frame rate captures. To obtain high frame rate,
+ * the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method
+ * must be used. The {@link CameraDevice#capture capture},
+ * {@link CameraDevice#captureBurst captureBurst}, and
+ * {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will
+ * result in slow frame captures.</li>
+ *
+ * </ol>
+ *
+ * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
+ * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
+ */
+ public static final Key INFO_SUPPORTED_HARDWARE_LEVEL =
+ new Key<Integer>("android.info.supportedHardwareLevel");
+
+ /**
+ * <p>The type reported by limited-capability camera devices.</p>
+ *
+ * <p>Limited-capability devices have a number of limitations relative to
+ * full-capability cameras. Roughly, they have capabilities comparable to
+ * those provided by the deprecated {@link android.hardware.Camera}
+ * class.</p>
+ *
+ * <p>Specifically, limited-mode devices:</p>
+ *
+ * <ol>
+ *
+ * <li>Do not provide per-frame result metadata for repeating
+ * captures. This means that a CaptureListener will not be called for
+ * captures done through {@link CameraDevice#setRepeatingRequest
+ * setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst
+ * setRepeatingBurst}.</li>
+ *
+ * <li>Do not support complete result metadata. Only a few fields are
+ * provided, such as the timestamp (TODO).</li>
+ *
+ * <li>Do not support manual capture controls. Only the (TODO)
+ * ANDROID_CONTROL_* fields and TODO controls are used, and the various
+ * AE/AF/AWB_OFF control values cannot be used.</li>
+ *
+ * <li>Do not support high frame rate captures. To obtain high frame rate,
+ * the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method
+ * must be used. The {@link CameraDevice#capture capture},
+ * {@link CameraDevice#captureBurst captureBurst}, and
+ * {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will
+ * result in slow frame captures.</li>
+ *
+ * </ol>
+ *
+ * @see #INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0;
+
+ /**
+ * <p>The type reported by full-capability camera devices</p>
+ *
+ * <p>Full-capability devices allow for per-frame control of capture
+ * hardware and post-processing parameters at high frame rates. They also
+ * provide output data at high resolution in uncompressed formats, in
+ * addition to compressed JPEG output.</p>
+ *
+ * @see #INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1;
+
+ /**
+ * <p>The available output formats from this camera device. When using a
+ * {@link android.media.ImageReader} as an output target, the
+ * ImageReader must be configured to use one of these formats.</p>
+ *
+ * <p>The list is a subset of the formats defined in
+ * {@link android.graphics.ImageFormat}.</p>
+ *
+ * <p>The image formats {@link android.graphics.ImageFormat#JPEG},
+ * {@link android.graphics.ImageFormat#YUV_420_888} are guaranteed to be
+ * supported.</p>
+ */
+ public static final Key SCALER_AVAILABLE_FORMATS =
+ new Key<Integer[]>("android.scaler.availableFormats");
+
+ /**
+ * <p>The available output sizes for JPEG buffers from this camera
+ * device. When using a {@link android.media.ImageReader} as an output
+ * target, the ImageReader must be configured to use one of these sizes
+ * when using format {@link android.graphics.ImageFormat#JPEG}.</p>
+ */
+ public static final Key SCALER_AVAILABLE_JPEG_SIZES =
+ new Key<Size[]>("android.scaler.availableJpegSizes");
+
+ /**
+ * <p>The available sizes for output buffers from this camera device, when
+ * the buffers are neither of the {@link android.graphics.ImageFormat#JPEG}
+ * or of the {@link android.graphics.ImageFormat#RAW_SENSOR} type.</p>
+ *
+ * <p>When using a {@link android.view.SurfaceView},
+ * {@link android.graphics.SurfaceTexture},
+ * {@link android.media.MediaRecorder}, {@link android.media.MediaCodec}, or
+ * {@link android.renderscript.Allocation} as an output target, that target
+ * must be configured to one of these sizes. See
+ * {@link CameraDevice#configureOutputs} for details.
+ *
+ * <p>When using a {@link android.media.ImageReader} as an output
+ * target, the ImageReader must be configured to use one of these sizes
+ * when using format {@link android.graphics.ImageFormat#YUV_420_888}.</p>
+ *
+ */
+ public static final Key SCALER_AVAILABLE_PROCESSED_SIZES =
+ new Key<Size[]>("android.scaler.availableProcessedSizes");
+
+ /**
+ * <p>The available sizes for output buffers from this camera device, when
+ * the buffers are of the {@link android.graphics.ImageFormat#RAW_SENSOR} type. This type of output may not be
+ * supported by the device; check {@link #SCALER_AVAILABLE_FORMATS} to
+ * check. In that case, this list will not exist.</p>
+ *
+ * <p>When using a {@link android.media.ImageReader} as an output
+ * target, the ImageReader must be configured to use one of these sizes
+ * when using image format {@link android.graphics.ImageFormat#RAW_SENSOR}.</p>
+ */
+ public static final Key SCALER_AVAILABLE_RAW_SIZES =
+ new Key<Size[]>("android.scaler.availableRawSizes");
+
+ /**
+ * <p>The coordinates of the sensor's active pixel array, relative to its
+ * total pixel array. These are the pixels that are actually used for image
+ * capture. The active pixel region may be smaller than the total number of
+ * pixels, if some pixels are used for other tasks such as calibrating the
+ * sensor's black level. If all pixels available for readout are used for
+ * imaging, then this rectangle will be
+ * {@code (0,0) - (SENSOR_PIXEL_ARRAY_SIZE.width,
+ * SENSOR_PIXEL_ARRAY_SIZE.height)}.</p>
+ *
+ * <p>If raw sensor capture is supported by this device, the width and
+ * height of the active pixel array match up to one of the supported raw
+ * capture sizes, and using that size will capture just the active pixel
+ * array region.</p>
+ *
+ * <p>Most other coordinates used by the camera device (for example, for
+ * metering and crop region selection, or for reporting detected faces) use
+ * a coordinate system based on the active array dimensions, with (0,0)
+ * being the top-left corner of the active array.</p>
+ */
+ public static final Key SENSOR_ACTIVE_ARRAY_SIZE =
+ new Key<Rect>("android.sensor.activeArraySize");
+
+ /**
+ * <p>The size of the sensor's total pixel array available for readout. Some
+ * of these pixels may not be used for image capture, in which case
+ * {@link #SENSOR_ACTIVE_ARRAY_SIZE} will describe a rectangle smaller than
+ * this. If raw sensor capture is supported by this device, this is one of
+ * the supported capture sizes.</p>
+ */
+ public static final Key SENSOR_PIXEL_ARRAY_SIZE =
+ new Key<Size>("android.sensor.activeArraySize");
+
+ // TODO: Many more of these.
+
+}
diff --git a/core/java/android/hardware/photography/CaptureRequest.java b/core/java/android/hardware/photography/CaptureRequest.java
new file mode 100644
index 0000000..a54c743
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureRequest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+import android.view.Surface;
+
+import java.util.List;
+
+
+/**
+ * <p>All the settings required to capture a single image from the image sensor.</p>
+ *
+ * <p>Contains the configuration for the capture hardware (sensor, lens, flash),
+ * the processing pipeline, the control algorithms, and the output buffers.</p>
+ *
+ * <p>CaptureRequests can be created by calling
+ * {@link CameraDevice#createCaptureRequest}</p>
+ *
+ * <p>CaptureRequests are given to {@link CameraDevice#capture} or
+ * {@link CameraDevice#setRepeatingRequest} to capture images from a camera.</p>
+ *
+ * <p>Each request can specify a different subset of target Surfaces for the
+ * camera to send the captured data to. All the surfaces used in a request must
+ * be part of the surface list given to the last call to
+ * {@link CameraDevice#configureOutputs}.</p>
+ *
+ * <p>For example, a request meant for repeating preview might only include the
+ * Surface for the preview SurfaceView or SurfaceTexture, while a
+ * high-resolution still capture would also include a Surface from a ImageReader
+ * configured for high-resolution JPEG images.</p>
+ *
+ * @see CameraDevice#capture
+ * @see CameraDevice#setRepeatingRequest
+ * @see CameraDevice#createRequest
+ */
+public final class CaptureRequest extends CameraMetadata {
+
+ /**
+ * The exposure time for this capture, in nanoseconds.
+ */
+ public static final Key SENSOR_EXPOSURE_TIME =
+ new Key<Long>("android.sensor.exposureTime");
+
+ /**
+ * The sensor sensitivity (gain) setting for this camera.
+ * This is represented as an ISO sensitivity value
+ */
+ public static final Key SENSOR_SENSITIVITY =
+ new Key<Integer>("android.sensor.sensitivity");
+
+ // Many more settings
+
+ CaptureRequest() {
+ }
+
+ /**
+ * <p>Add a surface to the list of targets for this request</p>
+ *
+ * <p>The Surface added must be one of the surfaces included in the last
+ * call to {@link CameraDevice#configureOutputs}.</p>
+ */
+ public void addTarget(Surface outputTarget) {
+ }
+
+ /**
+ * <p>Remove a surface from the list of targets for this request.</p>
+ */
+ public void removeTarget(Surface outputTarget) {
+ }
+
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CaptureResult.java b/core/java/android/hardware/photography/CaptureResult.java
new file mode 100644
index 0000000..dd36f1d
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureResult.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+/**
+ * <p>The results of a single image capture from the image sensor.</p>
+ *
+ * <p>Contains the final configuration for the capture hardware (sensor, lens,
+ * flash), the processing pipeline, the control algorithms, and the output
+ * buffers.</p>
+ *
+ * <p>CaptureResults are produced by a {@link CameraDevice} after processing a
+ * {@link CaptureRequest}. All properties listed for capture requests can also
+ * be queried on the capture result, to determine the final values used for
+ * capture. The result also includes additional metadata about the state of the
+ * camera device during the capture.</p>
+ *
+ */
+public final class CaptureResult extends CameraMetadata {
+
+ /**
+ * The timestamp representing the start of image capture, in nanoseconds.
+ * This corresponds to the timestamp available through
+ * {@link android.graphics.SurfaceTexture#getTimestamp SurfaceTexture.getTimestamp()}
+ * or {@link android.media.Image#getTimestamp Image.getTimestamp()} for this
+ * capture's image data.
+ */
+ public static final Key SENSOR_TIMESTAMP =
+ new Key<Long>("android.sensor.timestamp");
+
+ /**
+ * The state of the camera device's auto-exposure algorithm. One of the
+ * CONTROL_AE_STATE_* enumerations.
+ */
+ public static final Key CONTROL_AE_STATE =
+ new Key<Integer>("android.control.aeState");
+
+ /**
+ * The auto-exposure algorithm is inactive.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_INACTIVE = 0;
+
+ /**
+ * The auto-exposure algorithm is currently searching for proper exposure.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_SEARCHING = 1;
+
+ /**
+ * The auto-exposure algorithm has reached proper exposure values for the
+ * current scene.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_CONVERGED = 2;
+
+ /**
+ * The auto-exposure algorithm has been locked to its current values.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_LOCKED = 3;
+
+ /**
+ * The auto-exposure algorithm has reached proper exposure values as with
+ * CONTROL_AE_STATE_CONVERGED, but the scene is too dark to take a good
+ * quality image without firing the camera flash.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4;
+
+ /**
+ * The precapture sequence of the auto-exposure algorithm has been triggered,
+ * and is underway.
+ * @see CONTROL_AE_STATE
+ */
+ public static final int CONTROL_AE_STATE_PRECAPTURE =5;
+
+ /**
+ * The list of faces detected in this capture. Available if face detection
+ * was enabled for this capture
+ */
+ public static final Key STATISTICS_DETECTED_FACES =
+ new Key<Face[]>("android.statistics.faces");
+
+ // TODO: Many many more
+
+ CaptureResult() {
+ }
+
+ /**
+ * Describes a face detected in an image.
+ */
+ public static class Face {
+
+ /**
+ * <p>Bounds of the face. A rectangle relative to the sensor's
+ * {@link CameraProperties#SENSOR_ACTIVE_ARRAY_SIZE}, with (0,0)
+ * representing the top-left corner of the active array rectangle.</p>
+ */
+ public Rect getBounds() {
+ return mBounds;
+ }
+
+ /* <p>The confidence level for the detection of the face. The range is 1 to
+ * 100. 100 is the highest confidence.</p>
+ *
+ * <p>Depending on the device, even very low-confidence faces may be
+ * listed, so applications should filter out faces with low confidence,
+ * depending on the use case. For a typical point-and-shoot camera
+ * application that wishes to display rectangles around detected faces,
+ * filtering out faces with confidence less than 50 is recommended.</p>
+ *
+ */
+ public int getScore() {
+ return mScore;
+ }
+
+ /**
+ * An unique id per face while the face is visible to the tracker. If
+ * the face leaves the field-of-view and comes back, it will get a new
+ * id. This is an optional field, may not be supported on all devices.
+ * If not supported, id will always be set to -1. The optional fields
+ * are supported as a set. Either they are all valid, or none of them
+ * are.
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * The coordinates of the center of the left eye. The coordinates are in
+ * the same space as the ones for {@link #getBounds}. This is an
+ * optional field, may not be supported on all devices. If not
+ * supported, the value will always be set to null. The optional fields
+ * are supported as a set. Either they are all valid, or none of them
+ * are.
+ */
+ public Point getLeftEye() {
+ return mLeftEye;
+ }
+
+ /**
+ * The coordinates of the center of the right eye. The coordinates are
+ * in the same space as the ones for {@link #getBounds}.This is an
+ * optional field, may not be supported on all devices. If not
+ * supported, the value will always be set to null. The optional fields
+ * are supported as a set. Either they are all valid, or none of them
+ * are.
+ */
+ public Point getRightEye() {
+ return mRightEye;
+ }
+
+ /**
+ * The coordinates of the center of the mouth. The coordinates are in
+ * the same space as the ones for {@link #getBounds}. This is an optional
+ * field, may not be supported on all devices. If not supported, the
+ * value will always be set to null. The optional fields are supported
+ * as a set. Either they are all valid, or none of them are.
+ */
+ public Point getMouth() {
+ return mMouth;
+ }
+
+ private Rect mBounds;
+ private int mScore;
+ private int mId;
+ private Point mLeftEye;
+ private Point mRightEye;
+ private Point mMouth;
+ }
+}
diff --git a/core/java/android/hardware/photography/Size.java b/core/java/android/hardware/photography/Size.java
new file mode 100644
index 0000000..e1115d3
--- /dev/null
+++ b/core/java/android/hardware/photography/Size.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography;
+
+/**
+ * A simple immutable class for describing the dimensions of camera image
+ * buffers.
+ */
+public final class Size {
+ /**
+ * Create a new immutable Size instance
+ *
+ * @param w The width to store in the Size instance
+ * @param h The height to store in the Size instance
+ */
+ Size(int w, int h) {
+ mWidth = w;
+ mHeight = h;
+ }
+
+ public final int getWidth() {
+ return mWidth;
+ }
+
+ public final int getHeight() {
+ return mHeight;
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+};
diff --git a/core/java/android/hardware/photography/package.html b/core/java/android/hardware/photography/package.html
new file mode 100644
index 0000000..578bdf5
--- /dev/null
+++ b/core/java/android/hardware/photography/package.html
@@ -0,0 +1,84 @@
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<HTML>
+<BODY>
+<p>The android.hardware.photography package provides an interface to
+individual camera devices connected to an Android device. It replaces
+the deprecated {@link android.hardware.Camera} class.</p>
+
+<p>This package models a camera device as a pipeline, which takes in
+input requests for capturing a single frame, captures the single image
+per the request, and then outputs one capture result metadata packet,
+plus a set of output image buffers for the request. The requests are
+processed in-order, and multiple requests can be in flight at
+once. Since the camera device is a pipeline with multiple stages,
+having multiple requests in flight is required to maintain full
+framerate on most Android devices.</p>
+
+<p>To enumerate, query, and open available camera devices, obtain a
+{@link android.hardware.photography.CameraManager} instance.</p>
+
+<p>Individual {@link android.hardware.photography.CameraDevice
+CameraDevices} provide a set of static property information that
+describes the hardware device and the available settings and output
+parameters for the device. This information is provided through the
+{@link android.hardware.photography.CameraProperties} object.</p>
+
+<p>To capture or stream images from a camera device, the application
+must first configure a set of output Surfaces for use with the camera
+device, with {@link
+android.hardware.photography.CameraDevice#configureOutputs}. Each
+Surface has to be pre-configured with an appropriate size and format
+(if applicable) to match the sizes and formats available from the
+camera device. A target Surface can be obtained from a variety of
+classes, including {@link android.view.SurfaceView}, {@link
+android.graphics.SurfaceTexture} via {@link
+android.view.Surface#Surface(SurfaceTexture), {@link
+android.media.MediaCodec}, and {@link android.media.ImageReader}.
+</p>
+
+<p>The application then needs to construct a {@link
+android.hardware.photography.CaptureRequest}, which defines all the
+capture parameters needed by a camera device to capture a single
+image. The request also lists which of the configured output Surfaces
+should be used as targets for this capture. The CameraDevice has a
+{@link android.hardware.photography.CameraDevice#createCaptureRequest
+convenience factory method} for creating a request for a given use
+case which is optimized for the Android device the application is
+running on.</p>
+
+<p>Once the request has been set up, it can be handed to the
+CameraDevice either for a one-shot {@link
+android.hardware.photography.CameraDevice#capture} or for an endlessly
+{@link android.hardware.photography.CameraDevice#setRepeatingRequest
+repeating} use. Both methods also accept a list of requests to use as
+a burst capture / repeating burst. Repeating requests have a lower
+priority than captures, so a request submitted
+through <code>capture()</code> while there's a repeating request
+configured will be captured as soon as the current repeat (burst)
+capture completes.</p>
+
+<p>After processing a request, the camera device will produce a {@link
+android.hardware.photography.CaptureResult} object, which contains
+information about the state of the camera device at time of capture,
+and the final settings used. These may vary somewhat from the request,
+if rounding or resolving contradictory parameters was necessary. The
+camera device will also send a frame of image data into each of the
+output streams included in the request. These are produced
+asynchronously relative to the output CaptureResult, sometimes
+substantially later.</p>
+
+</BODY>
+</HTML>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 78bf9af..ffcc297 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -464,6 +464,21 @@
}
/**
+ * Checks if the given network type is backed by a Wi-Fi radio.
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeWifi(int networkType) {
+ switch (networkType) {
+ case TYPE_WIFI:
+ case TYPE_WIFI_P2P:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
* Specifies the preferred network type. When the device has more
* than one type available the preferred network type will be used.
* Note that this made sense when we only had 2 network types,
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d0f7511..32bbfbd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -130,7 +130,7 @@
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 6;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
@@ -259,17 +259,7 @@
* {@hide}
*/
public abstract int getUid();
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesReceived(int which);
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesSent(int which);
-
+
public abstract void noteWifiRunningLocked();
public abstract void noteWifiStoppedLocked();
public abstract void noteFullWifiLockAcquiredLocked();
@@ -304,11 +294,14 @@
};
public static final int NUM_USER_ACTIVITY_TYPES = 3;
-
+
public abstract void noteUserActivityLocked(int type);
public abstract boolean hasUserActivity();
public abstract int getUserActivityCount(int type, int which);
-
+
+ public abstract boolean hasNetworkActivity();
+ public abstract long getNetworkActivityCount(int type, int which);
+
public static abstract class Sensor {
/*
* FIXME: it's not correct to use this magic value because it
@@ -929,6 +922,15 @@
*/
public abstract long getBluetoothOnTime(long batteryRealtime, int which);
+ public static final int NETWORK_MOBILE_RX_BYTES = 0;
+ public static final int NETWORK_MOBILE_TX_BYTES = 1;
+ public static final int NETWORK_WIFI_RX_BYTES = 2;
+ public static final int NETWORK_WIFI_TX_BYTES = 3;
+
+ public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_TX_BYTES + 1;
+
+ public abstract long getNetworkActivityCount(int type, int which);
+
/**
* Return whether we are currently running on battery.
*/
@@ -1246,16 +1248,20 @@
totalRealtime / 1000, totalUptime / 1000);
// Calculate total network and wakelock times across all uids.
- long rxTotal = 0;
- long txTotal = 0;
+ long mobileRxTotal = 0;
+ long mobileTxTotal = 0;
+ long wifiRxTotal = 0;
+ long wifiTxTotal = 0;
long fullWakeLockTimeTotal = 0;
long partialWakeLockTimeTotal = 0;
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
- rxTotal += u.getTcpBytesReceived(which);
- txTotal += u.getTcpBytesSent(which);
-
+ mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
+
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
@@ -1279,7 +1285,8 @@
// Dump misc stats
dumpLine(pw, 0 /* uid */, category, MISC_DATA,
screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
- wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
+ wifiRunningTime / 1000, bluetoothOnTime / 1000,
+ mobileRxTotal, mobileTxTotal, wifiRxTotal, wifiTxTotal,
fullWakeLockTimeTotal, partialWakeLockTimeTotal,
getInputEventCount(which));
@@ -1350,14 +1357,18 @@
}
Uid u = uidStats.valueAt(iu);
// Dump Network stats per uid, if any
- long rx = u.getTcpBytesReceived(which);
- long tx = u.getTcpBytesSent(which);
+ long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
-
- if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
-
+
+ if (mobileRx > 0 || mobileTx > 0 || wifiRx > 0 || wifiTx > 0) {
+ dumpLine(pw, uid, category, NETWORK_DATA, mobileRx, mobileTx, wifiRx, wifiTx);
+ }
+
if (fullWifiLockOnTime != 0 || wifiScanTime != 0
|| uidWifiRunningTime != 0) {
dumpLine(pw, uid, category, WIFI_DATA,
@@ -1569,8 +1580,10 @@
pw.println(sb.toString());
// Calculate total network and wakelock times across all uids.
- long rxTotal = 0;
- long txTotal = 0;
+ long mobileRxTotal = 0;
+ long mobileTxTotal = 0;
+ long wifiRxTotal = 0;
+ long wifiTxTotal = 0;
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
@@ -1623,9 +1636,11 @@
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
- rxTotal += u.getTcpBytesReceived(which);
- txTotal += u.getTcpBytesSent(which);
-
+ mobileRxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ mobileTxTotal += u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ wifiRxTotal += u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ wifiTxTotal += u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
+
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
@@ -1658,8 +1673,11 @@
}
pw.print(prefix);
- pw.print(" Total received: "); pw.print(formatBytesLocked(rxTotal));
- pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
+ pw.print(" Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotal));
+ pw.print(", Total sent: "); pw.println(formatBytesLocked(mobileTxTotal));
+ pw.print(prefix);
+ pw.print(" Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotal));
+ pw.print(", Total sent: "); pw.println(formatBytesLocked(wifiTxTotal));
sb.setLength(0);
sb.append(prefix);
sb.append(" Total full wakelock time: "); formatTimeMs(sb,
@@ -1801,18 +1819,25 @@
pw.println(prefix + " #" + uid + ":");
boolean uidActivity = false;
- long tcpReceived = u.getTcpBytesReceived(which);
- long tcpSent = u.getTcpBytesSent(which);
+ long mobileRxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
+ long mobileTxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, which);
+ long wifiRxBytes = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, which);
+ long wifiTxBytes = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
-
- if (tcpReceived != 0 || tcpSent != 0) {
- pw.print(prefix); pw.print(" Network: ");
- pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
- pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
+
+ if (mobileRxBytes > 0 || mobileTxBytes > 0) {
+ pw.print(prefix); pw.print(" Mobile network: ");
+ pw.print(formatBytesLocked(mobileRxBytes)); pw.print(" received, ");
+ pw.print(formatBytesLocked(mobileTxBytes)); pw.println(" sent");
}
-
+ if (wifiRxBytes > 0 || wifiTxBytes > 0) {
+ pw.print(prefix); pw.print(" Wi-Fi network: ");
+ pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
+ pw.print(formatBytesLocked(wifiTxBytes)); pw.println(" sent");
+ }
+
if (u.hasUserActivity()) {
boolean hasData = false;
for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index bfea9ca..2e0e59b 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -164,11 +164,19 @@
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
- NotificationListenerService.this.onNotificationPosted(sbn);
+ try {
+ NotificationListenerService.this.onNotificationPosted(sbn);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationPosted", t);
+ }
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
- NotificationListenerService.this.onNotificationRemoved(sbn);
+ try {
+ NotificationListenerService.this.onNotificationRemoved(sbn);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationRemoved", t);
+ }
}
}
}
diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java
index 6398d3d..917a109 100644
--- a/core/java/android/speech/tts/SynthesisRequest.java
+++ b/core/java/android/speech/tts/SynthesisRequest.java
@@ -41,6 +41,7 @@
private String mVariant;
private int mSpeechRate;
private int mPitch;
+ private int mCallerUid;
public SynthesisRequest(String text, Bundle params) {
mText = text;
@@ -98,6 +99,13 @@
}
/**
+ * Gets the request caller Uid.
+ */
+ public int getCallerUid() {
+ return mCallerUid;
+ }
+
+ /**
* Sets the locale for the request.
*/
void setLanguage(String language, String country, String variant) {
@@ -119,4 +127,11 @@
void setPitch(int pitch) {
mPitch = pitch;
}
+
+ /**
+ * Sets Caller Uid
+ */
+ void setCallerUid(int uid) {
+ mCallerUid = uid;
+ }
}
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 703dcff..575855c 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -557,11 +557,13 @@
// guarded by 'this'.
private AbstractSynthesisCallback mSynthesisCallback;
private final EventLogger mEventLogger;
+ private final int mCallerUid;
public SynthesisSpeechItem(Object callerIdentity, int callerUid, int callerPid,
Bundle params, String text) {
super(callerIdentity, callerUid, callerPid, params);
mText = text;
+ mCallerUid = callerUid;
mSynthesisRequest = new SynthesisRequest(mText, mParams);
mDefaultLocale = getSettingsLocale();
setRequestParams(mSynthesisRequest);
@@ -611,7 +613,7 @@
private void setRequestParams(SynthesisRequest request) {
request.setLanguage(getLanguage(), getCountry(), getVariant());
request.setSpeechRate(getSpeechRate());
-
+ request.setCallerUid(mCallerUid);
request.setPitch(getPitch());
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index edda779..bb0a6e1 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -400,8 +400,16 @@
public void putAll(ArrayMap<? extends K, ? extends V> array) {
final int N = array.mSize;
ensureCapacity(mSize + N);
- for (int i=0; i<N; i++) {
- put(array.keyAt(i), array.valueAt(i));
+ if (mSize == 0) {
+ if (N > 0) {
+ System.arraycopy(array.mHashes, 0, mHashes, 0, N);
+ System.arraycopy(array.mArray, 0, mArray, 0, N<<1);
+ mSize = N;
+ }
+ } else {
+ for (int i=0; i<N; i++) {
+ put(array.keyAt(i), array.valueAt(i));
+ }
}
}
@@ -605,7 +613,7 @@
* Return a {@link java.util.Set} for iterating over and interacting with all keys
* in the array map.
*
- * <p><b>Note:</b> this is a fair inefficient way to access the array contents, it
+ * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
* requires generating a number of temporary objects.</p>
*/
@Override
@@ -617,11 +625,71 @@
* Return a {@link java.util.Collection} for iterating over and interacting with all values
* in the array map.
*
- * <p><b>Note:</b> this is a fair inefficient way to access the array contents, it
+ * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
* requires generating a number of temporary objects.</p>
*/
@Override
public Collection<V> values() {
return getCollection().getValues();
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation returns false if the object is not a map, or
+ * if the maps have different sizes. Otherwise, for each key in this map,
+ * values of both maps are compared. If the values for any key are not
+ * equal, the method returns false, otherwise it returns true.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof Map) {
+ Map<?, ?> map = (Map<?, ?>) object;
+ if (size() != map.size()) {
+ return false;
+ }
+
+ try {
+ for (int i=0; i<mSize; i++) {
+ K key = keyAt(i);
+ V mine = valueAt(i);
+ Object theirs = map.get(key);
+ if (mine == null) {
+ if (theirs != null || !map.containsKey(key)) {
+ return false;
+ }
+ } else if (!mine.equals(theirs)) {
+ return false;
+ }
+ }
+ } catch (NullPointerException ignored) {
+ return false;
+ } catch (ClassCastException ignored) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation sums a hashcode using all keys and values.
+ */
+ @Override
+ public int hashCode() {
+ int result = 0;
+ for (int i=0; i<mSize; i++) {
+ K key = keyAt(i);
+ V value = valueAt(i);
+ result += (key == null ? 0 : key.hashCode())
+ ^ (value == null ? 0 : value.hashCode());
+ }
+ return result;
+ }
+
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 2d6453e..e835a97 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -406,6 +406,10 @@
if (host == null || !ViewRootImpl.isViewDescendantOf(host, root)) {
break;
}
+ // The focused view not shown, we failed.
+ if (!isShown(host)) {
+ break;
+ }
// If the host has a provider ask this provider to search for the
// focus instead fetching all provider nodes to do the search here.
AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index cc7d948..88539f21 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -736,6 +736,21 @@
}
@Override
+ public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
+ Bitmap bitmap = patch.getBitmap();
+ if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+ // Shaders are ignored when drawing patches
+ int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
+ try {
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
+ } finally {
+ if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
+ }
+ }
+
+ @Override
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
Bitmap bitmap = patch.getBitmap();
if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index ee36097..db577f3 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3003,13 +3003,13 @@
}
/**
- * Returns a string that represents the symbolic name of the specified action
+ * Returns a string that represents the symbolic name of the specified unmasked action
* such as "ACTION_DOWN", "ACTION_POINTER_DOWN(3)" or an equivalent numeric constant
* such as "35" if unknown.
*
- * @param action The action.
+ * @param action The unmasked action.
* @return The symbolic name of the specified action.
- * @hide
+ * @see #getAction()
*/
public static String actionToString(int action) {
switch (action) {
@@ -3047,7 +3047,7 @@
* Returns a string that represents the symbolic name of the specified axis
* such as "AXIS_X" or an equivalent numeric constant such as "42" if unknown.
*
- * @param axis The axis
+ * @param axis The axis.
* @return The symbolic name of the specified axis.
*/
public static String axisToString(int axis) {
@@ -3061,7 +3061,7 @@
*
* @param symbolicName The symbolic name of the axis.
* @return The axis or -1 if not found.
- * @see KeyEvent#keycodeToString(int)
+ * @see KeyEvent#keyCodeToString(int)
*/
public static int axisFromString(String symbolicName) {
if (symbolicName == null) {
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 015a78e..99fa2a4 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -277,9 +277,6 @@
*
* <p>This method is intended to be used by frameworks which often need
* direct access to the Surface object (usually to pass it to native code).
- * When designing APIs always use SurfaceHolder to pass surfaces around
- * as opposed to the Surface object itself. A rule of thumb is that
- * application code should never have to call this method.
*
* @return Surface The surface.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6f88bb2..e860dca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1564,6 +1564,8 @@
private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
+ SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
+
/**
* The view's tag.
* {@hide}
@@ -2136,13 +2138,12 @@
/**
* Flag indicating whether a view has accessibility focus.
*/
- static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
/**
- * Flag indicating whether a view state for accessibility has changed.
+ * Flag whether the accessibility state of the subtree rooted at this view changed.
*/
- static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
- << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
/**
* Flag indicating whether a view failed the quickReject() check in draw(). This condition
@@ -2194,6 +2195,12 @@
*/
static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
+ /**
+ * Flag indicating that the view has been through at least one layout since it
+ * was last attached to a window.
+ */
+ static final int PFLAG3_HAS_LAYOUT = 0x4;
+
/* End of masks for mPrivateFlags3 */
@@ -4454,10 +4461,6 @@
onFocusChanged(true, direction, previouslyFocusedRect);
refreshDrawableState();
-
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- notifyAccessibilityStateChanged();
- }
}
}
@@ -4561,10 +4564,6 @@
if (!rootViewRequestFocus()) {
notifyGlobalFocusCleared(this);
}
-
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- notifyAccessibilityStateChanged();
- }
}
}
@@ -4575,11 +4574,8 @@
}
boolean rootViewRequestFocus() {
- View root = getRootView();
- if (root != null) {
- return root.requestFocus();
- }
- return false;
+ final View root = getRootView();
+ return root != null && root.requestFocus();
}
/**
@@ -4596,10 +4592,6 @@
onFocusChanged(false, 0, null);
refreshDrawableState();
-
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- notifyAccessibilityStateChanged();
- }
}
}
@@ -4650,9 +4642,9 @@
*/
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
if (gainFocus) {
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ } else {
+ notifyViewAccessibilityStateChangedIfNeeded();
}
InputMethodManager imm = InputMethodManager.peekInstance();
@@ -4709,6 +4701,10 @@
* @see AccessibilityDelegate
*/
public void sendAccessibilityEvent(int eventType) {
+ // Excluded views do not send accessibility events.
+ if (!includeForAccessibility()) {
+ return;
+ }
if (mAccessibilityDelegate != null) {
mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
} else {
@@ -5367,9 +5363,11 @@
mContentDescription = contentDescription;
final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ notifySubtreeAccessibilityStateChangedIfNeeded();
+ } else {
+ notifyViewAccessibilityStateChangedIfNeeded();
}
- notifyAccessibilityStateChanged();
}
/**
@@ -6146,6 +6144,21 @@
}
/**
+ * Returns true if this view is currently attached to a window.
+ */
+ public boolean isAttachedToWindow() {
+ return mAttachInfo != null;
+ }
+
+ /**
+ * Returns true if this view has been through at least one layout since it
+ * was last attached to or detached from a window.
+ */
+ public boolean hasLayout() {
+ return (mPrivateFlags3 & PFLAG3_HAS_LAYOUT) == PFLAG3_HAS_LAYOUT;
+ }
+
+ /**
* If this view doesn't do any drawing on its own, set this flag to
* allow further optimizations. By default, this flag is not set on
* View, but could be set on some View subclasses such as ViewGroup.
@@ -6649,7 +6662,6 @@
}
invalidate();
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
- notifyAccessibilityStateChanged();
return true;
}
return false;
@@ -6712,7 +6724,6 @@
mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
invalidate();
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
- notifyAccessibilityStateChanged();
}
}
@@ -6886,11 +6897,16 @@
* @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
*/
public void setImportantForAccessibility(int mode) {
+ final boolean oldIncludeForAccessibility = includeForAccessibility();
if (mode != getImportantForAccessibility()) {
mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
& PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
- notifyAccessibilityStateChanged();
+ if (oldIncludeForAccessibility != includeForAccessibility()) {
+ notifySubtreeAccessibilityStateChangedIfNeeded();
+ } else {
+ notifyViewAccessibilityStateChangedIfNeeded();
+ }
}
}
@@ -6997,25 +7013,44 @@
}
/**
- * Notifies accessibility services that some view's important for
- * accessibility state has changed. Note that such notifications
- * are made at most once every
+ * Notifies that the accessibility state of this view changed. The change
+ * is local to this view and does not represent structural changes such
+ * as children and parent. For example, the view became focusable. The
+ * notification is at at most once every
* {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
- * to avoid unnecessary load to the system. Also once a view has
- * made a notifucation this method is a NOP until the notification has
- * been sent to clients.
+ * to avoid unnecessary load to the system. Also once a view has a pending
+ * notifucation this method is a NOP until the notification has been sent.
*
* @hide
- *
- * TODO: Makse sure this method is called for any view state change
- * that is interesting for accessilility purposes.
*/
- public void notifyAccessibilityStateChanged() {
+ public void notifyViewAccessibilityStateChangedIfNeeded() {
if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
return;
}
- if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
- mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
+ if (mSendViewStateChangedAccessibilityEvent == null) {
+ mSendViewStateChangedAccessibilityEvent =
+ new SendViewStateChangedAccessibilityEvent();
+ }
+ mSendViewStateChangedAccessibilityEvent.runOrPost();
+ }
+
+ /**
+ * Notifies that the accessibility state of this view changed. The change
+ * is *not* local to this view and does represent structural changes such
+ * as children and parent. For example, the view size changed. The
+ * notification is at at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
+ * to avoid unnecessary load to the system. Also once a view has a pending
+ * notifucation this method is a NOP until the notification has been sent.
+ *
+ * @hide
+ */
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {
+ if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
+ return;
+ }
+ if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
+ mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
if (mParent != null) {
mParent.childAccessibilityStateChanged(this);
}
@@ -7023,13 +7058,11 @@
}
/**
- * Reset the state indicating the this view has requested clients
- * interested in its accessibility state to be notified.
- *
- * @hide
+ * Reset the flag indicating the accessibility state of the subtree rooted
+ * at this view changed.
*/
- public void resetAccessibilityStateChanged() {
- mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
+ void resetSubtreeAccessibilityStateChanged() {
+ mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
}
/**
@@ -7142,7 +7175,7 @@
|| getAccessibilitySelectionEnd() != end)
&& (start == end)) {
setAccessibilitySelection(start, end);
- notifyAccessibilityStateChanged();
+ notifyViewAccessibilityStateChangedIfNeeded();
return true;
}
} break;
@@ -8563,6 +8596,11 @@
* @param mask Constant indicating the bit range that should be changed
*/
void setFlags(int flags, int mask) {
+ final boolean accessibilityEnabled =
+ AccessibilityManager.getInstance(mContext).isEnabled();
+ final boolean oldIncludeForAccessibility = accessibilityEnabled
+ ? includeForAccessibility() : false;
+
int old = mViewFlags;
mViewFlags = (mViewFlags & ~mask) | (flags & mask);
@@ -8587,9 +8625,6 @@
*/
if (mParent != null) mParent.focusableViewAvailable(this);
}
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- notifyAccessibilityStateChanged();
- }
}
final int newVisibility = flags & VISIBILITY_MASK;
@@ -8710,10 +8745,18 @@
}
}
- if (AccessibilityManager.getInstance(mContext).isEnabled()
- && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
- || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
- notifyAccessibilityStateChanged();
+ if (accessibilityEnabled) {
+ if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
+ || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
+ if (oldIncludeForAccessibility != includeForAccessibility()) {
+ notifySubtreeAccessibilityStateChangedIfNeeded();
+ } else {
+ notifyViewAccessibilityStateChangedIfNeeded();
+ }
+ }
+ if ((changed & ENABLED_MASK) != 0) {
+ notifyViewAccessibilityStateChangedIfNeeded();
+ }
}
}
@@ -11757,9 +11800,13 @@
mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
}
+ mPrivateFlags3 &= ~PFLAG3_HAS_LAYOUT;
+
jumpDrawablesToCurrentState();
clearAccessibilityFocus();
+ resetSubtreeAccessibilityStateChanged();
+
if (isFocused()) {
InputMethodManager imm = InputMethodManager.peekInstance();
imm.focusIn(this);
@@ -12041,6 +12088,7 @@
*/
protected void onDetachedFromWindow() {
mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
+ mPrivateFlags3 &= ~PFLAG3_HAS_LAYOUT;
removeUnsetPressCallback();
removeLongPressCallback();
@@ -12055,8 +12103,6 @@
mCurrentAnimation = null;
mCurrentScene = null;
-
- resetAccessibilityStateChanged();
}
private void cleanupDraw() {
@@ -12835,8 +12881,7 @@
mRecreateDisplayList = true;
}
if (displayList == null) {
- final String name = getClass().getSimpleName();
- displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
+ displayList = mAttachInfo.mHardwareRenderer.createDisplayList(getClass().getName());
// If we're creating a new display list, make sure our parent gets invalidated
// since they will need to recreate their display list to account for this
// new child display list.
@@ -13483,7 +13528,8 @@
onAnimationStart();
}
- boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
+ final Transformation t = parent.getChildTransformation();
+ boolean more = a.getTransformation(drawingTime, t, 1f);
if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
if (parent.mInvalidationTransformation == null) {
parent.mInvalidationTransformation = new Transformation();
@@ -13491,7 +13537,7 @@
invalidationTransform = parent.mInvalidationTransformation;
a.getTransformation(drawingTime, invalidationTransform, 1f);
} else {
- invalidationTransform = parent.mChildTransformation;
+ invalidationTransform = t;
}
if (more) {
@@ -13544,17 +13590,15 @@
if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
ViewGroup parentVG = (ViewGroup) mParent;
- final boolean hasTransform =
- parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
- if (hasTransform) {
- Transformation transform = parentVG.mChildTransformation;
- final int transformType = parentVG.mChildTransformation.getTransformationType();
+ final Transformation t = parentVG.getChildTransformation();
+ if (parentVG.getChildStaticTransformation(this, t)) {
+ final int transformType = t.getTransformationType();
if (transformType != Transformation.TYPE_IDENTITY) {
if ((transformType & Transformation.TYPE_ALPHA) != 0) {
- alpha = transform.getAlpha();
+ alpha = t.getAlpha();
}
if ((transformType & Transformation.TYPE_MATRIX) != 0) {
- displayList.setMatrix(transform.getMatrix());
+ displayList.setMatrix(t.getMatrix());
}
}
}
@@ -13599,7 +13643,7 @@
final int flags = parent.mGroupFlags;
if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
- parent.mChildTransformation.clear();
+ parent.getChildTransformation().clear();
parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
}
@@ -13627,7 +13671,7 @@
if (concatMatrix) {
mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
- transformToApply = parent.mChildTransformation;
+ transformToApply = parent.getChildTransformation();
} else {
if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
@@ -13637,12 +13681,11 @@
}
if (!useDisplayListProperties &&
(flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
- final boolean hasTransform =
- parent.getChildStaticTransformation(this, parent.mChildTransformation);
+ final Transformation t = parent.getChildTransformation();
+ final boolean hasTransform = parent.getChildStaticTransformation(this, t);
if (hasTransform) {
- final int transformType = parent.mChildTransformation.getTransformationType();
- transformToApply = transformType != Transformation.TYPE_IDENTITY ?
- parent.mChildTransformation : null;
+ final int transformType = t.getTransformationType();
+ transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
}
}
@@ -14352,6 +14395,7 @@
}
}
mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
+ mPrivateFlags3 |= PFLAG3_HAS_LAYOUT;
}
/**
@@ -14444,6 +14488,8 @@
mPrivateFlags |= drawn;
mBackgroundSizeChanged = true;
+
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
return changed;
}
@@ -15208,9 +15254,7 @@
invalidate(true);
refreshDrawableState();
dispatchSetSelected(selected);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- notifyAccessibilityStateChanged();
- }
+ notifyViewAccessibilityStateChangedIfNeeded();
}
}
@@ -18825,6 +18869,38 @@
}
}
+ private class SendViewStateChangedAccessibilityEvent implements Runnable {
+ private boolean mPosted;
+ private long mLastEventTimeMillis;
+
+ public void run() {
+ mPosted = false;
+ mLastEventTimeMillis = SystemClock.uptimeMillis();
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ AccessibilityEvent event = AccessibilityEvent.obtain();
+ event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ event.setContentChangeType(AccessibilityEvent.CONTENT_CHANGE_TYPE_NODE);
+ sendAccessibilityEventUnchecked(event);
+ }
+ }
+
+ public void runOrPost() {
+ if (mPosted) {
+ return;
+ }
+ final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
+ final long minEventIntevalMillis =
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
+ if (timeSinceLastMillis >= minEventIntevalMillis) {
+ removeCallbacks(this);
+ run();
+ } else {
+ postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
+ mPosted = true;
+ }
+ }
+ }
+
/**
* Dump all private flags in readable format, useful for documentation and
* sanity checking.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b0fbe84..29b2e4b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -128,7 +128,7 @@
* A Transformation used when drawing children, to
* apply on the child being drawn.
*/
- final Transformation mChildTransformation = new Transformation();
+ private Transformation mChildTransformation;
/**
* Used to track the current invalidation region.
@@ -1698,16 +1698,6 @@
}
/**
- * @hide
- */
- @Override
- public void childAccessibilityStateChanged(View child) {
- if (mParent != null) {
- mParent.childAccessibilityStateChanged(child);
- }
- }
-
- /**
* Implement this method to intercept hover events before they are handled
* by child views.
* <p>
@@ -2534,13 +2524,19 @@
* @hide
*/
@Override
- public void resetAccessibilityStateChanged() {
- super.resetAccessibilityStateChanged();
+ public void childAccessibilityStateChanged(View root) {
+ if (mParent != null) {
+ mParent.childAccessibilityStateChanged(root);
+ }
+ }
+
+ @Override
+ void resetSubtreeAccessibilityStateChanged() {
+ super.resetSubtreeAccessibilityStateChanged();
View[] children = mChildren;
final int childCount = mChildrenCount;
for (int i = 0; i < childCount; i++) {
- View child = children[i];
- child.resetAccessibilityStateChanged();
+ children[i].resetSubtreeAccessibilityStateChanged();
}
}
@@ -3211,6 +3207,13 @@
return false;
}
+ Transformation getChildTransformation() {
+ if (mChildTransformation == null) {
+ mChildTransformation = new Transformation();
+ }
+ return mChildTransformation;
+ }
+
/**
* {@hide}
*/
@@ -3459,7 +3462,7 @@
}
private void clearCachedLayoutMode() {
- if (!getBooleanFlag(FLAG_LAYOUT_MODE_WAS_EXPLICITLY_SET)) {
+ if (!hasBooleanFlag(FLAG_LAYOUT_MODE_WAS_EXPLICITLY_SET)) {
mLayoutMode = LAYOUT_MODE_UNDEFINED;
}
}
@@ -3590,6 +3593,10 @@
if (child.hasTransientState()) {
childHasTransientStateChanged(child, true);
}
+
+ if (child.isImportantForAccessibility() && child.getVisibility() != View.GONE) {
+ notifySubtreeAccessibilityStateChangedIfNeeded();
+ }
}
private void addInArray(View child, int index) {
@@ -3829,6 +3836,10 @@
}
onViewRemoved(view);
+
+ if (view.isImportantForAccessibility() && view.getVisibility() != View.GONE) {
+ notifySubtreeAccessibilityStateChangedIfNeeded();
+ }
}
/**
@@ -4779,7 +4790,7 @@
setBooleanFlag(FLAG_USE_CHILD_DRAWING_ORDER, enabled);
}
- private boolean getBooleanFlag(int flag) {
+ private boolean hasBooleanFlag(int flag) {
return (mGroupFlags & flag) == flag;
}
@@ -4847,7 +4858,7 @@
void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
if (mLayoutMode == LAYOUT_MODE_UNDEFINED ||
mLayoutMode == layoutModeOfRoot ||
- getBooleanFlag(FLAG_LAYOUT_MODE_WAS_EXPLICITLY_SET)) {
+ hasBooleanFlag(FLAG_LAYOUT_MODE_WAS_EXPLICITLY_SET)) {
return;
}
setLayoutMode(LAYOUT_MODE_UNDEFINED, false);
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 5510939..2d86bfe 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -15,6 +15,7 @@
*/
package android.view;
+import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -169,6 +170,14 @@
child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]);
}
parent.removeView(child);
+ if (parent.getLayoutTransition() != null) {
+ // LayoutTransition will cause the child to delay removal - cancel it
+ parent.getLayoutTransition().cancel(LayoutTransition.DISAPPEARING);
+ }
+ // fail-safe if view is still attached for any reason
+ if (child.getParent() != null) {
+ child.mParent = null;
+ }
}
super.addView(child);
}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d79aa7e..2ebc1a19 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -292,13 +292,14 @@
public ViewParent getParentForAccessibility();
/**
- * A child notifies its parent that its state for accessibility has changed.
- * That is some of the child properties reported to accessibility services has
- * changed, hence the interested services have to be notified for the new state.
+ * A child notifies its parent that the accessibility state of a subtree rooted
+ * at a given node changed. That is the structure of the subtree is different.
+ *
+ * @param The root of the changed subtree.
*
* @hide
*/
- public void childAccessibilityStateChanged(View child);
+ public void childAccessibilityStateChanged(View root);
/**
* Tells if this view parent can resolve the layout direction.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bcc58a2..60d8a75 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1728,10 +1728,6 @@
if (triggerGlobalLayoutListener) {
attachInfo.mRecomputeGlobalAttributes = false;
attachInfo.mTreeObserver.dispatchOnGlobalLayout();
-
- if (AccessibilityManager.getInstance(host.mContext).isEnabled()) {
- postSendWindowContentChangedCallback(mView);
- }
}
if (computesInternalInsets) {
@@ -2791,6 +2787,7 @@
setAccessibilityFocus(null, null);
+ mView.assignParent(null);
mView = null;
mAttachInfo.mRootView = null;
mAttachInfo.mSurface = null;
@@ -5153,6 +5150,7 @@
mAdded = false;
}
+ WindowManagerGlobal.getInstance().doRemoveView(this);
}
public void requestUpdateConfiguration(Configuration config) {
@@ -5712,15 +5710,7 @@
mSendWindowContentChangedAccessibilityEvent =
new SendWindowContentChangedAccessibilityEvent();
}
- View oldSource = mSendWindowContentChangedAccessibilityEvent.mSource;
- if (oldSource == null) {
- mSendWindowContentChangedAccessibilityEvent.mSource = source;
- mHandler.postDelayed(mSendWindowContentChangedAccessibilityEvent,
- ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
- } else {
- mSendWindowContentChangedAccessibilityEvent.mSource =
- getCommonPredecessor(oldSource, source);
- }
+ mSendWindowContentChangedAccessibilityEvent.runOrPost(source);
}
/**
@@ -6404,12 +6394,32 @@
private class SendWindowContentChangedAccessibilityEvent implements Runnable {
public View mSource;
+ public long mLastEventTimeMillis;
public void run() {
+ mLastEventTimeMillis = SystemClock.uptimeMillis();
+ AccessibilityEvent event = AccessibilityEvent.obtain();
+ event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ event.setContentChangeType(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ mSource.sendAccessibilityEventUnchecked(event);
+ mSource.resetSubtreeAccessibilityStateChanged();
+ mSource = null;
+ }
+
+ public void runOrPost(View source) {
if (mSource != null) {
- mSource.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
- mSource.resetAccessibilityStateChanged();
- mSource = null;
+ mSource = getCommonPredecessor(mSource, source);
+ return;
+ }
+ mSource = source;
+ final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
+ final long minEventIntevalMillis =
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
+ if (timeSinceLastMillis >= minEventIntevalMillis) {
+ mSource.removeCallbacks(this);
+ run();
+ } else {
+ mSource.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
}
}
}
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 0ff46e9..f7b85cc 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -22,7 +22,6 @@
import android.content.res.Configuration;
import android.opengl.ManagedEGLContext;
import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -33,6 +32,7 @@
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Provides low-level communication with the system window manager for
@@ -107,9 +107,10 @@
private final Object mLock = new Object();
- private View[] mViews;
- private ViewRootImpl[] mRoots;
- private WindowManager.LayoutParams[] mParams;
+ private final ArrayList<View> mViews = new ArrayList<View>();
+ private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
+ private final ArrayList<WindowManager.LayoutParams> mParams =
+ new ArrayList<WindowManager.LayoutParams>();
private boolean mNeedsEglTerminate;
private Runnable mSystemPropertyUpdater;
@@ -162,11 +163,10 @@
public String[] getViewRootNames() {
synchronized (mLock) {
- if (mRoots == null) return new String[0];
- String[] mViewRoots = new String[mRoots.length];
- int i = 0;
- for (ViewRootImpl root : mRoots) {
- mViewRoots[i++] = getWindowName(root);
+ final int numRoots = mRoots.size();
+ String[] mViewRoots = new String[numRoots];
+ for (int i = 0; i < numRoots; ++i) {
+ mViewRoots[i] = getWindowName(mRoots.get(i));
}
return mViewRoots;
}
@@ -174,8 +174,8 @@
public View getRootView(String name) {
synchronized (mLock) {
- if (mRoots == null) return null;
- for (ViewRootImpl root : mRoots) {
+ for (int i = mRoots.size() - 1; i >= 0; --i) {
+ final ViewRootImpl root = mRoots.get(i);
if (name.equals(getWindowName(root))) return root.getView();
}
}
@@ -209,8 +209,8 @@
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
- for (ViewRootImpl viewRoot : mRoots) {
- viewRoot.loadSystemProperties();
+ for (int i = mRoots.size() - 1; i >= 0; --i) {
+ mRoots.get(i).loadSystemProperties();
}
}
}
@@ -228,10 +228,10 @@
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- final int count = mViews != null ? mViews.length : 0;
- for (int i=0; i<count; i++) {
- if (mRoots[i].mWindow.asBinder() == wparams.token) {
- panelParentView = mViews[i];
+ final int count = mViews.size();
+ for (int i = 0; i < count; i++) {
+ if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
+ panelParentView = mViews.get(i);
}
}
}
@@ -240,28 +240,9 @@
view.setLayoutParams(wparams);
- if (mViews == null) {
- index = 1;
- mViews = new View[1];
- mRoots = new ViewRootImpl[1];
- mParams = new WindowManager.LayoutParams[1];
- } else {
- index = mViews.length + 1;
- Object[] old = mViews;
- mViews = new View[index];
- System.arraycopy(old, 0, mViews, 0, index-1);
- old = mRoots;
- mRoots = new ViewRootImpl[index];
- System.arraycopy(old, 0, mRoots, 0, index-1);
- old = mParams;
- mParams = new WindowManager.LayoutParams[index];
- System.arraycopy(old, 0, mParams, 0, index-1);
- }
- index--;
-
- mViews[index] = view;
- mRoots[index] = root;
- mParams[index] = wparams;
+ mViews.add(view);
+ mRoots.add(root);
+ mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
@@ -293,8 +274,9 @@
synchronized (mLock) {
int index = findViewLocked(view, true);
- ViewRootImpl root = mRoots[index];
- mParams[index] = wparams;
+ ViewRootImpl root = mRoots.get(index);
+ mParams.remove(index);
+ mParams.add(index, wparams);
root.setLayoutParams(wparams, false);
}
}
@@ -306,7 +288,8 @@
synchronized (mLock) {
int index = findViewLocked(view, true);
- View curView = removeViewLocked(index, immediate);
+ View curView = mRoots.get(index).getView();
+ removeViewLocked(index, immediate);
if (curView == view) {
return;
}
@@ -318,16 +301,13 @@
public void closeAll(IBinder token, String who, String what) {
synchronized (mLock) {
- if (mViews == null)
- return;
-
- int count = mViews.length;
+ int count = mViews.size();
//Log.i("foo", "Closing all windows of " + token);
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
//Log.i("foo", "@ " + i + " token " + mParams[i].token
// + " view " + mRoots[i].getView());
- if (token == null || mParams[i].token == token) {
- ViewRootImpl root = mRoots[i];
+ if (token == null || mParams.get(i).token == token) {
+ ViewRootImpl root = mRoots.get(i);
//Log.i("foo", "Force closing " + root);
if (who != null) {
@@ -335,77 +315,48 @@
what + " " + who + " has leaked window "
+ root.getView() + " that was originally added here");
leak.setStackTrace(root.getLocation().getStackTrace());
- Log.e(TAG, leak.getMessage(), leak);
+ Log.e(TAG, "", leak);
}
removeViewLocked(i, false);
- i--;
- count--;
}
}
}
}
- private View removeViewLocked(int index, boolean immediate) {
- ViewRootImpl root = mRoots[index];
+ private void removeViewLocked(int index, boolean immediate) {
+ ViewRootImpl root = mRoots.get(index);
View view = root.getView();
if (view != null) {
InputMethodManager imm = InputMethodManager.getInstance();
if (imm != null) {
- imm.windowDismissed(mViews[index].getWindowToken());
+ imm.windowDismissed(mViews.get(index).getWindowToken());
}
}
root.die(immediate);
-
- final int count = mViews.length;
-
- // remove it from the list
- View[] tmpViews = new View[count-1];
- removeItem(tmpViews, mViews, index);
- mViews = tmpViews;
-
- ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
- removeItem(tmpRoots, mRoots, index);
- mRoots = tmpRoots;
-
- WindowManager.LayoutParams[] tmpParams
- = new WindowManager.LayoutParams[count-1];
- removeItem(tmpParams, mParams, index);
- mParams = tmpParams;
-
if (view != null) {
view.assignParent(null);
- // func doesn't allow null... does it matter if we clear them?
- //view.setLayoutParams(null);
}
- return view;
}
- private static void removeItem(Object[] dst, Object[] src, int index) {
- if (dst.length > 0) {
- if (index > 0) {
- System.arraycopy(src, 0, dst, 0, index);
- }
- if (index < dst.length) {
- System.arraycopy(src, index+1, dst, index, src.length-index-1);
+ void doRemoveView(ViewRootImpl root) {
+ synchronized (mLock) {
+ final int index = mRoots.indexOf(root);
+ if (index >= 0) {
+ mRoots.remove(index);
+ mViews.remove(index);
+ mParams.remove(index);
}
}
}
private int findViewLocked(View view, boolean required) {
- if (mViews != null) {
- final int count = mViews.length;
- for (int i = 0; i < count; i++) {
- if (mViews[i] == view) {
- return i;
- }
- }
+ final int index = mViews.indexOf(view);
+ if (required && index < 0) {
+ throw new IllegalArgumentException("View=" + view + " not attached to window manager");
}
- if (required) {
- throw new IllegalArgumentException("View not attached to window manager");
- }
- return -1;
+ return index;
}
public void startTrimMemory(int level) {
@@ -418,10 +369,8 @@
// Destroy all hardware surfaces and resources associated to
// known windows
synchronized (mLock) {
- if (mViews == null) return;
- int count = mViews.length;
- for (int i = 0; i < count; i++) {
- mRoots[i].terminateHardwareResources();
+ for (int i = mRoots.size() - 1; i >= 0; --i) {
+ mRoots.get(i).terminateHardwareResources();
}
}
// Force a full memory flush
@@ -445,10 +394,8 @@
public void trimLocalMemory() {
synchronized (mLock) {
- if (mViews == null) return;
- int count = mViews.length;
- for (int i = 0; i < count; i++) {
- mRoots[i].destroyHardwareLayers();
+ for (int i = mRoots.size() - 1; i >= 0; --i) {
+ mRoots.get(i).destroyHardwareLayers();
}
}
}
@@ -458,51 +405,49 @@
PrintWriter pw = new PrintWriter(fout);
try {
synchronized (mLock) {
- if (mViews != null) {
- final int count = mViews.length;
+ final int count = mViews.size();
- pw.println("Profile data in ms:");
+ pw.println("Profile data in ms:");
- for (int i = 0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- String name = getWindowName(root);
- pw.printf("\n\t%s", name);
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots.get(i);
+ String name = getWindowName(root);
+ pw.printf("\n\t%s", name);
- HardwareRenderer renderer =
- root.getView().mAttachInfo.mHardwareRenderer;
- if (renderer != null) {
- renderer.dumpGfxInfo(pw);
- }
+ HardwareRenderer renderer =
+ root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ renderer.dumpGfxInfo(pw);
}
-
- pw.println("\nView hierarchy:\n");
-
- int viewsCount = 0;
- int displayListsSize = 0;
- int[] info = new int[2];
-
- for (int i = 0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- root.dumpGfxInfo(info);
-
- String name = getWindowName(root);
- pw.printf(" %s\n %d views, %.2f kB of display lists",
- name, info[0], info[1] / 1024.0f);
- HardwareRenderer renderer =
- root.getView().mAttachInfo.mHardwareRenderer;
- if (renderer != null) {
- pw.printf(", %d frames rendered", renderer.getFrameCount());
- }
- pw.printf("\n\n");
-
- viewsCount += info[0];
- displayListsSize += info[1];
- }
-
- pw.printf("\nTotal ViewRootImpl: %d\n", count);
- pw.printf("Total Views: %d\n", viewsCount);
- pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f);
}
+
+ pw.println("\nView hierarchy:\n");
+
+ int viewsCount = 0;
+ int displayListsSize = 0;
+ int[] info = new int[2];
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots.get(i);
+ root.dumpGfxInfo(info);
+
+ String name = getWindowName(root);
+ pw.printf(" %s\n %d views, %.2f kB of display lists",
+ name, info[0], info[1] / 1024.0f);
+ HardwareRenderer renderer =
+ root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ pw.printf(", %d frames rendered", renderer.getFrameCount());
+ }
+ pw.printf("\n\n");
+
+ viewsCount += info[0];
+ displayListsSize += info[1];
+ }
+
+ pw.printf("\nTotal ViewRootImpl: %d\n", count);
+ pw.printf("Total Views: %d\n", viewsCount);
+ pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f);
}
} finally {
pw.flush();
@@ -516,13 +461,11 @@
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (mLock) {
- if (mViews != null) {
- int count = mViews.length;
- for (int i=0; i < count; i++) {
- if (token == null || mParams[i].token == token) {
- ViewRootImpl root = mRoots[i];
- root.setStopped(stopped);
- }
+ int count = mViews.size();
+ for (int i = 0; i < count; i++) {
+ if (token == null || mParams.get(i).token == token) {
+ ViewRootImpl root = mRoots.get(i);
+ root.setStopped(stopped);
}
}
}
@@ -530,13 +473,11 @@
public void reportNewConfiguration(Configuration config) {
synchronized (mLock) {
- if (mViews != null) {
- int count = mViews.length;
- config = new Configuration(config);
- for (int i=0; i < count; i++) {
- ViewRootImpl root = mRoots[i];
- root.requestUpdateConfiguration(config);
- }
+ int count = mViews.size();
+ config = new Configuration(config);
+ for (int i=0; i < count; i++) {
+ ViewRootImpl root = mRoots.get(i);
+ root.requestUpdateConfiguration(config);
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index dbeca1f..82c8163 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -326,6 +326,7 @@
* <em>Properties:</em></br>
* <ul>
* <li>{@link #getEventType()} - The type of the event.</li>
+ * <li>{@link #getContentChangeType()} - The type of content change.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
@@ -661,6 +662,18 @@
public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
/**
+ * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+ * The subtree rooted at the source node changed.
+ */
+ public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0;
+
+ /**
+ * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+ * Only the source node changed.
+ */
+ public static final int CONTENT_CHANGE_TYPE_NODE = 1;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -695,6 +708,7 @@
private long mEventTime;
int mMovementGranularity;
int mAction;
+ int mContentChangeType;
private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>();
@@ -714,6 +728,7 @@
mEventType = event.mEventType;
mMovementGranularity = event.mMovementGranularity;
mAction = event.mAction;
+ mContentChangeType = event.mContentChangeType;
mEventTime = event.mEventTime;
mPackageName = event.mPackageName;
}
@@ -777,6 +792,33 @@
}
/**
+ * Gets the type of node tree change signaled by an
+ * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
+ *
+ * @see #CONTENT_CHANGE_TYPE_NODE
+ * @see #CONTENT_CHANGE_TYPE_SUBTREE
+ *
+ * @return The change type.
+ */
+ public int getContentChangeType() {
+ return mContentChangeType;
+ }
+
+ /**
+ * Sets the type of node tree change signaled by an
+ * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
+ *
+ * @see #CONTENT_CHANGE_TYPE_NODE
+ * @see #CONTENT_CHANGE_TYPE_SUBTREE
+ *
+ * @param changeType The change type.
+ */
+ public void setContentChangeType(int changeType) {
+ enforceNotSealed();
+ mContentChangeType = changeType;
+ }
+
+ /**
* Sets the event type.
*
* @param eventType The event type.
@@ -943,6 +985,7 @@
mEventType = 0;
mMovementGranularity = 0;
mAction = 0;
+ mContentChangeType = 0;
mPackageName = null;
mEventTime = 0;
while (!mRecords.isEmpty()) {
@@ -961,6 +1004,7 @@
mEventType = parcel.readInt();
mMovementGranularity = parcel.readInt();
mAction = parcel.readInt();
+ mContentChangeType = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
mConnectionId = parcel.readInt();
@@ -1013,6 +1057,7 @@
parcel.writeInt(mEventType);
parcel.writeInt(mMovementGranularity);
parcel.writeInt(mAction);
+ parcel.writeInt(mContentChangeType);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
parcel.writeInt(mConnectionId);
@@ -1074,6 +1119,7 @@
builder.append(super.toString());
if (DEBUG) {
builder.append("\n");
+ builder.append("; ContentChangeType: ").append(mContentChangeType);
builder.append("; sourceWindowId: ").append(mSourceWindowId);
builder.append("; mSourceNodeId: ").append(mSourceNodeId);
for (int i = 0; i < mRecords.size(); i++) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 84d7e72..139df3e 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -163,7 +163,7 @@
public AccessibilityNodeInfo getRootInActiveWindow(int connectionId) {
return findAccessibilityNodeInfoByAccessibilityId(connectionId,
AccessibilityNodeInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
- AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
+ false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
}
/**
@@ -177,18 +177,22 @@
* where to start the search. Use
* {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
* to start from the root.
+ * @param bypassCache Whether to bypass the cache while looking for the node.
* @param prefetchFlags flags to guide prefetching.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
- int accessibilityWindowId, long accessibilityNodeId, int prefetchFlags) {
+ int accessibilityWindowId, long accessibilityNodeId, boolean bypassCache,
+ int prefetchFlags) {
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
- AccessibilityNodeInfo cachedInfo = sAccessibilityNodeInfoCache.get(
- accessibilityNodeId);
- if (cachedInfo != null) {
- return cachedInfo;
+ if (!bypassCache) {
+ AccessibilityNodeInfo cachedInfo = sAccessibilityNodeInfoCache.get(
+ accessibilityNodeId);
+ if (cachedInfo != null) {
+ return cachedInfo;
+ }
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
@@ -350,7 +354,7 @@
}
} catch (RemoteException re) {
if (DEBUG) {
- Log.w(LOG_TAG, "Error while calling remote findAccessibilityFocus", re);
+ Log.w(LOG_TAG, "Error while calling remote findFocus", re);
}
}
return null;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index d9c9b69..750e022 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -21,6 +21,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.InputType;
import android.util.Pools.SynchronizedPool;
import android.util.SparseLongArray;
import android.view.View;
@@ -482,6 +483,9 @@
private int mTextSelectionStart = UNDEFINED;
private int mTextSelectionEnd = UNDEFINED;
+ private int mInputType = InputType.TYPE_NULL;
+
+ private Bundle mBundle;
private int mConnectionId = UNDEFINED;
@@ -594,16 +598,20 @@
* since it represents a view that is no longer in the view tree and should
* be recycled.
* </p>
+ *
+ * @param bypassCache Whether to bypass the cache.
* @return Whether the refresh succeeded.
+ *
+ * @hide
*/
- public boolean refresh() {
+ public boolean refresh(boolean bypassCache) {
enforceSealed();
if (!canPerformRequestOverConnection(mSourceNodeId)) {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
- mConnectionId, mWindowId, mSourceNodeId, 0);
+ mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
if (refreshedInfo == null) {
return false;
}
@@ -613,6 +621,19 @@
}
/**
+ * Refreshes this info with the latest state of the view it represents.
+ * <p>
+ * <strong>Note:</strong> If this method returns false this info is obsolete
+ * since it represents a view that is no longer in the view tree and should
+ * be recycled.
+ * </p>
+ * @return Whether the refresh succeeded.
+ */
+ public boolean refresh() {
+ return refresh(false);
+ }
+
+ /**
* @return The ids of the children.
*
* @hide
@@ -652,7 +673,7 @@
final long childId = mChildNodeIds.get(index);
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
- childId, FLAG_PREFETCH_DESCENDANTS);
+ childId, false, FLAG_PREFETCH_DESCENDANTS);
}
/**
@@ -878,7 +899,7 @@
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mParentNodeId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mParentNodeId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1470,7 +1491,7 @@
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabelForId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mLabelForId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1527,7 +1548,7 @@
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabeledById, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mLabeledById, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1600,6 +1621,52 @@
}
/**
+ * Gets the input type of the source as defined by {@link InputType}.
+ *
+ * @return The input type.
+ */
+ public int getInputType() {
+ return mInputType;
+ }
+
+ /**
+ * Sets the input type of the source as defined by {@link InputType}.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an
+ * AccessibilityService.
+ * </p>
+ *
+ * @param inputType The input type.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setInputType(int inputType) {
+ mInputType = inputType;
+ }
+
+ /**
+ * Gets an optional bundle with additional data. The bundle
+ * is lazily created and never <code>null</code>.
+ * <p>
+ * <strong>Note:</strong> It is recommended to use the package
+ * name of your application as a prefix for the keys to avoid
+ * collisions which may confuse an accessibility service if the
+ * same key has different meaning when emitted from different
+ * applications.
+ * </p>
+ *
+ * @return The bundle.
+ */
+ public Bundle getBundle() {
+ if (mBundle == null) {
+ mBundle = new Bundle();
+ }
+ return mBundle;
+ }
+
+ /**
* Gets the value of a boolean property.
*
* @param property The property.
@@ -1845,6 +1912,14 @@
parcel.writeInt(mTextSelectionStart);
parcel.writeInt(mTextSelectionEnd);
+ parcel.writeInt(mInputType);
+
+ if (mBundle != null) {
+ parcel.writeInt(1);
+ parcel.writeBundle(mBundle);
+ } else {
+ parcel.writeInt(0);
+ }
// Since instances of this class are fetched via synchronous i.e. blocking
// calls in IPCs we always recycle as soon as the instance is marshaled.
@@ -1880,6 +1955,10 @@
}
mTextSelectionStart = other.mTextSelectionStart;
mTextSelectionEnd = other.mTextSelectionEnd;
+ mInputType = other.mInputType;
+ if (other.mBundle != null && !other.mBundle.isEmpty()) {
+ getBundle().putAll(other.mBundle);
+ }
}
/**
@@ -1927,6 +2006,11 @@
mTextSelectionStart = parcel.readInt();
mTextSelectionEnd = parcel.readInt();
+ mInputType = parcel.readInt();
+
+ if (parcel.readInt() == 1) {
+ getBundle().putAll(parcel.readBundle());
+ }
}
/**
@@ -1953,6 +2037,10 @@
mActions = 0;
mTextSelectionStart = UNDEFINED;
mTextSelectionEnd = UNDEFINED;
+ mInputType = InputType.TYPE_NULL;
+ if (mBundle != null) {
+ mBundle.clear();
+ }
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
index 28518aa..dded74c 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
@@ -39,9 +39,9 @@
private static final boolean ENABLED = true;
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
- private static final boolean CHECK_INTEGRITY = true;
+ private static final boolean CHECK_INTEGRITY_IF_DEBUGGABLE_BUILD = true;
private final Object mLock = new Object();
@@ -67,16 +67,12 @@
if (ENABLED) {
final int eventType = event.getEventType();
switch (eventType) {
- case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
- // New window so we clear the cache.
- mWindowId = event.getWindowId();
- clear();
- } break;
+ case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
final int windowId = event.getWindowId();
+ // If a new window, we clear the cache.
if (mWindowId != windowId) {
- // New window so we clear the cache.
mWindowId = windowId;
clear();
}
@@ -87,34 +83,48 @@
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
- // Since we prefetch the descendants of a node we
- // just remove the entire subtree since when the node
- // is fetched we will gets its descendant anyway.
+ refreshCachedNode(event.getSourceNodeId());
+ } break;
+ case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+ clearSubTreeLocked(event.getSourceNodeId());
+ } break;
+ case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
synchronized (mLock) {
final long sourceId = event.getSourceNodeId();
- clearSubTreeLocked(sourceId);
- if (eventType == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- clearSubtreeWithOldInputFocusLocked(sourceId);
+ if (event.getContentChangeType()
+ == AccessibilityEvent.CONTENT_CHANGE_TYPE_NODE) {
+ refreshCachedNode(sourceId);
+ } else {
+ clearSubTreeLocked(sourceId);
}
- if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
- clearSubtreeWithOldAccessibilityFocusLocked(sourceId);
- }
- }
- } break;
- case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
- case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
- synchronized (mLock) {
- final long accessibilityNodeId = event.getSourceNodeId();
- clearSubTreeLocked(accessibilityNodeId);
}
} break;
}
- if (Build.IS_DEBUGGABLE && CHECK_INTEGRITY) {
+ if (Build.IS_DEBUGGABLE && CHECK_INTEGRITY_IF_DEBUGGABLE_BUILD) {
checkIntegrity();
}
}
}
+ private void refreshCachedNode(long sourceId) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Refresing cached node.");
+ }
+ synchronized (mLock) {
+ AccessibilityNodeInfo cachedInfo = mCacheImpl.get(sourceId);
+ // If the source is not in the cache - nothing to do.
+ if (cachedInfo == null) {
+ return;
+ }
+ // The node changed so we will just refresh it right now.
+ if (cachedInfo.refresh(false)) {
+ return;
+ }
+ // Weird, we could not refresh. Just evict the entire sub-tree.
+ clearSubTreeLocked(sourceId);
+ }
+ }
+
/**
* Gets a cached {@link AccessibilityNodeInfo} given its accessibility node id.
*
@@ -131,7 +141,7 @@
info = AccessibilityNodeInfo.obtain(info);
}
if (DEBUG) {
- Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
+// Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
}
return info;
}
@@ -149,7 +159,7 @@
if (ENABLED) {
synchronized(mLock) {
if (DEBUG) {
- Log.i(LOG_TAG, "add(" + info + ")");
+// Log.i(LOG_TAG, "add(" + info + ")");
}
final long sourceId = info.getSourceNodeId();
@@ -212,6 +222,13 @@
* @param rootNodeId The root id.
*/
private void clearSubTreeLocked(long rootNodeId) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing cached subtree.");
+ }
+ clearSubTreeRecursiveLocked(rootNodeId);
+ }
+
+ private void clearSubTreeRecursiveLocked(long rootNodeId) {
AccessibilityNodeInfo current = mCacheImpl.get(rootNodeId);
if (current == null) {
return;
@@ -221,41 +238,7 @@
final int childCount = childNodeIds.size();
for (int i = 0; i < childCount; i++) {
final long childNodeId = childNodeIds.valueAt(i);
- clearSubTreeLocked(childNodeId);
- }
- }
-
- /**
- * We are enforcing the invariant for a single input focus.
- *
- * @param currentInputFocusId The current input focused node.
- */
- private void clearSubtreeWithOldInputFocusLocked(long currentInputFocusId) {
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
- AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
- final long infoSourceId = info.getSourceNodeId();
- if (infoSourceId != currentInputFocusId && info.isFocused()) {
- clearSubTreeLocked(infoSourceId);
- return;
- }
- }
- }
-
- /**
- * We are enforcing the invariant for a single accessibility focus.
- *
- * @param currentAccessibilityFocusId The current input focused node.
- */
- private void clearSubtreeWithOldAccessibilityFocusLocked(long currentAccessibilityFocusId) {
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
- AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
- final long infoSourceId = info.getSourceNodeId();
- if (infoSourceId != currentAccessibilityFocusId && info.isAccessibilityFocused()) {
- clearSubTreeLocked(infoSourceId);
- return;
- }
+ clearSubTreeRecursiveLocked(childNodeId);
}
}
@@ -327,16 +310,17 @@
}
// Check for disconnected nodes or ones from another window.
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
+ for (int i = 0; i < mCacheImpl.size(); i++) {
AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
if (!seen.contains(info)) {
if (info.getWindowId() == windowId) {
- Log.e(LOG_TAG, "Disconneced node: ");
+ Log.e(LOG_TAG, "Disconneced node: " + info);
} else {
Log.e(LOG_TAG, "Node from: " + info.getWindowId() + " not from:"
+ windowId + " " + info);
}
+ mCacheImpl.removeAt(i);
+ i--;
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 7147c57..3fcd218 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -164,7 +164,7 @@
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
- mSourceNodeId, GET_SOURCE_PREFETCH_FLAGS);
+ mSourceNodeId, false, GET_SOURCE_PREFETCH_FLAGS);
}
/**
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index e8c1d23..890909b 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -29,19 +29,19 @@
/**
* Indicates a transformation that has no effect (alpha = 1 and identity matrix.)
*/
- public static int TYPE_IDENTITY = 0x0;
+ public static final int TYPE_IDENTITY = 0x0;
/**
* Indicates a transformation that applies an alpha only (uses an identity matrix.)
*/
- public static int TYPE_ALPHA = 0x1;
+ public static final int TYPE_ALPHA = 0x1;
/**
* Indicates a transformation that applies a matrix only (alpha = 1.)
*/
- public static int TYPE_MATRIX = 0x2;
+ public static final int TYPE_MATRIX = 0x2;
/**
* Indicates a transformation that applies an alpha and a matrix.
*/
- public static int TYPE_BOTH = TYPE_ALPHA | TYPE_MATRIX;
+ public static final int TYPE_BOTH = TYPE_ALPHA | TYPE_MATRIX;
protected Matrix mMatrix;
protected float mAlpha;
diff --git a/core/java/android/view/transition/Crossfade.java b/core/java/android/view/transition/Crossfade.java
index 7a55b0d..a40d0bf 100644
--- a/core/java/android/view/transition/Crossfade.java
+++ b/core/java/android/view/transition/Crossfade.java
@@ -26,12 +26,12 @@
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.util.ArrayMap;
import android.util.Log;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewOverlay;
import java.util.Map;
@@ -54,13 +54,97 @@
private static RectEvaluator sRectEvaluator = new RectEvaluator();
+ private int mFadeBehavior = FADE_BEHAVIOR_REVEAL;
+ private int mResizeBehavior = RESIZE_BEHAVIOR_SCALE;
+
+ /**
+ * Flag specifying that the fading animation should cross-fade
+ * between the old and new representation of all affected target
+ * views. This means that the old representation will fade out
+ * while the new one fades in. This effect may work well on views
+ * without solid backgrounds, such as TextViews.
+ *
+ * @see #setFadeBehavior(int)
+ */
+ public static final int FADE_BEHAVIOR_CROSSFADE = 0;
+ /**
+ * Flag specifying that the fading animation should reveal the
+ * new representation of all affected target views. This means
+ * that the old representation will fade out, gradually
+ * revealing the new representation, which remains opaque
+ * the whole time. This effect may work well on views
+ * with solid backgrounds, such as ImageViews.
+ *
+ * @see #setFadeBehavior(int)
+ */
+ public static final int FADE_BEHAVIOR_REVEAL = 1;
+
+ /**
+ * Flag specifying that the transition should not animate any
+ * changes in size between the old and new target views.
+ * This means that no scaling will take place as a result of
+ * this transition
+ *
+ * @see #setResizeBehavior(int)
+ */
+ public static final int RESIZE_BEHAVIOR_NONE = 0;
+ /**
+ * Flag specifying that the transition should animate any
+ * changes in size between the old and new target views.
+ * This means that the animation will scale the start/end
+ * representations of affected views from the starting size
+ * to the ending size over the course of the animation.
+ * This effect may work well on images, but is not recommended
+ * for text.
+ *
+ * @see #setResizeBehavior(int)
+ */
+ public static final int RESIZE_BEHAVIOR_SCALE = 1;
+
+ // TODO: Add fade/resize behaviors to xml resources
+
+ /**
+ * Sets the type of fading animation that will be run, one of
+ * {@link #FADE_BEHAVIOR_CROSSFADE} and {@link #FADE_BEHAVIOR_REVEAL}.
+ *
+ * @param fadeBehavior The type of fading animation to use when this
+ * transition is run.
+ */
+ public void setFadeBehavior(int fadeBehavior) {
+ if (fadeBehavior >= FADE_BEHAVIOR_CROSSFADE && fadeBehavior <= FADE_BEHAVIOR_REVEAL) {
+ mFadeBehavior = fadeBehavior;
+ }
+ }
+
+ public int getFadeBehavior() {
+ return mFadeBehavior;
+ }
+
+ /**
+ * Sets the type of resizing behavior that will be used during the
+ * transition animation, one of {@link #RESIZE_BEHAVIOR_NONE} and
+ * {@link #RESIZE_BEHAVIOR_SCALE}.
+ *
+ * @param resizeBehavior The type of resizing behavior to use when this
+ * transition is run.
+ */
+ public void setResizeBehavior(int resizeBehavior) {
+ if (resizeBehavior >= RESIZE_BEHAVIOR_NONE && resizeBehavior <= RESIZE_BEHAVIOR_SCALE) {
+ mResizeBehavior = resizeBehavior;
+ }
+ }
+
+ public int getResizeBehavior() {
+ return mResizeBehavior;
+ }
+
@Override
protected boolean prePlay(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
return false;
}
- final View view = startValues.view;
+ final View view = endValues.view;
Map<String, Object> startVals = startValues.values;
Map<String, Object> endVals = endValues.values;
Bitmap startBitmap = (Bitmap) startVals.get(PROPNAME_BITMAP);
@@ -72,8 +156,12 @@
" for start, end: " + startBitmap + ", " + endBitmap);
}
if (startDrawable != null && endDrawable != null && !startBitmap.sameAs(endBitmap)) {
- view.getOverlay().add(endDrawable);
- view.getOverlay().add(startDrawable);
+ ViewOverlay overlay = (mFadeBehavior == FADE_BEHAVIOR_REVEAL) ?
+ view.getOverlay() : ((ViewGroup) view.getParent()).getOverlay();
+ if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) {
+ overlay.add(endDrawable);
+ }
+ overlay.add(startDrawable);
return true;
} else {
return false;
@@ -107,6 +195,10 @@
view.invalidate(startDrawable.getBounds());
}
});
+ ObjectAnimator anim1 = null;
+ if (mFadeBehavior == FADE_BEHAVIOR_CROSSFADE) {
+ anim1 = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1);
+ }
if (Transition.DBG) {
Log.d(LOG_TAG, "Crossfade: created anim " + anim + " for start, end values " +
startValues + ", " + endValues);
@@ -114,23 +206,34 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- view.getOverlay().remove(startDrawable);
- view.getOverlay().remove(endDrawable);
+ ViewOverlay overlay = (mFadeBehavior == FADE_BEHAVIOR_REVEAL) ?
+ view.getOverlay() : ((ViewGroup) view.getParent()).getOverlay();
+ overlay.remove(startDrawable);
+ if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) {
+ overlay.remove(endDrawable);
+ }
}
});
AnimatorSet set = new AnimatorSet();
set.playTogether(anim);
- if (!startBounds.equals(endBounds)) {
+ if (anim1 != null) {
+ set.playTogether(anim1);
+ }
+ if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE && !startBounds.equals(endBounds)) {
if (Transition.DBG) {
Log.d(LOG_TAG, "animating from startBounds to endBounds: " +
startBounds + ", " + endBounds);
}
Animator anim2 = ObjectAnimator.ofObject(startDrawable, "bounds",
sRectEvaluator, startBounds, endBounds);
- Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds",
- sRectEvaluator, startBounds, endBounds);
set.playTogether(anim2);
- set.playTogether(anim3);
+ if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE) {
+ // TODO: How to handle resizing with a CROSSFADE (vs. REVEAL) effect
+ // when we are animating the view directly?
+ Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds",
+ sRectEvaluator, startBounds, endBounds);
+ set.playTogether(anim3);
+ }
}
return set;
}
@@ -138,8 +241,11 @@
@Override
protected void captureValues(TransitionValues values, boolean start) {
View view = values.view;
- values.values.put(PROPNAME_BOUNDS, new Rect(0, 0,
- view.getWidth(), view.getHeight()));
+ Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
+ if (mFadeBehavior == FADE_BEHAVIOR_CROSSFADE) {
+ bounds.offset(view.getLeft(), view.getTop());
+ }
+ values.values.put(PROPNAME_BOUNDS, bounds);
if (Transition.DBG) {
Log.d(LOG_TAG, "Captured bounds " + values.values.get(PROPNAME_BOUNDS) + ": start = " +
@@ -157,7 +263,7 @@
// TODO: I don't have resources, can't call the non-deprecated method?
BitmapDrawable drawable = new BitmapDrawable(bitmap);
// TODO: lrtb will be wrong if the view has transXY set
- drawable.setBounds(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+ drawable.setBounds(bounds);
values.values.put(PROPNAME_DRAWABLE, drawable);
}
diff --git a/core/java/android/view/transition/TransitionManager.java b/core/java/android/view/transition/TransitionManager.java
index 4971a92..8088f6b 100644
--- a/core/java/android/view/transition/TransitionManager.java
+++ b/core/java/android/view/transition/TransitionManager.java
@@ -19,6 +19,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import java.util.ArrayList;
+
/**
* This class manages the set of transitions that fire when there is a
* change of {@link Scene}. To use the manager, add scenes along with
@@ -41,8 +43,10 @@
new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
static ArrayMap<ViewGroup, Transition> sRunningTransitions =
new ArrayMap<ViewGroup, Transition>();
+ private static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<ViewGroup>();
- /**
+
+ /**
* Sets the transition to be used for any scene change for which no
* other transition is explicitly set. The initial value is
* an {@link AutoTransition} instance.
@@ -142,24 +146,15 @@
final ViewGroup sceneRoot = scene.getSceneRoot();
- Transition runningTransition = sRunningTransitions.get(sceneRoot);
- if (runningTransition != null) {
- runningTransition.cancelTransition();
- }
-
- // Capture current values
- if (transition != null) {
- transition.captureValues(sceneRoot, true);
- }
-
- // Notify previous scene that it is being exited
- Scene previousScene = sceneRoot.getCurrentScene();
- if (previousScene != null) {
- previousScene.exit();
- }
+ sceneChangeSetup(sceneRoot, transition);
scene.enter();
+ sceneChangeRunTransition(sceneRoot, transition);
+ }
+
+ private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
+ final Transition transition) {
if (transition != null) {
final ViewTreeObserver observer = sceneRoot.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@@ -181,6 +176,25 @@
}
}
+ private static void sceneChangeSetup(ViewGroup sceneRoot, Transition transition) {
+
+ Transition runningTransition = sRunningTransitions.get(sceneRoot);
+ if (runningTransition != null) {
+ runningTransition.cancelTransition();
+ }
+
+ // Capture current values
+ if (transition != null) {
+ transition.captureValues(sceneRoot, true);
+ }
+
+ // Notify previous scene that it is being exited
+ Scene previousScene = sceneRoot.getCurrentScene();
+ if (previousScene != null) {
+ previousScene.exit();
+ }
+ }
+
/**
* Change to the given scene, using the
* appropriate transition for this particular scene change
@@ -272,4 +286,47 @@
scene.setEnterAction(action);
changeScene(scene, transition);
}
+
+ /**
+ * Static utility method to animate to a new scene defined by all changes within
+ * the given scene root between calling this method and the next rendering frame.
+ * Calling this method causes TransitionManager to capture current values in the
+ * scene root and then post a request to run a transition on the next frame.
+ * At that time, the new values in the scene root will be captured and changes
+ * will be animated. There is no need to create a Scene; it is implied by
+ * changes which take place between calling this method and the next frame when
+ * the transition begins.
+ *
+ * <p>Calling this method several times before the next frame (for example, if
+ * unrelated code also wants to make dynamic changes and run a transition on
+ * the same scene root), only the first call will trigger capturing values
+ * and exiting the current scene. Subsequent calls to the method with the
+ * same scene root during the same frame will be ignored.</p>
+ *
+ * <p>Passing in <code>null</code> for the transition parameter will
+ * cause the TransitionManager to use its default transition.</p>
+ *
+ * @param sceneRoot The root of the View hierarchy to run the transition on.
+ * @param transition The transition to use for this change. A
+ * value of null causes the TransitionManager to use the default transition.
+ */
+ public static void beginDelayedTransition(final ViewGroup sceneRoot, Transition transition) {
+
+ if (!sPendingTransitions.contains(sceneRoot)) {
+ sPendingTransitions.add(sceneRoot);
+ if (transition == null) {
+ transition = sDefaultTransition;
+ }
+ final Transition finalTransition = transition;
+ sceneChangeSetup(sceneRoot, transition);
+ sceneRoot.setCurrentScene(null);
+ sceneRoot.postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ sPendingTransitions.remove(sceneRoot);
+ sceneChangeRunTransition(sceneRoot, finalTransition);
+ }
+ });
+ }
+ }
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index cc1309b..1991af1 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -25,11 +25,11 @@
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.os.Debug;
-import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.StrictMode;
import android.text.Editable;
+import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
@@ -61,9 +61,12 @@
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputConnectionWrapper;
import android.view.inputmethod.InputMethodManager;
import android.widget.RemoteViews.OnClickHandler;
@@ -5613,54 +5616,139 @@
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (isTextFilterEnabled()) {
- // XXX we need to have the text filter created, so we can get an
- // InputConnection to proxy to. Unfortunately this means we pretty
- // much need to make it as soon as a list view gets focus.
- createTextFilter(false);
if (mPublicInputConnection == null) {
mDefInputConnection = new BaseInputConnection(this, false);
- mPublicInputConnection = new InputConnectionWrapper(
- mTextFilter.onCreateInputConnection(outAttrs), true) {
- @Override
- public boolean reportFullscreenMode(boolean enabled) {
- // Use our own input connection, since it is
- // the "real" one the IME is talking with.
- return mDefInputConnection.reportFullscreenMode(enabled);
- }
-
- @Override
- public boolean performEditorAction(int editorAction) {
- // The editor is off in its own window; we need to be
- // the one that does this.
- if (editorAction == EditorInfo.IME_ACTION_DONE) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- if (imm != null) {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
- return true;
- }
- return false;
- }
-
- @Override
- public boolean sendKeyEvent(KeyEvent event) {
- // Use our own input connection, since the filter
- // text view may not be shown in a window so has
- // no ViewAncestor to dispatch events with.
- return mDefInputConnection.sendKeyEvent(event);
- }
- };
+ mPublicInputConnection = new InputConnectionWrapper(outAttrs);
}
- outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
- | EditorInfo.TYPE_TEXT_VARIATION_FILTER;
+ outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_FILTER;
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
return mPublicInputConnection;
}
return null;
}
+ private class InputConnectionWrapper implements InputConnection {
+ private final EditorInfo mOutAttrs;
+ private InputConnection mTarget;
+
+ public InputConnectionWrapper(EditorInfo outAttrs) {
+ mOutAttrs = outAttrs;
+ }
+
+ private InputConnection getTarget() {
+ if (mTarget == null) {
+ mTarget = getTextFilterInput().onCreateInputConnection(mOutAttrs);
+ }
+ return mTarget;
+ }
+
+ @Override
+ public boolean reportFullscreenMode(boolean enabled) {
+ // Use our own input connection, since it is
+ // the "real" one the IME is talking with.
+ return mDefInputConnection.reportFullscreenMode(enabled);
+ }
+
+ @Override
+ public boolean performEditorAction(int editorAction) {
+ // The editor is off in its own window; we need to be
+ // the one that does this.
+ if (editorAction == EditorInfo.IME_ACTION_DONE) {
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean sendKeyEvent(KeyEvent event) {
+ // Use our own input connection, since the filter
+ // text view may not be shown in a window so has
+ // no ViewAncestor to dispatch events with.
+ return mDefInputConnection.sendKeyEvent(event);
+ }
+
+ public CharSequence getTextBeforeCursor(int n, int flags) {
+ if (mTarget == null) return "";
+ return mTarget.getTextBeforeCursor(n, flags);
+ }
+
+ public CharSequence getTextAfterCursor(int n, int flags) {
+ if (mTarget == null) return "";
+ return mTarget.getTextAfterCursor(n, flags);
+ }
+
+ public CharSequence getSelectedText(int flags) {
+ if (mTarget == null) return "";
+ return mTarget.getSelectedText(flags);
+ }
+
+ public int getCursorCapsMode(int reqModes) {
+ if (mTarget == null) return InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
+ return mTarget.getCursorCapsMode(reqModes);
+ }
+
+ public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
+ return getTarget().getExtractedText(request, flags);
+ }
+
+ public boolean deleteSurroundingText(int beforeLength, int afterLength) {
+ return getTarget().deleteSurroundingText(beforeLength, afterLength);
+ }
+
+ public boolean setComposingText(CharSequence text, int newCursorPosition) {
+ return getTarget().setComposingText(text, newCursorPosition);
+ }
+
+ public boolean setComposingRegion(int start, int end) {
+ return getTarget().setComposingRegion(start, end);
+ }
+
+ public boolean finishComposingText() {
+ return mTarget == null || mTarget.finishComposingText();
+ }
+
+ public boolean commitText(CharSequence text, int newCursorPosition) {
+ return getTarget().commitText(text, newCursorPosition);
+ }
+
+ public boolean commitCompletion(CompletionInfo text) {
+ return getTarget().commitCompletion(text);
+ }
+
+ public boolean commitCorrection(CorrectionInfo correctionInfo) {
+ return getTarget().commitCorrection(correctionInfo);
+ }
+
+ public boolean setSelection(int start, int end) {
+ return getTarget().setSelection(start, end);
+ }
+
+ public boolean performContextMenuAction(int id) {
+ return getTarget().performContextMenuAction(id);
+ }
+
+ public boolean beginBatchEdit() {
+ return getTarget().beginBatchEdit();
+ }
+
+ public boolean endBatchEdit() {
+ return getTarget().endBatchEdit();
+ }
+
+ public boolean clearMetaKeyStates(int states) {
+ return getTarget().clearMetaKeyStates(states);
+ }
+
+ public boolean performPrivateCommand(String action, Bundle data) {
+ return getTarget().performPrivateCommand(action, data);
+ }
+ }
+
/**
* For filtering we proxy an input connection to an internal text editor,
* and this allows the proxying to happen.
@@ -5677,23 +5765,11 @@
*/
private void createTextFilter(boolean animateEntrance) {
if (mPopup == null) {
- Context c = getContext();
- PopupWindow p = new PopupWindow(c);
- LayoutInflater layoutInflater = (LayoutInflater)
- c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mTextFilter = (EditText) layoutInflater.inflate(
- com.android.internal.R.layout.typing_filter, null);
- // For some reason setting this as the "real" input type changes
- // the text view in some way that it doesn't work, and I don't
- // want to figure out why this is.
- mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
- | EditorInfo.TYPE_TEXT_VARIATION_FILTER);
- mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
- mTextFilter.addTextChangedListener(this);
+ PopupWindow p = new PopupWindow(getContext());
p.setFocusable(false);
p.setTouchable(false);
p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- p.setContentView(mTextFilter);
+ p.setContentView(getTextFilterInput());
p.setWidth(LayoutParams.WRAP_CONTENT);
p.setHeight(LayoutParams.WRAP_CONTENT);
p.setBackgroundDrawable(null);
@@ -5708,12 +5784,28 @@
}
}
+ private EditText getTextFilterInput() {
+ if (mTextFilter == null) {
+ final LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+ mTextFilter = (EditText) layoutInflater.inflate(
+ com.android.internal.R.layout.typing_filter, null);
+ // For some reason setting this as the "real" input type changes
+ // the text view in some way that it doesn't work, and I don't
+ // want to figure out why this is.
+ mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_VARIATION_FILTER);
+ mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ mTextFilter.addTextChangedListener(this);
+ }
+ return mTextFilter;
+ }
+
/**
* Clear the text filter.
*/
public void clearTextFilter() {
if (mFiltered) {
- mTextFilter.setText("");
+ getTextFilterInput().setText("");
mFiltered = false;
if (mPopup != null && mPopup.isShowing()) {
dismissPopup();
@@ -5759,7 +5851,8 @@
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (mPopup != null && isTextFilterEnabled()) {
+ if (isTextFilterEnabled()) {
+ createTextFilter(true);
int length = s.length();
boolean showing = mPopup.isShowing();
if (!showing && length > 0) {
@@ -6331,6 +6424,7 @@
}
mFirstActivePosition = firstActivePosition;
+ //noinspection MismatchedReadAndWriteOfArray
final View[] activeViews = mActiveViews;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -6425,7 +6519,7 @@
int viewType = lp.viewType;
final boolean scrapHasTransientState = scrap.hasTransientState();
if (!shouldRecycleViewType(viewType) || scrapHasTransientState) {
- if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER || scrapHasTransientState) {
+ if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER && scrapHasTransientState) {
if (mSkippedScrap == null) {
mSkippedScrap = new ArrayList<View>();
}
@@ -6499,7 +6593,7 @@
final boolean scrapHasTransientState = victim.hasTransientState();
if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) {
// Do not move views that should be ignored
- if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER ||
+ if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER &&
scrapHasTransientState) {
removeDetachedView(victim, false);
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 502de31..31ab0af 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -31,7 +31,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeProvider;
/**
* An AdapterView is a view whose children are determined by an {@link Adapter}.
@@ -1034,8 +1033,7 @@
checkSelectionChanged();
}
- //TODO: Hmm, we do not know the old state so this is sub-optimal
- notifyAccessibilityStateChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
void checkSelectionChanged() {
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index de8b80d..f1c3139 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -93,7 +93,7 @@
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
- notifyAccessibilityStateChanged();
+ notifyViewAccessibilityStateChangedIfNeeded();
}
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 452ad1b..c4406ac 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -114,7 +114,7 @@
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
- notifyAccessibilityStateChanged();
+ notifyViewAccessibilityStateChangedIfNeeded();
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 91c989d..50d28ab 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -499,6 +499,10 @@
* Create new SpellCheckSpans on the modified region.
*/
private void updateSpellCheckSpans(int start, int end, boolean createSpellChecker) {
+ // Remove spans whose adjacent characters are text not punctuation
+ mTextView.removeAdjacentSuggestionSpans(start);
+ mTextView.removeAdjacentSuggestionSpans(end);
+
if (mTextView.isTextEditable() && mTextView.isSuggestionsEnabled() &&
!(mTextView instanceof ExtractEditText)) {
if (mSpellChecker == null && createSpellChecker) {
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index ff0579c..55cfd27 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -595,12 +595,13 @@
final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+ // Calling overScrollBy will call onOverScrolled, which
+ // calls onScrollChanged if applicable.
if (overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
mOverscrollDistance, 0, true)) {
// Break our velocity if we hit a scroll barrier.
mVelocityTracker.clear();
}
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (canOverscroll) {
final int pulledToX = oldX + deltaX;
@@ -732,9 +733,12 @@
boolean clampedX, boolean clampedY) {
// Treat animating scrolls differently; see #computeScroll() for why.
if (!mScroller.isFinished()) {
+ final int oldX = mScrollX;
+ final int oldY = mScrollY;
mScrollX = scrollX;
mScrollY = scrollY;
invalidateParentIfNeeded();
+ onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (clampedX) {
mScroller.springBack(mScrollX, mScrollY, 0, getScrollRange(), 0, 0);
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index bc41931..0545d24 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -631,12 +631,13 @@
final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+ // Calling overScrollBy will call onOverScrolled, which
+ // calls onScrollChanged if applicable.
if (overScrollBy(0, deltaY, 0, mScrollY,
0, range, 0, mOverscrollDistance, true)) {
// Break our velocity if we hit a scroll barrier.
mVelocityTracker.clear();
}
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (canOverscroll) {
final int pulledToY = oldY + deltaY;
@@ -753,9 +754,12 @@
boolean clampedX, boolean clampedY) {
// Treat animating scrolls differently; see #computeScroll() for why.
if (!mScroller.isFinished()) {
+ final int oldX = mScrollX;
+ final int oldY = mScrollY;
mScrollX = scrollX;
mScrollY = scrollY;
invalidateParentIfNeeded();
+ onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (clampedY) {
mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange());
}
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 9e7f97e..b204dfd 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -753,4 +753,39 @@
}
}
}
+
+ public static boolean haveWordBoundariesChanged(final Editable editable, final int start,
+ final int end, final int spanStart, final int spanEnd) {
+ final boolean haveWordBoundariesChanged;
+ if (spanEnd != start && spanStart != end) {
+ haveWordBoundariesChanged = true;
+ if (DBG) {
+ Log.d(TAG, "(1) Text inside the span has been modified. Remove.");
+ }
+ } else if (spanEnd == start && start < editable.length()) {
+ final int codePoint = Character.codePointAt(editable, start);
+ haveWordBoundariesChanged = Character.isLetterOrDigit(codePoint);
+ if (DBG) {
+ Log.d(TAG, "(2) Characters have been appended to the spanned text. "
+ + (haveWordBoundariesChanged ? "Remove.<" : "Keep. <") + (char)(codePoint)
+ + ">, " + editable + ", " + editable.subSequence(spanStart, spanEnd) + ", "
+ + start);
+ }
+ } else if (spanStart == end && end > 0) {
+ final int codePoint = Character.codePointBefore(editable, end);
+ haveWordBoundariesChanged = Character.isLetterOrDigit(codePoint);
+ if (DBG) {
+ Log.d(TAG, "(3) Characters have been prepended to the spanned text. "
+ + (haveWordBoundariesChanged ? "Remove.<" : "Keep.<") + (char)(codePoint)
+ + ">, " + editable + ", " + editable.subSequence(spanStart, spanEnd) + ", "
+ + end);
+ }
+ } else {
+ if (DBG) {
+ Log.d(TAG, "(4) Characters adjacent to the spanned text were deleted. Keep.");
+ }
+ haveWordBoundariesChanged = false;
+ }
+ return haveWordBoundariesChanged;
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 12d0c49..816bb18 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1721,7 +1721,7 @@
setText(mText);
if (hasPasswordTransformationMethod()) {
- notifyAccessibilityStateChanged();
+ notifyViewAccessibilityStateChangedIfNeeded();
}
}
@@ -7318,7 +7318,6 @@
*/
protected void onSelectionChanged(int selStart, int selEnd) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
- notifyAccessibilityStateChanged();
}
/**
@@ -7363,27 +7362,42 @@
}
// The spans that are inside or intersect the modified region no longer make sense
- removeIntersectingSpans(start, start + before, SpellCheckSpan.class);
- removeIntersectingSpans(start, start + before, SuggestionSpan.class);
+ removeIntersectingNonAdjacentSpans(start, start + before, SpellCheckSpan.class);
+ removeIntersectingNonAdjacentSpans(start, start + before, SuggestionSpan.class);
}
// Removes all spans that are inside or actually overlap the start..end range
- private <T> void removeIntersectingSpans(int start, int end, Class<T> type) {
+ private <T> void removeIntersectingNonAdjacentSpans(int start, int end, Class<T> type) {
if (!(mText instanceof Editable)) return;
Editable text = (Editable) mText;
T[] spans = text.getSpans(start, end, type);
final int length = spans.length;
for (int i = 0; i < length; i++) {
- final int s = text.getSpanStart(spans[i]);
- final int e = text.getSpanEnd(spans[i]);
- // Spans that are adjacent to the edited region will be handled in
- // updateSpellCheckSpans. Result depends on what will be added (space or text)
- if (e == start || s == end) break;
+ final int spanStart = text.getSpanStart(spans[i]);
+ final int spanEnd = text.getSpanEnd(spans[i]);
+ if (spanEnd == start || spanStart == end) break;
text.removeSpan(spans[i]);
}
}
+ void removeAdjacentSuggestionSpans(final int pos) {
+ if (!(mText instanceof Editable)) return;
+ final Editable text = (Editable) mText;
+
+ final SuggestionSpan[] spans = text.getSpans(pos, pos, SuggestionSpan.class);
+ final int length = spans.length;
+ for (int i = 0; i < length; i++) {
+ final int spanStart = text.getSpanStart(spans[i]);
+ final int spanEnd = text.getSpanEnd(spans[i]);
+ if (spanEnd == pos || spanStart == pos) {
+ if (SpellChecker.haveWordBoundariesChanged(text, pos, pos, spanStart, spanEnd)) {
+ text.removeSpan(spans[i]);
+ }
+ }
+ }
+ }
+
/**
* Not private so it can be called from an inner class without going
* through a thunk.
@@ -8131,6 +8145,10 @@
info.setEditable(true);
}
+ if (mEditor != null) {
+ info.setInputType(mEditor.mInputType);
+ }
+
if (!TextUtils.isEmpty(mText)) {
info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
@@ -8163,7 +8181,6 @@
case AccessibilityNodeInfo.ACTION_COPY: {
if (isFocused() && canCopy()) {
if (onTextContextMenuItem(ID_COPY)) {
- notifyAccessibilityStateChanged();
return true;
}
}
@@ -8171,7 +8188,6 @@
case AccessibilityNodeInfo.ACTION_PASTE: {
if (isFocused() && canPaste()) {
if (onTextContextMenuItem(ID_PASTE)) {
- notifyAccessibilityStateChanged();
return true;
}
}
@@ -8179,7 +8195,6 @@
case AccessibilityNodeInfo.ACTION_CUT: {
if (isFocused() && canCut()) {
if (onTextContextMenuItem(ID_CUT)) {
- notifyAccessibilityStateChanged();
return true;
}
}
@@ -8198,7 +8213,6 @@
// No arguments clears the selection.
if (start == end && end == -1) {
Selection.removeSelection((Spannable) text);
- notifyAccessibilityStateChanged();
return true;
}
if (start >= 0 && start <= end && end <= text.length()) {
@@ -8207,7 +8221,6 @@
if (mEditor != null) {
mEditor.startSelectionActionMode();
}
- notifyAccessibilityStateChanged();
return true;
}
}
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e6796cb..e33c4d4 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -237,6 +237,7 @@
// update controls to initial state
updateHourControl();
+ updateMinuteControl();
updateAmPmControl();
setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
@@ -428,6 +429,7 @@
updateHourControl();
// set value after spinner range is updated
setCurrentHour(currentHour);
+ updateMinuteControl();
updateAmPmControl();
}
@@ -508,6 +510,14 @@
}
}
+ private void updateMinuteControl() {
+ if (is24HourView()) {
+ mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ } else {
+ mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+ }
+ }
+
private void updateAmPmControl() {
if (is24HourView()) {
if (mAmPmSpinner != null) {
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 823e19f..525517c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -71,6 +71,7 @@
void noteWifiMulticastEnabledFromSource(in WorkSource ws);
void noteWifiMulticastDisabledFromSource(in WorkSource ws);
void noteNetworkInterfaceType(String iface, int type);
+ void noteNetworkStatsEnabled();
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 38391df..38a8c19 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,7 +16,6 @@
package com.android.internal.os;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import android.bluetooth.BluetoothDevice;
@@ -46,6 +45,7 @@
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.JournaledFile;
import com.google.android.collect.Sets;
@@ -83,7 +83,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 65 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 66 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -231,6 +231,9 @@
final StopwatchTimer[] mPhoneDataConnectionsTimer =
new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
+ final LongSamplingCounter[] mNetworkActivityCounters =
+ new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
int mWifiOnUid = -1;
@@ -275,12 +278,6 @@
long mLastWriteTime = 0; // Milliseconds
- // Mobile data transferred while on battery
- private long[] mMobileDataTx = new long[4];
- private long[] mMobileDataRx = new long[4];
- private long[] mTotalDataTx = new long[4];
- private long[] mTotalDataRx = new long[4];
-
private long mRadioDataUptime;
private long mRadioDataStart;
@@ -337,9 +334,12 @@
private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+ private NetworkStats mLastSnapshot;
- /** Network ifaces that {@link ConnectivityManager} has claimed as mobile. */
+ @GuardedBy("this")
private HashSet<String> mMobileIfaces = Sets.newHashSet();
+ @GuardedBy("this")
+ private HashSet<String> mWifiIfaces = Sets.newHashSet();
// For debugging
public BatteryStatsImpl() {
@@ -466,7 +466,6 @@
}
public static class SamplingCounter extends Counter {
-
SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
super(unpluggables, in);
}
@@ -480,6 +479,93 @@
}
}
+ public static class LongSamplingCounter implements Unpluggable {
+ final ArrayList<Unpluggable> mUnpluggables;
+ long mCount;
+ long mLoadedCount;
+ long mLastCount;
+ long mUnpluggedCount;
+ long mPluggedCount;
+
+ LongSamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
+ mUnpluggables = unpluggables;
+ mPluggedCount = in.readLong();
+ mCount = mPluggedCount;
+ mLoadedCount = in.readLong();
+ mLastCount = 0;
+ mUnpluggedCount = in.readLong();
+ unpluggables.add(this);
+ }
+
+ LongSamplingCounter(ArrayList<Unpluggable> unpluggables) {
+ mUnpluggables = unpluggables;
+ unpluggables.add(this);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeLong(mCount);
+ out.writeLong(mLoadedCount);
+ out.writeLong(mUnpluggedCount);
+ }
+
+ @Override
+ public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ mUnpluggedCount = mPluggedCount;
+ mCount = mPluggedCount;
+ }
+
+ @Override
+ public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+ mPluggedCount = mCount;
+ }
+
+ public long getCountLocked(int which) {
+ long val;
+ if (which == STATS_LAST) {
+ val = mLastCount;
+ } else {
+ val = mCount;
+ if (which == STATS_SINCE_UNPLUGGED) {
+ val -= mUnpluggedCount;
+ } else if (which != STATS_SINCE_CHARGED) {
+ val -= mLoadedCount;
+ }
+ }
+
+ return val;
+ }
+
+ void addCountLocked(long count) {
+ mCount += count;
+ }
+
+ /**
+ * Clear state of this counter.
+ */
+ void reset(boolean detachIfReset) {
+ mCount = 0;
+ mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
+ if (detachIfReset) {
+ detach();
+ }
+ }
+
+ void detach() {
+ mUnpluggables.remove(this);
+ }
+
+ void writeSummaryFromParcelLocked(Parcel out) {
+ out.writeLong(mCount);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ mLoadedCount = in.readLong();
+ mCount = mLoadedCount;
+ mLastCount = 0;
+ mUnpluggedCount = mPluggedCount = mLoadedCount;
+ }
+ }
+
/**
* State for keeping track of timing information.
*/
@@ -1316,15 +1402,6 @@
return kwlt;
}
- private void doDataPlug(long[] dataTransfer, long currentBytes) {
- dataTransfer[STATS_LAST] = dataTransfer[STATS_SINCE_UNPLUGGED];
- dataTransfer[STATS_SINCE_UNPLUGGED] = -1;
- }
-
- private void doDataUnplug(long[] dataTransfer, long currentBytes) {
- dataTransfer[STATS_SINCE_UNPLUGGED] = currentBytes;
- }
-
/**
* Radio uptime in microseconds when transferring data. This value is very approximate.
* @return
@@ -1571,36 +1648,10 @@
}
public void doUnplugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
- NetworkStats.Entry entry = null;
-
- // Track UID data usage
- final NetworkStats uidStats = getNetworkStatsDetailGroupedByUid();
- final int size = uidStats.size();
- for (int i = 0; i < size; i++) {
- entry = uidStats.getValues(i, entry);
-
- final Uid u = mUidStats.get(entry.uid);
- if (u == null) continue;
-
- u.mStartedTcpBytesReceived = entry.rxBytes;
- u.mStartedTcpBytesSent = entry.txBytes;
- u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
- u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
- }
-
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track both mobile and total overall data
- final NetworkStats ifaceStats = getNetworkStatsSummary();
- entry = ifaceStats.getTotal(entry, mMobileIfaces);
- doDataUnplug(mMobileDataRx, entry.rxBytes);
- doDataUnplug(mMobileDataTx, entry.txBytes);
- entry = ifaceStats.getTotal(entry);
- doDataUnplug(mTotalDataRx, entry.rxBytes);
- doDataUnplug(mTotalDataTx, entry.txBytes);
-
// Track radio awake time
mRadioDataStart = getCurrentRadioDataUptime();
mRadioDataUptime = 0;
@@ -1611,32 +1662,10 @@
}
public void doPlugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
- NetworkStats.Entry entry = null;
-
- for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
- Uid u = mUidStats.valueAt(iu);
- if (u.mStartedTcpBytesReceived >= 0) {
- u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
- u.mStartedTcpBytesReceived = -1;
- }
- if (u.mStartedTcpBytesSent >= 0) {
- u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
- u.mStartedTcpBytesSent = -1;
- }
- }
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track both mobile and total overall data
- final NetworkStats ifaceStats = getNetworkStatsSummary();
- entry = ifaceStats.getTotal(entry, mMobileIfaces);
- doDataPlug(mMobileDataRx, entry.rxBytes);
- doDataPlug(mMobileDataTx, entry.txBytes);
- entry = ifaceStats.getTotal(entry);
- doDataPlug(mTotalDataRx, entry.rxBytes);
- doDataPlug(mTotalDataTx, entry.txBytes);
-
// Track radio awake time
mRadioDataUptime = getRadioDataUptime();
mRadioDataStart = -1;
@@ -2443,6 +2472,18 @@
} else {
mMobileIfaces.remove(iface);
}
+ if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
+ mWifiIfaces.add(iface);
+ } else {
+ mWifiIfaces.remove(iface);
+ }
+ }
+
+ public void noteNetworkStatsEnabledLocked() {
+ // During device boot, qtaguid isn't enabled until after the inital
+ // loading of battery stats. Now that they're enabled, take our initial
+ // snapshot for future delta calculation.
+ updateNetworkActivityLocked();
}
@Override public long getScreenOnTime(long batteryRealtime, int which) {
@@ -2501,6 +2542,15 @@
return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
+ @Override
+ public long getNetworkActivityCount(int type, int which) {
+ if (type >= 0 && type < mNetworkActivityCounters.length) {
+ return mNetworkActivityCounters[type].getCountLocked(which);
+ } else {
+ return 0;
+ }
+ }
+
@Override public boolean getIsOnBattery() {
return mOnBattery;
}
@@ -2515,17 +2565,6 @@
public final class Uid extends BatteryStats.Uid {
final int mUid;
- long mLoadedTcpBytesReceived;
- long mLoadedTcpBytesSent;
- long mCurrentTcpBytesReceived;
- long mCurrentTcpBytesSent;
- long mTcpBytesReceivedAtLastUnplug;
- long mTcpBytesSentAtLastUnplug;
-
- // These are not saved/restored when parcelling, since we want
- // to return from the parcel with a snapshot of the state.
- long mStartedTcpBytesReceived = -1;
- long mStartedTcpBytesSent = -1;
boolean mWifiRunning;
StopwatchTimer mWifiRunningTimer;
@@ -2551,6 +2590,8 @@
Counter[] mUserActivityCounters;
+ LongSamplingCounter[] mNetworkActivityCounters;
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -2614,43 +2655,6 @@
}
@Override
- public long getTcpBytesReceived(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesReceived;
- } else {
- long current = computeCurrentTcpBytesReceived();
- if (which == STATS_SINCE_UNPLUGGED) {
- current -= mTcpBytesReceivedAtLastUnplug;
- } else if (which == STATS_SINCE_CHARGED) {
- current += mLoadedTcpBytesReceived;
- }
- return current;
- }
- }
-
- public long computeCurrentTcpBytesReceived() {
- final long uidRxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
- null, mUid).rxBytes;
- return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
- ? (uidRxBytes - mStartedTcpBytesReceived) : 0);
- }
-
- @Override
- public long getTcpBytesSent(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesSent;
- } else {
- long current = computeCurrentTcpBytesSent();
- if (which == STATS_SINCE_UNPLUGGED) {
- current -= mTcpBytesSentAtLastUnplug;
- } else if (which == STATS_SINCE_CHARGED) {
- current += mLoadedTcpBytesSent;
- }
- return current;
- }
- }
-
- @Override
public void noteWifiRunningLocked() {
if (!mWifiRunning) {
mWifiRunning = true;
@@ -2913,11 +2917,38 @@
}
}
- public long computeCurrentTcpBytesSent() {
- final long uidTxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
- null, mUid).txBytes;
- return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
- ? (uidTxBytes - mStartedTcpBytesSent) : 0);
+ void noteNetworkActivityLocked(int type, long delta) {
+ if (mNetworkActivityCounters == null) {
+ initNetworkActivityLocked();
+ }
+ if (type >= 0 && type < NUM_NETWORK_ACTIVITY_TYPES) {
+ mNetworkActivityCounters[type].addCountLocked(delta);
+ } else {
+ Slog.w(TAG, "Unknown network activity type " + type + " was specified.",
+ new Throwable());
+ }
+ }
+
+ @Override
+ public boolean hasNetworkActivity() {
+ return mNetworkActivityCounters != null;
+ }
+
+ @Override
+ public long getNetworkActivityCount(int type, int which) {
+ if (mNetworkActivityCounters != null && type >= 0
+ && type < mNetworkActivityCounters.length) {
+ return mNetworkActivityCounters[type].getCountLocked(which);
+ } else {
+ return 0;
+ }
+ }
+
+ void initNetworkActivityLocked() {
+ mNetworkActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+ }
}
/**
@@ -2963,15 +2994,18 @@
}
}
- mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0;
- mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0;
-
if (mUserActivityCounters != null) {
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
mUserActivityCounters[i].reset(false);
}
}
+ if (mNetworkActivityCounters != null) {
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].reset(false);
+ }
+ }
+
if (mWakelockStats.size() > 0) {
Iterator<Map.Entry<String, Wakelock>> it = mWakelockStats.entrySet().iterator();
while (it.hasNext()) {
@@ -3062,6 +3096,11 @@
mUserActivityCounters[i].detach();
}
}
+ if (mNetworkActivityCounters != null) {
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].detach();
+ }
+ }
}
return !active;
@@ -3096,12 +3135,6 @@
pkg.writeToParcelLocked(out);
}
- out.writeLong(mLoadedTcpBytesReceived);
- out.writeLong(mLoadedTcpBytesSent);
- out.writeLong(computeCurrentTcpBytesReceived());
- out.writeLong(computeCurrentTcpBytesSent());
- out.writeLong(mTcpBytesReceivedAtLastUnplug);
- out.writeLong(mTcpBytesSentAtLastUnplug);
if (mWifiRunningTimer != null) {
out.writeInt(1);
mWifiRunningTimer.writeToParcel(out, batteryRealtime);
@@ -3158,6 +3191,14 @@
} else {
out.writeInt(0);
}
+ if (mNetworkActivityCounters != null) {
+ out.writeInt(1);
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeToParcel(out);
+ }
+ } else {
+ out.writeInt(0);
+ }
}
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -3200,12 +3241,6 @@
mPackageStats.put(packageName, pkg);
}
- mLoadedTcpBytesReceived = in.readLong();
- mLoadedTcpBytesSent = in.readLong();
- mCurrentTcpBytesReceived = in.readLong();
- mCurrentTcpBytesSent = in.readLong();
- mTcpBytesReceivedAtLastUnplug = in.readLong();
- mTcpBytesSentAtLastUnplug = in.readLong();
mWifiRunning = false;
if (in.readInt() != 0) {
mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
@@ -3268,6 +3303,14 @@
} else {
mUserActivityCounters = null;
}
+ if (in.readInt() != 0) {
+ mNetworkActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
+ }
+ } else {
+ mNetworkActivityCounters = null;
+ }
}
/**
@@ -4342,6 +4385,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+ }
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
@@ -4517,6 +4563,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].reset(this, false);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].reset(false);
+ }
mWifiOnTimer.reset(this, false);
mGlobalWifiRunningTimer.reset(this, false);
mBluetoothOnTimer.reset(this, false);
@@ -4592,6 +4641,7 @@
mDischargeStartLevel = level;
}
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
@@ -4614,6 +4664,7 @@
doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
} else {
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
@@ -4746,6 +4797,52 @@
}
}
+ private void updateNetworkActivityLocked() {
+ if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
+
+ final NetworkStats snapshot;
+ try {
+ snapshot = mNetworkStatsFactory.readNetworkStatsDetail();
+ } catch (IOException e) {
+ Log.wtf(TAG, "Failed to read network stats", e);
+ return;
+ }
+
+ if (mLastSnapshot == null) {
+ mLastSnapshot = snapshot;
+ return;
+ }
+
+ final NetworkStats delta = snapshot.subtract(mLastSnapshot);
+ mLastSnapshot = snapshot;
+
+ NetworkStats.Entry entry = null;
+ final int size = delta.size();
+ for (int i = 0; i < size; i++) {
+ entry = delta.getValues(i, entry);
+
+ if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
+ if (entry.tag != NetworkStats.TAG_NONE) continue;
+
+ final Uid u = getUidStatsLocked(entry.uid);
+
+ if (mMobileIfaces.contains(entry.iface)) {
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_BYTES, entry.rxBytes);
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_BYTES, entry.txBytes);
+
+ mNetworkActivityCounters[NETWORK_MOBILE_RX_BYTES].addCountLocked(entry.rxBytes);
+ mNetworkActivityCounters[NETWORK_MOBILE_TX_BYTES].addCountLocked(entry.txBytes);
+
+ } else if (mWifiIfaces.contains(entry.iface)) {
+ u.noteNetworkActivityLocked(NETWORK_WIFI_RX_BYTES, entry.rxBytes);
+ u.noteNetworkActivityLocked(NETWORK_WIFI_TX_BYTES, entry.txBytes);
+
+ mNetworkActivityCounters[NETWORK_WIFI_RX_BYTES].addCountLocked(entry.rxBytes);
+ mNetworkActivityCounters[NETWORK_WIFI_TX_BYTES].addCountLocked(entry.txBytes);
+ }
+ }
+ }
+
public long getAwakeTimeBattery() {
return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
}
@@ -4836,47 +4933,6 @@
return getBatteryRealtimeLocked(curTime);
}
- private long getTcpBytes(long current, long[] dataBytes, int which) {
- if (which == STATS_LAST) {
- return dataBytes[STATS_LAST];
- } else {
- if (which == STATS_SINCE_UNPLUGGED) {
- if (dataBytes[STATS_SINCE_UNPLUGGED] < 0) {
- return dataBytes[STATS_LAST];
- } else {
- return current - dataBytes[STATS_SINCE_UNPLUGGED];
- }
- } else if (which == STATS_SINCE_CHARGED) {
- return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_SINCE_CHARGED];
- }
- return current - dataBytes[STATS_CURRENT];
- }
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getMobileTcpBytesSent(int which) {
- final long mobileTxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).txBytes;
- return getTcpBytes(mobileTxBytes, mMobileDataTx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getMobileTcpBytesReceived(int which) {
- final long mobileRxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).rxBytes;
- return getTcpBytes(mobileRxBytes, mMobileDataRx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getTotalTcpBytesSent(int which) {
- final long totalTxBytes = getNetworkStatsSummary().getTotal(null).txBytes;
- return getTcpBytes(totalTxBytes, mTotalDataTx, which);
- }
-
- /** Only STATS_UNPLUGGED works properly */
- public long getTotalTcpBytesReceived(int which) {
- final long totalRxBytes = getNetworkStatsSummary().getTotal(null).rxBytes;
- return getTcpBytes(totalRxBytes, mTotalDataRx, which);
- }
-
@Override
public int getDischargeStartLevel() {
synchronized(this) {
@@ -5356,6 +5412,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].readSummaryFromParcelLocked(in);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
mWifiOn = false;
mWifiOnTimer.readSummaryFromParcelLocked(in);
mGlobalWifiRunning = false;
@@ -5427,6 +5486,15 @@
}
}
+ if (in.readInt() != 0) {
+ if (u.mNetworkActivityCounters == null) {
+ u.initNetworkActivityLocked();
+ }
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ u.mNetworkActivityCounters[i].readSummaryFromParcelLocked(in);
+ }
+ }
+
int NW = in.readInt();
if (NW > 100) {
Slog.w(TAG, "File corrupt: too many wake locks " + NW);
@@ -5509,9 +5577,6 @@
s.mLaunches = s.mLoadedLaunches = in.readInt();
}
}
-
- u.mLoadedTcpBytesReceived = in.readLong();
- u.mLoadedTcpBytesSent = in.readLong();
}
}
@@ -5524,6 +5589,7 @@
public void writeSummaryToParcel(Parcel out) {
// Need to update with current kernel wake lock counts.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
@@ -5559,6 +5625,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
@@ -5640,6 +5709,15 @@
}
}
+ if (u.mNetworkActivityCounters == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ u.mNetworkActivityCounters[i].writeSummaryFromParcelLocked(out);
+ }
+ }
+
int NW = u.mWakelockStats.size();
out.writeInt(NW);
if (NW > 0) {
@@ -5732,9 +5810,6 @@
}
}
}
-
- out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED));
- out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED));
}
}
@@ -5773,6 +5848,9 @@
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
null, mUnpluggables, in);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
+ }
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mGlobalWifiRunning = false;
@@ -5803,15 +5881,6 @@
mDischargeAmountScreenOffSinceCharge = in.readInt();
mLastWriteTime = in.readLong();
- mMobileDataRx[STATS_LAST] = in.readLong();
- mMobileDataRx[STATS_SINCE_UNPLUGGED] = -1;
- mMobileDataTx[STATS_LAST] = in.readLong();
- mMobileDataTx[STATS_SINCE_UNPLUGGED] = -1;
- mTotalDataRx[STATS_LAST] = in.readLong();
- mTotalDataRx[STATS_SINCE_UNPLUGGED] = -1;
- mTotalDataTx[STATS_LAST] = in.readLong();
- mTotalDataTx[STATS_SINCE_UNPLUGGED] = -1;
-
mRadioDataUptime = in.readLong();
mRadioDataStart = -1;
@@ -5861,6 +5930,7 @@
void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
// Need to update with current kernel wake lock counts.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
final long uSecUptime = SystemClock.uptimeMillis() * 1000;
final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
@@ -5887,6 +5957,9 @@
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
}
+ for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+ mNetworkActivityCounters[i].writeToParcel(out);
+ }
mWifiOnTimer.writeToParcel(out, batteryRealtime);
mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
@@ -5911,11 +5984,6 @@
out.writeInt(mDischargeAmountScreenOffSinceCharge);
out.writeLong(mLastWriteTime);
- out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED));
- out.writeLong(getMobileTcpBytesSent(STATS_SINCE_UNPLUGGED));
- out.writeLong(getTotalTcpBytesReceived(STATS_SINCE_UNPLUGGED));
- out.writeLong(getTotalTcpBytesSent(STATS_SINCE_UNPLUGGED));
-
// Write radio uptime for data
out.writeLong(getRadioDataUptime());
@@ -5967,6 +6035,7 @@
public void prepareForDumpLocked() {
// Need to retrieve current kernel wake lock stats before printing.
updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
}
public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly) {
@@ -5998,59 +6067,7 @@
mGlobalWifiRunningTimer.logState(pr, " ");
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
- pr.println("*** Mobile ifaces:");
- pr.println(mMobileIfaces.toString());
}
super.dumpLocked(pw, isUnpluggedOnly);
}
-
- private NetworkStats mNetworkSummaryCache;
- private NetworkStats mNetworkDetailCache;
-
- private NetworkStats getNetworkStatsSummary() {
- // NOTE: calls from BatteryStatsService already hold this lock
- synchronized (this) {
- if (mNetworkSummaryCache == null
- || mNetworkSummaryCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
- mNetworkSummaryCache = null;
-
- if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
- try {
- mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummaryDev();
- } catch (IOException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- }
- }
-
- if (mNetworkSummaryCache == null) {
- mNetworkSummaryCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
- }
- return mNetworkSummaryCache;
- }
- }
-
- private NetworkStats getNetworkStatsDetailGroupedByUid() {
- // NOTE: calls from BatteryStatsService already hold this lock
- synchronized (this) {
- if (mNetworkDetailCache == null
- || mNetworkDetailCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
- mNetworkDetailCache = null;
-
- if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
- try {
- mNetworkDetailCache = mNetworkStatsFactory
- .readNetworkStatsDetail().groupedByUid();
- } catch (IOException e) {
- Log.wtf(TAG, "problem reading network stats", e);
- }
- }
-
- if (mNetworkDetailCache == null) {
- mNetworkDetailCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
- }
- return mNetworkDetailCache;
- }
- }
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index d6549a1..a7a9266 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -29,6 +29,10 @@
jfieldID gOptions_purgeableFieldID;
jfieldID gOptions_shareableFieldID;
jfieldID gOptions_preferQualityOverSpeedFieldID;
+jfieldID gOptions_scaledFieldID;
+jfieldID gOptions_densityFieldID;
+jfieldID gOptions_screenDensityFieldID;
+jfieldID gOptions_targetDensityFieldID;
jfieldID gOptions_widthFieldID;
jfieldID gOptions_heightFieldID;
jfieldID gOptions_mimeFieldID;
@@ -152,12 +156,75 @@
return pr;
}
+static SkBitmap::Config configForScaledOutput(SkBitmap::Config config) {
+ switch (config) {
+ case SkBitmap::kNo_Config:
+ case SkBitmap::kIndex8_Config:
+ case SkBitmap::kRLE_Index8_Config:
+ return SkBitmap::kARGB_8888_Config;
+ default:
+ break;
+ }
+ return config;
+}
+
+class ScaleCheckingAllocator : public SkBitmap::HeapAllocator {
+public:
+ ScaleCheckingAllocator(float scale, int size)
+ : mScale(scale), mSize(size) {
+ }
+
+ virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
+ // accounts for scale in final allocation, using eventual size and config
+ const int bytesPerPixel = SkBitmap::ComputeBytesPerPixel(
+ configForScaledOutput(bitmap->getConfig()));
+ const int requestedSize = bytesPerPixel *
+ int(bitmap->width() * mScale + 0.5f) *
+ int(bitmap->height() * mScale + 0.5f);
+ if (requestedSize > mSize) {
+ ALOGW("bitmap for alloc reuse (%d bytes) can't fit scaled bitmap (%d bytes)",
+ mSize, requestedSize);
+ return false;
+ }
+ return SkBitmap::HeapAllocator::allocPixelRef(bitmap, ctable);
+ }
+private:
+ const float mScale;
+ const int mSize;
+};
+
+class RecyclingPixelAllocator : public SkBitmap::Allocator {
+public:
+ RecyclingPixelAllocator(SkPixelRef* pixelRef, unsigned int size)
+ : mPixelRef(pixelRef), mSize(size) {
+ SkSafeRef(mPixelRef);
+ }
+
+ ~RecyclingPixelAllocator() {
+ SkSafeUnref(mPixelRef);
+ }
+
+ virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
+ if (!bitmap->getSize64().is32() || bitmap->getSize() > mSize) {
+ ALOGW("bitmap marked for reuse (%d bytes) can't fit new bitmap (%d bytes)",
+ mSize, bitmap->getSize());
+ return false;
+ }
+ bitmap->setPixelRef(mPixelRef);
+ bitmap->lockPixels();
+ return true;
+ }
+
+private:
+ SkPixelRef* const mPixelRef;
+ const unsigned int mSize;
+};
+
// since we "may" create a purgeable imageref, we require the stream be ref'able
// i.e. dynamically allocated, since its lifetime may exceed the current stack
// frame.
static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
- jobject options, bool allowPurgeable, bool forcePurgeable = false,
- bool applyScale = false, float scale = 1.0f) {
+ jobject options, bool allowPurgeable, bool forcePurgeable = false) {
int sampleSize = 1;
@@ -166,9 +233,8 @@
bool doDither = true;
bool isMutable = false;
- bool willScale = applyScale && scale != 1.0f;
- bool isPurgeable = !willScale &&
- (forcePurgeable || (allowPurgeable && optionsPurgeable(env, options)));
+ float scale = 1.0f;
+ bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options));
bool preferQualityOverSpeed = false;
jobject javaBitmap = NULL;
@@ -191,11 +257,19 @@
preferQualityOverSpeed = env->GetBooleanField(options,
gOptions_preferQualityOverSpeedFieldID);
javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
+
+ if (env->GetBooleanField(options, gOptions_scaledFieldID)) {
+ const int density = env->GetIntField(options, gOptions_densityFieldID);
+ const int targetDensity = env->GetIntField(options, gOptions_targetDensityFieldID);
+ const int screenDensity = env->GetIntField(options, gOptions_screenDensityFieldID);
+ if (density != 0 && targetDensity != 0 && density != screenDensity) {
+ scale = (float) targetDensity / density;
+ }
+ }
}
- if (willScale && javaBitmap != NULL) {
- return nullObjectReturn("Cannot pre-scale a reused bitmap");
- }
+ const bool willScale = scale != 1.0f;
+ isPurgeable &= !willScale;
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
if (decoder == NULL) {
@@ -206,35 +280,26 @@
decoder->setDitherImage(doDither);
decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
- NinePatchPeeker peeker(decoder);
- JavaPixelAllocator javaAllocator(env);
-
- SkBitmap* bitmap;
- bool useExistingBitmap = false;
+ SkBitmap* outputBitmap = NULL;
unsigned int existingBufferSize = 0;
- if (javaBitmap == NULL) {
- bitmap = new SkBitmap;
- } else {
- bitmap = (SkBitmap*) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
- // only reuse the provided bitmap if it is mutable
- if (!bitmap->isImmutable()) {
- useExistingBitmap = true;
- // config of supplied bitmap overrules config set in options
- prefConfig = bitmap->getConfig();
- existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap);
- } else {
+ if (javaBitmap != NULL) {
+ outputBitmap = (SkBitmap*) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
+ if (outputBitmap->isImmutable()) {
ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
- bitmap = new SkBitmap;
+ javaBitmap = NULL;
+ outputBitmap = NULL;
+ } else {
+ existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap);
}
}
- SkAutoTDelete<SkImageDecoder> add(decoder);
- SkAutoTDelete<SkBitmap> adb(!useExistingBitmap ? bitmap : NULL);
+ SkAutoTDelete<SkBitmap> adb(outputBitmap == NULL ? new SkBitmap : NULL);
+ if (outputBitmap == NULL) outputBitmap = adb.get();
+ SkAutoTDelete<SkImageDecoder> add(decoder);
+
+ NinePatchPeeker peeker(decoder);
decoder->setPeeker(&peeker);
- if (!isPurgeable) {
- decoder->setAllocator(&javaAllocator);
- }
AutoDecoderCancel adc(options, decoder);
@@ -245,45 +310,31 @@
return nullObjectReturn("gOptions_mCancelID");
}
- SkImageDecoder::Mode decodeMode = mode;
- if (isPurgeable) {
- decodeMode = SkImageDecoder::kDecodeBounds_Mode;
- }
+ SkImageDecoder::Mode decodeMode = isPurgeable ? SkImageDecoder::kDecodeBounds_Mode : mode;
- if (javaBitmap != NULL) {
- // If we're reusing the pixelref from an existing bitmap, decode the bounds and
- // reinitialize the native object for the new content, keeping the pixelRef
- SkPixelRef* pixelRef = bitmap->pixelRef();
- SkSafeRef(pixelRef);
- SkBitmap boundsBitmap;
- decoder->decode(stream, &boundsBitmap, prefConfig, SkImageDecoder::kDecodeBounds_Mode);
- stream->rewind();
-
- if (boundsBitmap.getSize() > existingBufferSize) {
- return nullObjectReturn("bitmap marked for reuse too small to contain decoded data");
+ JavaPixelAllocator javaAllocator(env);
+ RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
+ ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
+ SkBitmap::Allocator* outputAllocator = (javaBitmap != NULL) ?
+ (SkBitmap::Allocator*)&recyclingAllocator : (SkBitmap::Allocator*)&javaAllocator;
+ if (decodeMode != SkImageDecoder::kDecodeBounds_Mode) {
+ if (!willScale) {
+ decoder->setAllocator(outputAllocator);
+ } else if (javaBitmap != NULL) {
+ // check for eventual scaled bounds at allocation time, so we don't decode the bitmap
+ // only to find the scaled result too large to fit in the allocation
+ decoder->setAllocator(&scaleCheckingAllocator);
}
-
- bitmap->setConfig(boundsBitmap.config(), boundsBitmap.width(), boundsBitmap.height(), 0);
- bitmap->setPixelRef(pixelRef);
- SkSafeUnref(pixelRef);
- GraphicsJNI::reinitBitmap(env, javaBitmap);
}
- SkBitmap* decoded;
- if (willScale) {
- decoded = new SkBitmap;
- } else {
- decoded = bitmap;
- }
- SkAutoTDelete<SkBitmap> adb2(willScale ? decoded : NULL);
-
- if (!decoder->decode(stream, decoded, prefConfig, decodeMode, javaBitmap != NULL)) {
+ SkBitmap decodingBitmap;
+ if (!decoder->decode(stream, &decodingBitmap, prefConfig, decodeMode)) {
return nullObjectReturn("decoder->decode returned false");
}
- int scaledWidth = decoded->width();
- int scaledHeight = decoded->height();
+ int scaledWidth = decodingBitmap.width();
+ int scaledHeight = decodingBitmap.height();
if (willScale && mode != SkImageDecoder::kDecodeBounds_Mode) {
scaledWidth = int(scaledWidth * scale + 0.5f);
@@ -351,33 +402,26 @@
// Dalvik code has always behaved. We simply recreate the behavior here.
// The result is slightly different from simply using scale because of
// the 0.5f rounding bias applied when computing the target image size
- const float sx = scaledWidth / float(decoded->width());
- const float sy = scaledHeight / float(decoded->height());
+ const float sx = scaledWidth / float(decodingBitmap.width());
+ const float sy = scaledHeight / float(decodingBitmap.height());
- SkBitmap::Config config = decoded->config();
- switch (config) {
- case SkBitmap::kNo_Config:
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kRLE_Index8_Config:
- config = SkBitmap::kARGB_8888_Config;
- break;
- default:
- break;
- }
-
- bitmap->setConfig(config, scaledWidth, scaledHeight);
- bitmap->setIsOpaque(decoded->isOpaque());
- if (!bitmap->allocPixels(&javaAllocator, NULL)) {
+ // TODO: avoid copying when scaled size equals decodingBitmap size
+ SkBitmap::Config config = configForScaledOutput(decodingBitmap.config());
+ outputBitmap->setConfig(config, scaledWidth, scaledHeight);
+ outputBitmap->setIsOpaque(decodingBitmap.isOpaque());
+ if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
}
- bitmap->eraseColor(0);
+ outputBitmap->eraseColor(0);
SkPaint paint;
paint.setFilterBitmap(true);
- SkCanvas canvas(*bitmap);
+ SkCanvas canvas(*outputBitmap);
canvas.scale(sx, sy);
- canvas.drawBitmap(*decoded, 0.0f, 0.0f, &paint);
+ canvas.drawBitmap(decodingBitmap, 0.0f, 0.0f, &paint);
+ } else {
+ outputBitmap->swap(decodingBitmap);
}
if (padding) {
@@ -392,17 +436,17 @@
SkPixelRef* pr;
if (isPurgeable) {
- pr = installPixelRef(bitmap, stream, sampleSize, doDither);
+ pr = installPixelRef(outputBitmap, stream, sampleSize, doDither);
} else {
// if we get here, we're in kDecodePixels_Mode and will therefore
// already have a pixelref installed.
- pr = bitmap->pixelRef();
+ pr = outputBitmap->pixelRef();
}
if (pr == NULL) {
return nullObjectReturn("Got null SkPixelRef");
}
- if (!isMutable && !useExistingBitmap) {
+ if (!isMutable && javaBitmap == NULL) {
// promise we will never change our pixels (great for sharing and pictures)
pr->setImmutable();
}
@@ -410,35 +454,31 @@
// detach bitmap from its autodeleter, since we want to own it now
adb.detach();
- if (useExistingBitmap) {
+ if (javaBitmap != NULL) {
+ GraphicsJNI::reinitBitmap(env, javaBitmap);
+ outputBitmap->notifyPixelsChanged();
// If a java bitmap was passed in for reuse, pass it back
return javaBitmap;
}
// now create the java bitmap
- return GraphicsJNI::createBitmap(env, bitmap, javaAllocator.getStorageObj(),
+ return GraphicsJNI::createBitmap(env, outputBitmap, javaAllocator.getStorageObj(),
isMutable, ninePatchChunk, layoutBounds, -1);
}
-static jobject nativeDecodeStreamScaled(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
- jobject padding, jobject options, jboolean applyScale, jfloat scale) {
+static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
+ jobject padding, jobject options) {
jobject bitmap = NULL;
SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0);
if (stream) {
// for now we don't allow purgeable with java inputstreams
- bitmap = doDecode(env, stream, padding, options, false, false, applyScale, scale);
+ bitmap = doDecode(env, stream, padding, options, false, false);
stream->unref();
}
return bitmap;
}
-static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
- jobject padding, jobject options) {
-
- return nativeDecodeStreamScaled(env, clazz, is, storage, padding, options, false, 1.0f);
-}
-
static ssize_t getFDSize(int fd) {
off64_t curr = ::lseek64(fd, 0, SEEK_CUR);
if (curr < 0) {
@@ -513,8 +553,8 @@
return stream;
}
-static jobject nativeDecodeAssetScaled(JNIEnv* env, jobject clazz, jint native_asset,
- jobject padding, jobject options, jboolean applyScale, jfloat scale) {
+static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
+ jobject padding, jobject options) {
SkStream* stream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
@@ -532,13 +572,7 @@
stream = new AssetStreamAdaptor(asset);
}
SkAutoUnref aur(stream);
- return doDecode(env, stream, padding, options, true, forcePurgeable, applyScale, scale);
-}
-
-static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
- jobject padding, jobject options) {
-
- return nativeDecodeAssetScaled(env, clazz, native_asset, padding, options, false, 1.0f);
+ return doDecode(env, stream, padding, options, true, forcePurgeable);
}
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
@@ -572,10 +606,6 @@
"(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeStream
},
- { "nativeDecodeStream",
- "(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;ZF)Landroid/graphics/Bitmap;",
- (void*)nativeDecodeStreamScaled
- },
{ "nativeDecodeFileDescriptor",
"(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
@@ -587,11 +617,6 @@
(void*)nativeDecodeAsset
},
- { "nativeDecodeAsset",
- "(ILandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;ZF)Landroid/graphics/Bitmap;",
- (void*)nativeDecodeAssetScaled
- },
-
{ "nativeDecodeByteArray",
"([BIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeByteArray
@@ -634,6 +659,10 @@
gOptions_shareableFieldID = getFieldIDCheck(env, options_class, "inInputShareable", "Z");
gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, options_class,
"inPreferQualityOverSpeed", "Z");
+ gOptions_scaledFieldID = getFieldIDCheck(env, options_class, "inScaled", "Z");
+ gOptions_densityFieldID = getFieldIDCheck(env, options_class, "inDensity", "I");
+ gOptions_screenDensityFieldID = getFieldIDCheck(env, options_class, "inScreenDensity", "I");
+ gOptions_targetDensityFieldID = getFieldIDCheck(env, options_class, "inTargetDensity", "I");
gOptions_widthFieldID = getFieldIDCheck(env, options_class, "outWidth", "I");
gOptions_heightFieldID = getFieldIDCheck(env, options_class, "outHeight", "I");
gOptions_mimeFieldID = getFieldIDCheck(env, options_class, "outMimeType", "Ljava/lang/String;");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6918099..1643522 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -216,7 +216,8 @@
android:description="@string/permdesc_sendSms" />
<!-- Allows an application (Phone) to send a request to other applications
- to handle the respond-via-message action during incoming calls. -->
+ to handle the respond-via-message action during incoming calls.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:permissionGroup="android.permission-group.MESSAGES"
android:protectionLevel="signature|system"
@@ -240,7 +241,8 @@
android:description="@string/permdesc_receiveMms" />
<!-- Allows an application to receive emergency cell broadcast messages,
- to record or display them to the user. Reserved for system apps.
+ to record or display them to the user.
+ <p>Not for use by third-party applications.
@hide Pending API council approval -->
<permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
android:permissionGroup="android.permission-group.MESSAGES"
@@ -319,7 +321,8 @@
android:description="@string/permdesc_writeContacts" />
<!-- Allows an application to execute contacts directory search.
- This should only be used by ContactsProvider. -->
+ This should only be used by ContactsProvider.
+ <p>Not for use by third-party applications. -->
<!-- @hide -->
<permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
@@ -598,15 +601,16 @@
android:label="@string/permlab_accessLocationExtraCommands"
android:description="@string/permdesc_accessLocationExtraCommands" />
- <!-- Allows an application to install a location provider into the Location Manager -->
+ <!-- Allows an application to install a location provider into the Location Manager.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
android:protectionLevel="signature|system"
android:label="@string/permlab_installLocationProvider"
android:description="@string/permdesc_installLocationProvider" />
<!-- Allows an application to use location features in hardware,
- such as the geofencing api
- Protected by signature|system protection level -->
+ such as the geofencing api.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.LOCATION_HARDWARE"
android:permissionGroup="android.permission-group.LOCATION"
android:protectionLevel="signature|system" />
@@ -769,8 +773,8 @@
android:label="@string/permlab_manageAccounts"
android:description="@string/permdesc_manageAccounts" />
- <!-- Allows applications to call into AccountAuthenticators. Only
- the system can get this permission. -->
+ <!-- Allows applications to call into AccountAuthenticators.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCOUNT_MANAGER"
android:permissionGroup="android.permission-group.ACCOUNTS"
android:protectionLevel="signature"
@@ -870,7 +874,8 @@
android:label="@string/permlab_accessMtp"
android:description="@string/permdesc_accessMtp" />
- <!-- Allows access to hardware peripherals. Intended only for hardware testing -->
+ <!-- Allows access to hardware peripherals. Intended only for hardware testing.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.HARDWARE_TEST"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
android:protectionLevel="signature"
@@ -971,7 +976,8 @@
android:description="@string/permdesc_processOutgoingCalls" />
<!-- Allows modification of the telephony state - power on, mmi, etc.
- Does not include placing calls. -->
+ Does not include placing calls.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.MODIFY_PHONE_STATE"
android:permissionGroup="android.permission-group.PHONE_CALLS"
android:protectionLevel="signature|system"
@@ -1265,7 +1271,8 @@
android:description="@string/permgroupdesc_systemClock"
android:priority="140" />
- <!-- Allows applications to set the system time -->
+ <!-- Allows applications to set the system time.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_TIME"
android:protectionLevel="signature|system"
android:label="@string/permlab_setTime"
@@ -1378,7 +1385,8 @@
android:label="@string/permlab_writeSettings"
android:description="@string/permdesc_writeSettings" />
- <!-- Allows an application to modify the Google service map. -->
+ <!-- Allows an application to modify the Google service map.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_GSERVICES"
android:protectionLevel="signature|system"
android:label="@string/permlab_writeGservices"
@@ -1401,7 +1409,8 @@
android:label="@string/permlab_retrieve_window_content"
android:description="@string/permdesc_retrieve_window_content" />
- <!-- Modify the global animation scaling factor. -->
+ <!-- Modify the global animation scaling factor.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ANIMATION_SCALE"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature|system|development"
@@ -1459,14 +1468,16 @@
android:label="@string/permlab_broadcastSticky"
android:description="@string/permdesc_broadcastSticky" />
- <!-- Allows mounting and unmounting file systems for removable storage. -->
+ <!-- Allows mounting and unmounting file systems for removable storage.
+ <p>Not for use by third-party applications.-->
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="system|signature"
android:label="@string/permlab_mount_unmount_filesystems"
android:description="@string/permdesc_mount_unmount_filesystems" />
- <!-- Allows formatting file systems for removable storage. -->
+ <!-- Allows formatting file systems for removable storage.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="system|signature"
@@ -1513,7 +1524,8 @@
android:label="@string/permlab_asec_rename"
android:description="@string/permdesc_asec_rename" />
- <!-- Allows applications to write the apn settings -->
+ <!-- Allows applications to write the apn settings.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_APN_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature|system"
@@ -1561,7 +1573,7 @@
<eat-comment />
<!-- Group of permissions that are related to development features. These
- are not permissions that should appear in normal applications; they
+ are not permissions that should appear in third-party applications; they
protect APIs that are intended only to be used for development
purposes. -->
<permission-group android:name="android.permission-group.DEVELOPMENT_TOOLS"
@@ -1569,15 +1581,16 @@
android:description="@string/permgroupdesc_developmentTools"
android:priority="310" />
- <!-- Allows an application to read or write the secure system settings. -->
+ <!-- Allows an application to read or write the secure system settings.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_SECURE_SETTINGS"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
android:label="@string/permlab_writeSecureSettings"
android:description="@string/permdesc_writeSecureSettings" />
- <!-- Allows an application to retrieve state dump information from system
- services. -->
+ <!-- Allows an application to retrieve state dump information from system services.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.DUMP"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
@@ -1585,15 +1598,16 @@
android:description="@string/permdesc_dump" />
<!-- Allows an application to read the low-level system log files.
- Log entries can contain the user's private information,
- which is why this permission is not available to normal apps. -->
+ <p>Not for use by third-party applications, because
+ Log entries can contain the user's private information. -->
<permission android:name="android.permission.READ_LOGS"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
android:label="@string/permlab_readLogs"
android:description="@string/permdesc_readLogs" />
- <!-- Configure an application for debugging. -->
+ <!-- Configure an application for debugging.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_DEBUG_APP"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
@@ -1601,7 +1615,8 @@
android:description="@string/permdesc_setDebugApp" />
<!-- Allows an application to set the maximum number of (not needed)
- application processes that can be running. -->
+ application processes that can be running.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_PROCESS_LIMIT"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
@@ -1609,14 +1624,16 @@
android:description="@string/permdesc_setProcessLimit" />
<!-- Allows an application to control whether activities are immediately
- finished when put in the background. -->
+ finished when put in the background.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ALWAYS_FINISH"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
android:label="@string/permlab_setAlwaysFinish"
android:description="@string/permdesc_setAlwaysFinish" />
- <!-- Allow an application to request that a signal be sent to all persistent processes -->
+ <!-- Allow an application to request that a signal be sent to all persistent processes.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
@@ -1628,7 +1645,8 @@
<!-- ==================================== -->
<eat-comment />
- <!-- Allows applications to RW to diagnostic resources. -->
+ <!-- Allows applications to RW to diagnostic resources.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.DIAGNOSTIC"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature"
@@ -1636,7 +1654,8 @@
android:label="@string/permlab_diagnostic" />
<!-- Allows an application to open, close, or disable the status bar
- and its icons. -->
+ and its icons.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.STATUS_BAR"
android:label="@string/permlab_statusBar"
android:description="@string/permdesc_statusBar"
@@ -1650,14 +1669,15 @@
android:protectionLevel="signature" />
<!-- Allows an application to force a BACK operation on whatever is the
- top activity. -->
+ top activity.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.FORCE_BACK"
android:label="@string/permlab_forceBack"
android:description="@string/permdesc_forceBack"
android:protectionLevel="signature" />
- <!-- Allows an application to update device statistics. Not for
- use by third party apps. -->
+ <!-- Allows an application to update device statistics.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.UPDATE_DEVICE_STATS"
android:label="@string/permlab_updateBatteryStats"
android:description="@string/permdesc_updateBatteryStats"
@@ -1678,15 +1698,16 @@
android:protectionLevel="signature|system" />
<!-- Allows an application to open windows that are for use by parts
- of the system user interface. Not for use by third party apps. -->
+ of the system user interface.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
android:label="@string/permlab_internalSystemWindow"
android:description="@string/permdesc_internalSystemWindow"
android:protectionLevel="signature" />
<!-- Allows an application to manage (create, destroy,
- Z-order) application tokens in the window manager. This is only
- for use by the system. -->
+ Z-order) application tokens in the window manager.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_APP_TOKENS"
android:label="@string/permlab_manageAppTokens"
android:description="@string/permdesc_manageAppTokens"
@@ -1702,7 +1723,7 @@
<!-- Allows an application to inject user events (keys, touch, trackball)
into the event stream and deliver them to ANY window. Without this
permission, you can only deliver events to windows in your own process.
- Very few applications should need to use this permission. -->
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.INJECT_EVENTS"
android:label="@string/permlab_injectEvents"
android:description="@string/permdesc_injectEvents"
@@ -1735,7 +1756,8 @@
<!-- Allows an application to watch and control how activities are
started globally in the system. Only for is in debugging
- (usually the monkey command). -->
+ (usually the monkey command).
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
android:label="@string/permlab_runSetActivityWatcher"
android:description="@string/permdesc_runSetActivityWatcher"
@@ -1760,14 +1782,16 @@
android:protectionLevel="signature|system" />
<!-- Allows an application to retrieve private information about
- the current top activity, such as any assist context it can provide. -->
+ the current top activity, such as any assist context it can provide.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
android:label="@string/permlab_getTopActivityInfo"
android:description="@string/permdesc_getTopActivityInfo"
android:protectionLevel="signature" />
<!-- Allows an application to retrieve the current state of keys and
- switches. This is only for use by the system.
+ switches.
+ <p>Not for use by third-party applications.
@deprecated The API that used this permission has been removed. -->
<permission android:name="android.permission.READ_INPUT_STATE"
android:label="@string/permlab_readInputState"
@@ -1817,46 +1841,51 @@
android:protectionLevel="signature" />
<!-- Allows low-level access to setting the orientation (actually
- rotation) of the screen. Not for use by normal applications. -->
+ rotation) of the screen.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ORIENTATION"
android:label="@string/permlab_setOrientation"
android:description="@string/permdesc_setOrientation"
android:protectionLevel="signature" />
<!-- Allows low-level access to setting the pointer speed.
- Not for use by normal applications. -->
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_POINTER_SPEED"
android:label="@string/permlab_setPointerSpeed"
android:description="@string/permdesc_setPointerSpeed"
android:protectionLevel="signature" />
<!-- Allows low-level access to setting the keyboard layout.
- Not for use by normal applications.
+ <p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
android:label="@string/permlab_setKeyboardLayout"
android:description="@string/permdesc_setKeyboardLayout"
android:protectionLevel="signature" />
- <!-- Allows an application to install packages. -->
+ <!-- Allows an application to install packages.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_PACKAGES"
android:label="@string/permlab_installPackages"
android:description="@string/permdesc_installPackages"
android:protectionLevel="signature|system" />
- <!-- Allows an application to clear user data -->
+ <!-- Allows an application to clear user data.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.CLEAR_APP_USER_DATA"
android:label="@string/permlab_clearAppUserData"
android:description="@string/permdesc_clearAppUserData"
android:protectionLevel="signature" />
- <!-- Allows an application to delete cache files. -->
+ <!-- Allows an application to delete cache files.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.DELETE_CACHE_FILES"
android:label="@string/permlab_deleteCacheFiles"
android:description="@string/permdesc_deleteCacheFiles"
android:protectionLevel="signature|system" />
- <!-- Allows an application to delete packages. -->
+ <!-- Allows an application to delete packages.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.DELETE_PACKAGES"
android:label="@string/permlab_deletePackages"
android:description="@string/permdesc_deletePackages"
@@ -1870,7 +1899,8 @@
android:protectionLevel="signature|system" />
<!-- Allows an application to change whether an application component (other than its own) is
- enabled or not. -->
+ enabled or not.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
android:label="@string/permlab_changeComponentState"
android:description="@string/permdesc_changeComponentState"
@@ -1882,14 +1912,16 @@
android:description="@string/permdesc_grantRevokePermissions"
android:protectionLevel="signature" />
- <!-- Allows an application to use SurfaceFlinger's low level features -->
+ <!-- Allows an application to use SurfaceFlinger's low level features.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
android:label="@string/permlab_accessSurfaceFlinger"
android:description="@string/permdesc_accessSurfaceFlinger"
android:protectionLevel="signature" />
<!-- Allows an application to take screen shots and more generally
- get access to the frame buffer data -->
+ get access to the frame buffer data.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_FRAME_BUFFER"
android:label="@string/permlab_readFrameBuffer"
android:description="@string/permdesc_readFrameBuffer"
@@ -1911,19 +1943,22 @@
android:description="@string/permdesc_controlWifiDisplay"
android:protectionLevel="signature" />
- <!-- Required to be able to disable the device (very dangerous!). -->
+ <!-- Required to be able to disable the device (very dangerous!).
+ <p>Not for use by third-party applications.. -->
<permission android:name="android.permission.BRICK"
android:label="@string/permlab_brick"
android:description="@string/permdesc_brick"
android:protectionLevel="signature" />
- <!-- Required to be able to reboot the device. -->
+ <!-- Required to be able to reboot the device.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.REBOOT"
android:label="@string/permlab_reboot"
android:description="@string/permdesc_reboot"
android:protectionLevel="signature|system" />
- <!-- Allows low-level access to power management -->
+ <!-- Allows low-level access to power management.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.DEVICE_POWER"
android:label="@string/permlab_devicePower"
android:description="@string/permdesc_devicePower"
@@ -1935,34 +1970,39 @@
android:protectionLevel="signature" />
<!-- Run as a manufacturer test application, running as the root user.
- Only available when the device is running in manufacturer test mode. -->
+ Only available when the device is running in manufacturer test mode.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.FACTORY_TEST"
android:label="@string/permlab_factoryTest"
android:description="@string/permdesc_factoryTest"
android:protectionLevel="signature" />
<!-- Allows an application to broadcast a notification that an application
- package has been removed. -->
+ package has been removed.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:label="@string/permlab_broadcastPackageRemoved"
android:description="@string/permdesc_broadcastPackageRemoved"
android:protectionLevel="signature" />
- <!-- Allows an application to broadcast an SMS receipt notification -->
+ <!-- Allows an application to broadcast an SMS receipt notification.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.BROADCAST_SMS"
android:permissionGroup="android.permission-group.MESSAGES"
android:label="@string/permlab_broadcastSmsReceived"
android:description="@string/permdesc_broadcastSmsReceived"
android:protectionLevel="signature" />
- <!-- Allows an application to broadcast a WAP PUSH receipt notification -->
+ <!-- Allows an application to broadcast a WAP PUSH receipt notification.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.BROADCAST_WAP_PUSH"
android:permissionGroup="android.permission-group.MESSAGES"
android:label="@string/permlab_broadcastWapPush"
android:description="@string/permdesc_broadcastWapPush"
android:protectionLevel="signature" />
+ <!-- Not for use by third-party applications. -->
<permission android:name="android.permission.MASTER_CLEAR"
android:label="@string/permlab_masterClear"
android:description="@string/permdesc_masterClear"
@@ -1970,7 +2010,8 @@
<!-- Allows an application to call any phone number, including emergency
numbers, without going through the Dialer user interface for the user
- to confirm the call being placed. Not for use by third party apps. -->
+ to confirm the call being placed.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.CALL_PRIVILEGED"
android:label="@string/permlab_callPrivileged"
android:description="@string/permdesc_callPrivileged"
@@ -1983,14 +2024,16 @@
android:protectionLevel="signature|system" />
<!-- Allows enabling/disabling location update notifications from
- the radio. Not for use by normal applications. -->
+ the radio.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
android:label="@string/permlab_locationUpdates"
android:description="@string/permdesc_locationUpdates"
android:protectionLevel="signature|system" />
<!-- Allows read/write access to the "properties" table in the checkin
- database, to change values that get uploaded. -->
+ database, to change values that get uploaded.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
android:label="@string/permlab_checkinProperties"
android:description="@string/permdesc_checkinProperties"
@@ -2010,7 +2053,8 @@
android:description="@string/permdesc_batteryStats"
android:protectionLevel="dangerous" />
- <!-- Allows an application to control the backup and restore process
+ <!-- Allows an application to control the backup and restore process.
+ <p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.BACKUP"
android:label="@string/permlab_backup"
@@ -2037,7 +2081,7 @@
picks an AppWidget to go into a particular host, thereby giving that
host application access to the private data from the AppWidget app.
An application that has this permission should honor that contract.
- Very few applications should need to use this permission. -->
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.BIND_APPWIDGET"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:label="@string/permlab_bindGadget"
@@ -2058,7 +2102,8 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature|system" />
- <!-- Allows applications to change the background data setting
+ <!-- Allows applications to change the background data setting.
+ <p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 39915f9..28b63a7 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
<string name="owner_name" msgid="2716755460376028154">"Eienaar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hierdie program werk nie met rekeninge vir beperkte profiele nie"</string>
<string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
<string name="revoke" msgid="5404479185228271586">"Herroep"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 327f1cb..8a2fc36 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"የአሁኑ ተጠቃሚ <xliff:g id="NAME">%1$s</xliff:g>።"</string>
<string name="owner_name" msgid="2716755460376028154">"ባለቤት"</string>
<string name="error_message_title" msgid="4510373083082500195">"ስህተት"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"ይህ መተግበሪያ የተገደቡ መገለጫዎች መለያዎችን አይደግፍም"</string>
<string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
<string name="revoke" msgid="5404479185228271586">"ሻር"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4d8a5cc..d4803a9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Собственик"</string>
<string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Това приложение не поддържа профили за потребителски профили с ограничена функционалност"</string>
<string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отмяна"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4eaf068..9b86c35 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Usuari actual: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Propietari"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"L\'aplicació no és compatible amb comptes de perfils restringits"</string>
<string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 91498cd..6f2ffa6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
<string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tato aplikace nepodporuje účty pro omezené profily"</string>
<string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
<string name="revoke" msgid="5404479185228271586">"Zrušit"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 081fd2a..876c475 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Ejer"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fejl"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne applikation understøtter ikke konti for begrænsede profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
<string name="revoke" msgid="5404479185228271586">"Tilbagekald"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 53db449..bd40c64 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -602,7 +602,7 @@
<string name="permlab_readDictionary" msgid="4107101525746035718">"Begriffe lesen, die Sie zum Wörterbuch hinzugefügt haben"</string>
<string name="permdesc_readDictionary" msgid="659614600338904243">"Ermöglicht der App, alle Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
<string name="permlab_writeDictionary" msgid="2183110402314441106">"Wörter zu meinem Wörterbuch hinzufügen"</string>
- <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Ermöglicht der App, dem Nutzerwörterbuch neue Einträge hinzuzufügen"</string>
+ <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Ermöglicht der App, neue Einträge zum Nutzerwörterbuch hinzuzufügen"</string>
<string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"Zugriff auf geschützten Speicher testen"</string>
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"Zugriff auf geschützten Speicher testen"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Ermöglicht der App, eine Berechtigung für USB-Speicher zu testen, die künftig auf neuen Geräten verfügbar sein wird"</string>
@@ -944,11 +944,11 @@
<item quantity="other" msgid="3903706804349556379">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
</plurals>
<plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Vor 1 Minute"</item>
+ <item quantity="one" msgid="3306787433088810191">"vor 1 Minute"</item>
<item quantity="other" msgid="2176942008915455116">"vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
</plurals>
<plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Vor 1 Stunde"</item>
+ <item quantity="one" msgid="9150797944610821849">"vor 1 Stunde"</item>
<item quantity="other" msgid="2467273239587587569">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
</plurals>
<plurals name="last_num_days">
@@ -957,7 +957,7 @@
<string name="last_month" msgid="3959346739979055432">"Letzter Monat"</string>
<string name="older" msgid="5211975022815554840">"Älter"</string>
<plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"Gestern"</item>
+ <item quantity="one" msgid="861358534398115820">"gestern"</item>
<item quantity="other" msgid="2479586466153314633">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
</plurals>
<plurals name="in_num_seconds">
@@ -985,11 +985,11 @@
<item quantity="other" msgid="851164968597150710">"vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
</plurals>
<plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Vor 1 Stunde"</item>
+ <item quantity="one" msgid="4796212039724722116">"vor 1 Stunde"</item>
<item quantity="other" msgid="6889970745748538901">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
</plurals>
<plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"Gestern"</item>
+ <item quantity="one" msgid="8463161711492680309">"gestern"</item>
<item quantity="other" msgid="3453342639616481191">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
</plurals>
<plurals name="abbrev_in_num_seconds">
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Eigentümer"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fehler"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Diese App unterstützt keine Konten für eingeschränkte Profile."</string>
<string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
<string name="revoke" msgid="5404479185228271586">"Aufheben"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 78a707f..c388643 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -607,7 +607,7 @@
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"δοκιμή πρόσβασης σε προστατευμένο χώρο αποθήκευσης"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Επιτρέπει USB για άλλες συσκ."</string>
<string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Επιτρέπει στην εφαρμογή τη δοκιμή μια άδειας για την κάρτα SD που θα διατίθεται σε μελλοντικές συσκευές."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"τροπ. ή διαγρ. περιεχ. αποθ. χώρ. USB"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"τροπ. ή διαγρ. του USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"τροποποίηση ή διαγραφή των περιεχομένων της κάρτας SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Επιτρέπει στην εφαρμογή την εγγραφή στον αποθηκευτικό χώρο USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Τρέχων χρήστης <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Κάτοχος"</string>
<string name="error_message_title" msgid="4510373083082500195">"Σφάλμα"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένα προφίλ"</string>
<string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
<string name="revoke" msgid="5404479185228271586">"Ανάκληση"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 49f6e1f..1175115 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos."</string>
<string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0a704c3..8724464 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -927,7 +927,7 @@
<string name="prepend_shortcut_label" msgid="2572214461676015642">"MENU+"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"espacio"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"intro"</string>
- <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"suprimir"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"eliminar"</string>
<string name="search_go" msgid="8298016669822141719">"Buscar"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"Buscar"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"Consulta"</string>
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos"</string>
<string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8f6911c..0ae1829 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Omanik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Viga"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"See rakendus ei toeta piiratud profiilide kontosid"</string>
<string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
<string name="revoke" msgid="5404479185228271586">"Tühista"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 15a5f95..bd0b22c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Omistaja"</string>
<string name="error_message_title" msgid="4510373083082500195">"Virhe"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tämä sovellus ei tue rajoitettujen profiilien tilejä"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
<string name="revoke" msgid="5404479185228271586">"Peruuta"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9afa938..26d1831 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propriétaire"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erreur"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Les comptes des profils en accès limité ne sont pas compatibles avec cette application."</string>
<string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
<string name="revoke" msgid="5404479185228271586">"Révoquer"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 4df3a5b..a7cae1d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
<string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"यह एप्लिकेशन प्रतिबंधित प्रोफ़ाइल के खातों का समर्थन नहीं करता है"</string>
<string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
<string name="revoke" msgid="5404479185228271586">"निरस्त करें"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a7208ee..cda7076 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Pogreška"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikacija ne podržava račune za ograničene profile"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
<string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3060fd1..0d5336e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
<string name="owner_name" msgid="2716755460376028154">"Tulajdonos"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hiba"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ez az alkalmazás nem támogatja a korlátozott profilokkal rendelkező fiókokat"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
<string name="revoke" msgid="5404479185228271586">"Visszavonás"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5504078..bd2fbf4 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Kesalahan"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikasi ini tidak mendukung akun untuk profil yang dibatasi"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Cabut"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a1e8bfc..4ad6f74 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Utente corrente <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Errore"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Questa app non supporta account relativi a profili con limitazioni"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index d48f846..b5f18e1 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"המשתמש הנוכחי <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"בעלים"</string>
<string name="error_message_title" msgid="4510373083082500195">"שגיאה"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"האפליקציה הזו לא תומכת בחשבונות עבור פרופילים מוגבלים"</string>
<string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
<string name="revoke" msgid="5404479185228271586">"בטל"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9932924..2e4ce40 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"現在のユーザーは<xliff:g id="NAME">%1$s</xliff:g>です。"</string>
<string name="owner_name" msgid="2716755460376028154">"所有者"</string>
<string name="error_message_title" msgid="4510373083082500195">"エラー"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"このアプリでは制限付きプロフィールのアカウントはサポートしていません"</string>
<string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
<string name="revoke" msgid="5404479185228271586">"取り消し"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f66fb33..94fa0d9 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"현재 사용자는 <xliff:g id="NAME">%1$s</xliff:g>님입니다."</string>
<string name="owner_name" msgid="2716755460376028154">"소유자"</string>
<string name="error_message_title" msgid="4510373083082500195">"오류"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"이 앱은 제한된 프로필의 계정을 지원하지 않습니다."</string>
<string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
<string name="revoke" msgid="5404479185228271586">"취소"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d4019f3..e938945 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Dabartinis naudotojas: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Savininkas"</string>
<string name="error_message_title" msgid="4510373083082500195">"Klaida"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ši programa nepalaiko apribotų profilių paskyrų"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
<string name="revoke" msgid="5404479185228271586">"Anuliuoti"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dac8a7b..b81df3a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Pašreizējais lietotājs: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Īpašnieks"</string>
<string name="error_message_title" msgid="4510373083082500195">"Kļūda"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Šajā lietotnē netiek atbalstīti ierobežotu profilu konti."</string>
<string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
<string name="revoke" msgid="5404479185228271586">"Atsaukt"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index bcc9493..f9de1b1 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Ralat"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Apl ini tidak menyokong akaun untuk profil yang disekat"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Batalkan"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5993cc9..cd222a0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Gjeldende bruker: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Eier"</string>
<string name="error_message_title" msgid="4510373083082500195">"Feil"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne appen støtter ikke kontoer for begrensede profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
<string name="revoke" msgid="5404479185228271586">"Opphev"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b8e5deb..4492fef 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Eigenaar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Deze app biedt geen ondersteuning voor accounts voor beperkte profielen"</string>
<string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
<string name="revoke" msgid="5404479185228271586">"Intrekken"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 642237c..3c27ab4 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Właściciel"</string>
<string name="error_message_title" msgid="4510373083082500195">"Błąd"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacja nie obsługuje kont w profilach z ograniczeniami"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
<string name="revoke" msgid="5404479185228271586">"Cofnij"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ff912b9..29b63a9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> do utilizador atual."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicação não suporta contas de perfis restritos"</string>
<string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9698884..f5ba0fb 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -607,7 +607,7 @@
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"testar o acesso ao armazenamento protegido"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Permite que o aplicativo teste uma permissão para o armazenamento USB que estará disponível em dispositivos futuros."</string>
<string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Permite que o aplicativo teste uma permissão para o cartão SD que estará disponível em dispositivos futuros."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modif ou excl cont. armaz USB"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modificar ou excluir conteúdo do armazenamento USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modificar ou excluir o conteúdo do cartão SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Permite gravar no armaz. USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite que o aplicativo grave em seu cartão SD."</string>
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Este aplicativo não suporta contas para perfis restritos"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b7866f6..f09fcc2 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Eroare"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Această aplicație nu acceptă conturi pentru profilurile cu permisiuni limitate"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
<string name="revoke" msgid="5404479185228271586">"Revocați"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3b8b907..211a52c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Выбран аккаунт пользователя <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Владелец"</string>
<string name="error_message_title" msgid="4510373083082500195">"Ошибка"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Это приложение не поддерживается в аккаунтах для профилей с ограниченным доступом"</string>
<string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отменить"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index fd0b91f..f412b6b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -607,7 +607,7 @@
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"preskus dostopa do zaščitene shrambe"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Aplikaciji omogoča preskušanje dovoljenja za shrambo USB, ki bo na voljo v prihodnjih napravah."</string>
<string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Aplikaciji omogoča preskušanje dovoljenja za kartico SD, ki bo na voljo v prihodnjih napravah."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"spr. ali bris. vseb. pomn. USB"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"spreminjanje ali brisanje vsebine shrambe USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"spreminjanje ali brisanje vsebine kartice SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Programu omogoča zapisovanje v pomnilnik USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Programu omogoča pisanje na kartico SD."</string>
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Lastnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Napaka"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacija ne podpira računov za profile z omejitvami"</string>
<string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
<string name="revoke" msgid="5404479185228271586">"Prekliči"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 742375f..d5b6554 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Актуелни корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Власник"</string>
<string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ова апликација не подржава налоге за ограничене профиле"</string>
<string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
<string name="revoke" msgid="5404479185228271586">"Опозови"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 1a316bd..5f87ba9 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Ägare"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fel"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Den här appen stöder inte konton för begränsade profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
<string name="revoke" msgid="5404479185228271586">"Återkalla"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index bf03bdc..b203824 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Mmiliki"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hitilafu"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Programu hii haiwezi kutumiwa na akaunti za wasifu zilizowekewa vikwazo"</string>
<string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
<string name="revoke" msgid="5404479185228271586">"Batilisha"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f917448..521cb00 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"เจ้าของ"</string>
<string name="error_message_title" msgid="4510373083082500195">"ข้อผิดพลาด"</string>
- <string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่มีโปรไฟล์ที่ถูกจำกัด"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่โปรไฟล์ถูกจำกัด"</string>
<string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
<string name="revoke" msgid="5404479185228271586">"เพิกถอน"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 53aaa0e..9e58994 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"May-ari"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hindi sinusuportahan ng app na ito ang mga account para sa mga pinaghihigpitang profile"</string>
<string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
<string name="revoke" msgid="5404479185228271586">"Bawiin"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 1c25ab7..2c72c3f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Sahibi"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hata"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Bu uygulama, kısıtlanmış profillerin hesaplarını desteklemez"</string>
<string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
<string name="revoke" msgid="5404479185228271586">"İptal et"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 9070582..73e3c12 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Поточний користувач: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Власник"</string>
<string name="error_message_title" msgid="4510373083082500195">"Помилка"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ця програма не підтримує облікові записи для обмежених профілів"</string>
<string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
<string name="revoke" msgid="5404479185228271586">"Анулювати"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 5d4f0a7..d72b1a7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Chủ sở hữu"</string>
<string name="error_message_title" msgid="4510373083082500195">"Lỗi"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ứng dụng này không hỗ trợ tài khoản đối với các tiểu sử bị hạn chế"</string>
<string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
<string name="revoke" msgid="5404479185228271586">"Thu hồi"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 9878860..7ea742a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
<string name="owner_name" msgid="2716755460376028154">"机主"</string>
<string name="error_message_title" msgid="4510373083082500195">"错误"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"此应用不支持受限个人资料的帐户"</string>
<string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
<string name="revoke" msgid="5404479185228271586">"撤消"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index f175fc1..499b3ac 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -621,7 +621,7 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"撥打/接聽網路電話"</string>
<string name="permdesc_use_sip" msgid="4717632000062674294">"允許應用程式使用 SIP 服務撥打/接聽網路電話。"</string>
- <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"讀取網路用量記錄"</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"讀取網路用量紀錄"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"允許應用程式讀取特定網路和應用程式的網路使用記錄。"</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"管理網路政策"</string>
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允許應用程式管理網路政策並定義應用程式專用規則。"</string>
@@ -1498,8 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"目前的使用者是 <xliff:g id="NAME">%1$s</xliff:g>。"</string>
<string name="owner_name" msgid="2716755460376028154">"擁有者"</string>
<string name="error_message_title" msgid="4510373083082500195">"錯誤"</string>
- <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
- <skip />
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"這個應用程式不支援設有限制的個人資料所屬帳戶"</string>
<string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
<string name="revoke" msgid="5404479185228271586">"撤銷"</string>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 089a859..36a7a86 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2046,6 +2046,7 @@
<public type="attr" name="canRequestTouchExplorationMode" id="0x010103d7" />
<public type="attr" name="canRequestEnhancedWebAccessibility" id="0x010103d8" />
<public type="attr" name="canRequestFilterKeyEvents" id="0x010103d9" />
+ <public type="attr" name="layoutMode" id="0x010103da" />
<public type="style" name="Theme.Holo.NoActionBar.Overscan" id="0x010301dd" />
<public type="style" name="Theme.Holo.Light.NoActionBar.Overscan" id="0x010301de" />
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index a147350..27cedcb 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -219,6 +219,21 @@
- from: /guide/tutorials/...
to: /resources/tutorials/...
+# move ui docs to design
+
+- from: /guide/practices/ui_guidelines/index.html
+ to: /design/index.html
+
+- from: /guide/practices/ui_guidelines/icon_design.*
+ to: /design/style/iconography.html
+
+- from: /guide/practices/ui_guidelines/activity_task_design.html
+ to: /design/patterns/app-structure.html
+
+- from: /guide/practices/ui_guidelines/menu_design.html
+ to: /design/patterns/actionbar.html
+
+
# ------------------- RESOURCES -------------------
- from: /resources/dashboard/...
diff --git a/docs/html/design/media/devices_displays_density.png b/docs/html/design/media/devices_displays_density.png
index 7ddad31..4e3cbf6 100644
--- a/docs/html/design/media/devices_displays_density.png
+++ b/docs/html/design/media/devices_displays_density.png
Binary files differ
diff --git a/docs/html/design/media/devices_displays_density@2x.png b/docs/html/design/media/devices_displays_density@2x.png
new file mode 100644
index 0000000..79a46b0
--- /dev/null
+++ b/docs/html/design/media/devices_displays_density@2x.png
Binary files differ
diff --git a/docs/html/design/style/devices-displays.jd b/docs/html/design/style/devices-displays.jd
index 18550d9..a8f9d6f 100644
--- a/docs/html/design/style/devices-displays.jd
+++ b/docs/html/design/style/devices-displays.jd
@@ -32,7 +32,7 @@
</div>
</div>
- <img src="{@docRoot}design/media/devices_displays_density.png">
+ <img src="{@docRoot}design/media/devices_displays_density@2x.png" alt="" height="160" />
<h4>Strategies</h4>
<p>So where do you begin when designing for multiple screens? One approach is to work in the base
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index 1475e5c..0d2cdbb 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -4,9 +4,37 @@
<img src="{@docRoot}design/media/iconography_overview.png">
+
<p>An icon is a graphic that takes up a small portion of screen real estate and provides a quick,
intuitive representation of an action, a status, or an app.</p>
+<p>When you design icons for your app, it's important to keep in mind that your
+app may be installed on a variety of devices that offer a range of
+pixel densities, as mentioned in
+<a href="{@docRoot}design/style/devices-displays.html">Devices
+and Displays</a>. But you can make your icons look great on all devices
+by providing each icon in multiple sizes. When your app runs, Android checks the characteristics of
+the device screen and loads the appropriate density-specific assets for your app. </p>
+
+<p>Because you will deliver each icon in multiple sizes to support different densities,
+the design guidelines below
+refer to the icon dimensions in <acronym title="density-independent pixels">dp</acronym>
+units, which are based on the pixel dimensions of a medium-density (MDPI) screen.</p>
+
+<img src="{@docRoot}design/media/devices_displays_density@2x.png" alt="" height="160" />
+
+<p>So, to create an icon for different densities, you should follow the <strong>2:3:4:6 scaling
+ratio</strong> between the four primary densities (medium, high, x-high, and xx-high,
+respectively). For example, consider that the size for a launcher icon is specified to be
+48x48 dp. This means the baseline (MDPI) asset is 48x48 px, and the
+high density (HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
+density (XHDPI) asset should be 2x the baseline at 96x96 px, and so on.</p>
+
+<p class="note"><strong>Note:</strong> Android also supports low-density (LDPI) screens,
+but you normally don't need to create custom assets at this size because Android
+effectively down-scales your HDPI assets by 1/2 to match the expected size.</p>
+
+
<h2 id="launcher">Launcher</h2>
@@ -338,3 +366,165 @@
</div>
<!-- 2 free columns -->
</div>
+
+
+
+
+
+
+
+
+
+
+<h2 id="DesignTips">Design Tips</h2>
+
+<p>Here are some tips you might find useful as you create icons or other
+drawable assets for your application. These tips assume you are using
+Adobe® Photoshop® or a similar raster and vector image-editing program.</p>
+
+
+
+
+<h3>Use vector shapes where possible</h3>
+
+<p>Many image-editing programs such as Adobe® Photoshop® allow you to use a
+combination of vector shapes and raster layers and effects. When possible,
+use vector shapes so that if the need arises, assets can be scaled up without
+loss of detail and edge crispness.</p>
+
+<p>Using vectors also makes it easy to align edges and corners to pixel
+boundaries at smaller resolutions.</li>
+
+
+
+<h3>Start with large artboards</h3>
+
+<p>Because you will need to create assets for different screen densities,
+it is best to start your icon
+designs on large artboards with dimensions that are multiples of the target icon
+sizes. For example, launcher icons are 48, 72, 96, or 144 pixels wide,
+depending on screen density (mdpi, hdpi, xhdpi, and xxhdpi, respectively). If you
+initially draw launcher icons on an 864x864 artboard, it will be easier and
+cleaner to adjust the icons when you scale the artboard down to the target
+sizes for final asset creation.</p>
+
+
+
+<h3>When scaling, redraw bitmap layers as needed</h3>
+
+<p>If you scaled an image up from a bitmap layer, rather than from a vector
+layer, those layers will need to be redrawn manually to appear crisp at higher
+densities. For example if a 60x60 circle was painted as a bitmap for
+mdpi it will need to be repainted as a 90x90 circle for hdpi.</p>
+
+
+
+<h3>Use common naming conventions for icon assets</h3>
+
+<p>Try to name files so that related assets will group together inside a
+directory when they are sorted alphabetically. In particular, it helps to use a
+common prefix for each icon type. For example:</p>
+
+<table>
+<tr>
+<th>Asset Type</th>
+<th>Prefix</th>
+<th>Example</th>
+</tr>
+<tr>
+<td>Icons</td>
+<td><code>ic_</code></td>
+<td><code>ic_star.png</code></td>
+</tr>
+<tr>
+<td>Launcher icons</td>
+<td><code>ic_launcher</code></td>
+<td><code>ic_launcher_calendar.png</code></td>
+</tr>
+<tr>
+<td>Menu icons and Action Bar icons</td>
+<td><code>ic_menu</code></td>
+<td><code>ic_menu_archive.png</code></td>
+</tr>
+<tr>
+<td>Status bar icons</td>
+<td><code>ic_stat_notify</code></td>
+<td><code>ic_stat_notify_msg.png</code></td>
+</tr>
+<tr>
+<td>Tab icons</td>
+<td><code>ic_tab</code></td>
+<td><code>ic_tab_recent.png</code></td>
+</tr>
+<tr>
+<td>Dialog icons</td>
+<td><code>ic_dialog</code></td>
+<td><code>ic_dialog_info.png</code></td>
+</tr>
+</table>
+
+<p>Note that you are not required to use a shared prefix of any
+type—doing so is for your convenience only.</p>
+
+
+<h3>Set up a working space that organizes files by density</h3>
+
+<p>Supporting multiple screen densities means you must create multiple versions
+of the same icon. To help keep the multiple copies of files safe and easier to
+find, we recommend creating a directory structure in your working space that
+organizes asset files based on the target density. For example:</p>
+
+<pre>
+art/...
+ mdpi/...
+ _pre_production/...
+ <em>working_file</em>.psd
+ <em>finished_asset</em>.png
+ hdpi/...
+ _pre_production/...
+ <em>working_file</em>.psd
+ <em>finished_asset</em>.png
+ xhdpi/...
+ _pre_production/...
+ <em>working_file</em>.psd
+ <em>finished_asset</em>.png</pre>
+ xxhdpi/...
+ _pre_production/...
+ <em>working_file</em>.psd
+ <em>finished_asset</em>.png</pre>
+
+<p>Because the structure in your working space is similar to that of the application, you
+can quickly determine which assets should be copied to each
+resources directory. Separating assets by density also helps you detect any
+variances in filenames across densities, which is important because
+corresponding assets for different densities must share the same filename.</p>
+
+<p>For comparison, here's the resources directory structure of a typical
+application: </p>
+
+<pre>res/...
+ drawable-ldpi/...
+ <em>finished_asset</em>.png
+ drawable-mdpi/...
+ <em>finished_asset</em>.png
+ drawable-hdpi/...
+ <em>finished_asset</em>.png
+ drawable-xhdpi/...
+ <em>finished_asset</em>.png
+</pre>
+
+<p>For more information about how to save resources in the application project,
+see <a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a>.
+</p>
+
+
+<h3>Remove unnecessary metadata from final assets</h3>
+
+<p>Although the Android SDK tools will automatically compress PNGs when packaging
+application resources into the application binary, a good practice is to remove
+unnecessary headers and metadata from your PNG assets. Tools such as <a
+href="http://optipng.sourceforge.net/">OptiPNG</a> or <a
+href="http://pmt.sourceforge.net/pngcrush/">Pngcrush</a> can ensure that this
+metadata is removed and that your image asset file sizes are optimized.</p>
+
+
diff --git a/docs/html/design/style/metrics-grids.jd b/docs/html/design/style/metrics-grids.jd
index 3116ff6d..0a99a2f 100644
--- a/docs/html/design/style/metrics-grids.jd
+++ b/docs/html/design/style/metrics-grids.jd
@@ -4,15 +4,28 @@
<p>Devices vary not only in physical size, but also in screen density (<acronym title="Dots per
inch">DPI</acronym>). To simplify the way you design for multiple screens, think of each device as
-falling into a particular size bucket and density bucket. The size buckets are <em>handset</em> (smaller than
-600<acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi
-screen.">dp</acronym>) and <em>tablet</em> (larger than or equal 600dp). The density buckets are <acronym
+falling into a particular size bucket and density bucket:</p>
+<ul>
+ <li>The size buckets are <em>handset</em> (smaller than
+600<acronym title="Density-independent pixels: One dp is one pixel on a 160 dpi (mdpi)
+screen.">dp</acronym>) and <em>tablet</em> (larger than or equal 600dp).</li>
+ <li>The density buckets are <acronym
title="Low density (120 dpi)">LDPI</acronym>, <acronym title="Medium density (160
-dpi)">MDPI</acronym>, <acronym title="High density (240 dpi)">HDPI</acronym>, and <acronym title
-="Extra-high density (320 dpi)">XHDPI</acronym>. Optimize your application's UI by designing
+dpi)">MDPI</acronym>, <acronym title="High density (240 dpi)">HDPI</acronym>, <acronym title
+="Extra-high density (320 dpi)">XHDPI</acronym>, and <acronym title
+="Extra-extra!-high density (480 dpi)">XXHDPI</acronym>.</li>
+</ul>
+
+<p>Optimize your application's UI by designing
alternative layouts for some of the different size buckets, and provide alternative bitmap images
for different density buckets.</p>
+<p>Because it's important that you design and implement your layouts for multiple densities,
+the guidelines below and throught the documentation
+refer to layout dimensions with <acronym title="Density-independent pixels: One dp is one pixel
+on a 160 dpi (mdpi) screen.">dp</acronym> measurements instead of pixels.</p>
+
+
<div class="layout-content-row">
<div class="layout-content-col span-8">
@@ -30,6 +43,7 @@
</div>
</div>
+
<h2 id="48dp-rhythm">48dp Rhythm</h2>
<p>Touchable UI components are generally laid out along 48dp units.</p>
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index ffe15c5..0cadbd2 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -23,7 +23,7 @@
<li><a href="#msg_examples">Message Examples</a></li>
</ol>
</li>
- <li><a href="#flow">Control Flow</a> </li>
+ <li><a href="#flow">Flow Control</a> </li>
</ol>
<h2>See Also</h2>
@@ -48,6 +48,8 @@
<p>The upstream messaging (device-to-cloud) feature of CCS is part of the Google Play services platform. Upstream messaging is available through the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. To use upstream messaging and the new streamlined registration process, you must <a href="{@docRoot}google/play-services/setup.html">set up</a> the Google Play services SDK.</p>
+<p class="note"><strong>Note:</strong> For an example of an XMPP server, see <a href="server.html#xmpp">GCM Server</a>.
+
<h2 id="gcm">CCS vs. GCM HTTP</h2>
<p>CCS messaging differs from GCM HTTP messaging in the following ways:</p>
@@ -229,69 +231,13 @@
</gcm>
</message></pre>
-<h4 id="python">Python Example</h4>
-<p>This example illustrates how to connect,
-send, and receive GCM messages using XMPP. It shouldn't be used as-is
-on a production deployment.</p>
-<pre>
-import sys, json, xmpp
-SERVER = ('gcm.googleapis.com', 5235)
-#USERNAME = '<your_numeric_project_id>'
-#PASSWORD = '<your_gcm_api_key>'
+<h2 id="flow">Flow Control</h2>
-# Unique message id for downstream messages
-sent_message_id = 0
+<p>Every message sent to CCS receives either an ACK or a NACK response. Messages that haven't received one of these responses are considered pending. If the pending message count reaches 1000, the 3rd-party server should stop sending new messages and wait for CCS to acknowledge some of the existing pending messages.</p>
-def message_callback(session, message):
- global sent_message_id
- gcm = message.getTags('gcm')
+<p>Conversely, to avoid overloading the 3rd-party server, CCS will stop sending if there are too many unacknowledged messages. Therefore, the 3rd-party server should "ACK" received messages as soon as possible to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party server should continue sending ACKs to avoid blocking delivery of new messages.</p>
- if gcm:
- gcm_json = gcm[0].getData()
- msg = json.loads(gcm_json)
- msg_id = msg['message_id']
- device_reg_id = msg['from']
-
- # Ignore non-standard messages (e.g. acks/nacks).
- if not msg.has_key('message_type'):
- # Acknowledge the incoming message.
- send({'to': device_reg_id,
- 'message_type': 'ack',
- 'message_id': msg_id})
-
- # Send a response back to the server.
- send({'to': device_reg_id,
- 'message_id' : str(sent_message_id),
- 'data': {'pong': 1}})
- sent_message_id = sent_message_id + 1
-
-def send(json_dict):
- template = ("<message from='{0}' to='gcm@google.com'>"
- "<gcm xmlns='google:mobile:data'>{1}</gcm></message>")
- client.send(xmpp.protocol.Message(
- node=template.format(client.Bind.bound[0],
- json.dumps(json_dict))))
-
-client = xmpp.Client(SERVER[0], debug=['socket'])
-client.connect(server=SERVER, secure=1, use_srv=False)
-auth = client.auth(USERNAME, PASSWORD, 'test')
-if not auth:
- print 'Authentication failed!'
- sys.exit(1)
-
-client.RegisterHandler('message', message_callback)
-
-while True:
- client.Process(1)</pre>
-
-<h2 id="flow">Control Flow</h2>
-
-<p>Every message sent by a 3rd-party server to CCS receives either an ACK or a NACK response. A single connection can have at most 1000 messages that were sent without having yet received a response.</p>
-
-<p>To enforce this policy, the app can maintain a counter of sent messages that increments on each send and decrements on each ACK or NACK. If the counter exceeds 1000, the app should stop sending messages until an ACK or NACK is received.</p>
-
-<p>Conversely, when CCS sends messages to a 3rd-party server, it expects ACKs for each message it sends, and it will not send more than 1000 unacknowledged messages.</p>
-
-<p>The ACKs and messages must match on each connection. You can only send an ACK for a message on the connection on which it was received.</p>
+<p>ACKs are only valid within the context of one connection. If the connection is closed before a message can be ACKed, the 3rd-party server should wait for CCS to resend the message before ACKing it again.
+</p>
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
new file mode 100644
index 0000000..7604932
--- /dev/null
+++ b/docs/html/google/gcm/client.jd
@@ -0,0 +1,24 @@
+page.title=GCM Client
+page.tags="cloud","push","messaging"
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="gs.html">Getting Started</a></li>
+<li><a href="server.html">GCM Server</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>A GCM client is a GCM-enabled app that runs on an Android device. To write your client code, we recommend that you use the new <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. The client helper library that was offered in previous versions of GCM still works, but it has been superseded by the more efficient <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs.</p>
+
+<p>A full GCM implementation requires both a client implementation and a server-side implementation. For a step-by-step guide to creating a complete sample implementation that includes both client and server, see <a href="gs.html">Getting Started</a>. </p>
+
+<p>
+
+
diff --git a/docs/html/google/gcm/demo.jd b/docs/html/google/gcm/demo.jd
index 6da9e98..012eb9a 100644
--- a/docs/html/google/gcm/demo.jd
+++ b/docs/html/google/gcm/demo.jd
@@ -1,6 +1,22 @@
page.title=GCM Demo Application
@jd:body
+<div id="deprecatedSticker">
+ <a href="#"
+ onclick="$('#naMessage').show();$('#deprecatedSticker').hide();return false">
+ <strong>This doc is deprecated</strong></a>
+</div>
+
+
+<div id="naMessage" style="display:block">
+<div><p><strong>The information in this document has been superseded by <a href="server.html">GCM Server</a> and <a href="client.html">GCM Client</a></strong>. Please use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> API instead of the GCM client helper library. The GCM server helper library is still valid.</p>
+
+ <input style="margin-top:1em;padding:5px" type="button"
+ value="That's nice, but I still want to read this document"
+onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
+</div>
+</div>
+
<div id="qv-wrapper">
<div id="qv">
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 5acf60d..ceb82b0 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -28,20 +28,6 @@
<li><a href="#user">What Does the User See?</a></li>
</ol>
</li>
- <li><a href="#writing_apps">Writing Android Applications that use GCM</a>
- <ol>
- <li><a href="#manifest">Creating the Manifest</a></li>
- <li><a href="#registering">Registering for GCM</a></li>
-
- <li><a href="#handling_intents">Handling Intents Sent by GCM</a>
- <ol>
- <li><a href="#handling_reg">Handling Registration Results</a></li>
- <li><a href="#received_data">Handling Received Data</a></li>
- </ol>
- </li>
- <li><a href="#testing">Developing and Testing Your Android Applications</a></li>
- </ol>
- </li>
<li><a href="#server">Role of the 3rd-party Application Server</a>
<ol class="toc">
<li><a href="#send-msg">Sending Messages</a>
@@ -53,7 +39,6 @@
</ol>
<li><a href="#stats">Viewing Statistics</a>
</li>
- <li><a href="#example">Examples</a></li>
</ol>
@@ -306,336 +291,6 @@
includes GCM. They must approve the use of this feature to install the
Android application. </p>
-<h2 id="writing_apps">Writing Android Applications that Use GCM</h2>
-
-<p>To write Android applications that use GCM, you must have an application
-server that can perform the tasks described in <a href="#server">Role of the
-3rd-party Application Server</a>. This section describes the steps you take to
-create a client application that uses GCM.</p>
-
-<p>Remember that there is no user interface associated with GCM.
-However you choose to process messages in your Android application is up to you.</p>
-
-<p>There are two primary steps involved in writing a client Android application:</p>
-
-<ul>
- <li>Creating a manifest that contains the permissions the Android application needs to
-use GCM.</li>
- <li>Implementing your code. To use GCM, this implementation must
-include:
- <ul>
- <li>Code to start and stop the registration service.</li>
- <li>Receivers for the <code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code> intents.</li>
- </ul>
- </li>
-</ul>
-
-<p class="note"><strong>Note:</strong> This section describes how to
-write an app without using the
-<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>.
-For details on writing
-an app that uses the helper libraries (which is the recommended and
-simpler approach), see <a href="gs.html">GCM: Getting Started</a>.
-
-<h3 id="manifest">Creating the Manifest</h3>
-
-<p>To use the GCM feature, the
-<code>AndroidManifest.xml</code> file must include the following:</p>
-
-<ul>
- <li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
- <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd-party server.</li>
- <li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
- <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional—use only if the app wants to keep the device from sleeping.</li>
- <li>An <code>applicationPackage + ".permission.C2D_MESSAGE</code> permission to prevent other Android applications from registering and receiving the Android application's
-messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.</li>
- <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code>, with the category set
-as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
-Framework can send a message to it. Note that both registration and the receiving
-of messages are implemented as <a href="{@docRoot}guide/components/intents-filters.html">Intents</a>.</li>
- <li>An intent service to handle the intents received by the broadcast receiver. Optional.</li>
- <li>If the GCM feature is critical to the Android application's function, be sure to
-set <code>android:minSdkVersion="8"</code> in the manifest. This
-ensures that the Android application cannot be installed in an environment in which it
-could not run properly. </li>
-</ul>
-
-<p>Here are excerpts from a manifest that supports GCM:</p>
-
-<pre class="prettyprint pretty-xml">
-<manifest package="com.example.gcm" ...>
-
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/>
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- <uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
-
- <permission android:name="com.example.gcm.permission.C2D_MESSAGE"
- android:protectionLevel="signature" />
- <uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
-
- <application ...>
- <receiver
- android:name=".MyBroadcastReceiver"
- android:permission="com.google.android.c2dm.permission.SEND" >
- <intent-filter>
- <action android:name="com.google.android.c2dm.intent.RECEIVE" />
- <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
- <category android:name="com.example.gcm" />
- </intent-filter>
- </receiver>
- <service android:name=".MyIntentService" />
- </application>
-
-</manifest>
-</pre>
-
-<h3 id="registering">Registering for GCM</h3>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
- <h2>Streamlined Registration</h2>
- <p>There is now a simpler alternative to registering and unregistering. Simply call the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
-This method registers the application for GCM and returns the registration ID. To unregister, call the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#unregister">{@code unregister()}</a> method (though you should rarely if ever need to unregister).</p>
-</div>
-</div>
-
-<p>An Android application needs to register with GCM servers before it can receive messages. To register, the application sends an Intent
-(<code>com.google.android.c2dm.intent.REGISTER</code>), with 2 extra parameters:
-</p>
-
-<ul>
- <li><code>sender</code> is the project number of the account authorized to send messages
-to the Android application. </li>
- <li><code>app</code> is the Android application's ID, set with a <code>PendingIntent</code> to
-allow the registration service to extract Android application information. </li>
-</ul>
-
-<p>For example:</p>
-
-<pre style="clear:right">Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
-// sets the app name in the intent
-registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
-registrationIntent.putExtra("sender", senderID);
-startService(registrationIntent);</pre>
-
-<p>This intent will be asynchronously sent to the GCM server, and the response will be delivered to
-the application as a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent containing
-the registration ID assigned to the Android application running on that particular device.</p>
-
-<p>Registration is not complete until the Android application sends the registration ID
-to the 3rd-party application server, which in turn will use the registration ID to send
-messages to the application.</p>
-
-<h3 id="unregistering">Unregistering from GCM</h3>
-
-<p>To unregister from GCM, do the following:</p>
-
-<pre class="prettyprint pretty-java">Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
-unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
-startService(unregIntent);
-</pre>
-
-<p>Similar to the registration request, this intent is sent asynchronously, and the response comes as a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent.
-
-
-<h3 id="handling_intents">Handling Intents sent by GCM</h3>
-
-<p>As discussed in <a href="#manifest">Creating the Manifest</a>, the manifest
-defines a broadcast receiver for the <code>com.google.android.c2dm.intent.REGISTRATION</code> and <code>com.google.android.c2dm.intent.RECEIVE</code> intents.
-These <a href="{@docRoot}guide/components/intents-filters.html">intents</a> are sent by GCM to indicate that a device was registered (or unregistered), or to deliver messages, respectively.</p>
-
-<p>Handling these intents might require I/O operations (such as network calls to the 3rd-party server), and
-such operations should not be done in the receiver's <code>onReceive()</code> method.
-You may be tempted to spawn a new thread directly, but there are no guarantees that the process will run long enough for the thread to finish the work.
-Thus the recommended way to handle the intents is to delegate them to a service, such as an {@link android.app.IntentService}.
-For example:</p>
-
-
-<pre class="prettyprint pretty-java">
-public class MyBroadcastReceiver extends BroadcastReceiver {
-
- @Override
- public final void onReceive(Context context, Intent intent) {
- MyIntentService.runIntentInService(context, intent);
- setResult(Activity.RESULT_OK, null, null);
- }
-}
-</pre>
-
-<p>Then in <code>MyIntentService</code>:</p>
-<pre class="prettyprint pretty-java">
-public class MyIntentService extends IntentService {
-
- private static PowerManager.WakeLock sWakeLock;
- private static final Object LOCK = MyIntentService.class;
-
- static void runIntentInService(Context context, Intent intent) {
- synchronized(LOCK) {
- if (sWakeLock == null) {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "my_wakelock");
- }
- }
- sWakeLock.acquire();
- intent.setClassName(context, MyIntentService.class.getName());
- context.startService(intent);
- }
-
- @Override
- public final void onHandleIntent(Intent intent) {
- try {
- String action = intent.getAction();
- if (action.equals("com.google.android.c2dm.intent.REGISTRATION")) {
- handleRegistration(intent);
- } else if (action.equals("com.google.android.c2dm.intent.RECEIVE")) {
- handleMessage(intent);
- }
- } finally {
- synchronized(LOCK) {
- sWakeLock.release();
- }
- }
- }
-}
-</pre>
-
-<p class="note"><strong>Note:</strong> your application must acquire a wake lock before starting the service—otherwise the device could be put to sleep before the service is started.</p>
-
-<h4 id="handling_reg">Handling Registration Results</h4>
-
-<p>When a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent is received, it could potentially contain 3 extras: <code>registration_id</code>, <code>error</code>, and <code>unregistered</code>.
-
-<p>When a registration succeeds, <code>registration_id</code> contains the registration ID and the other extras are not set.
-The application must ensure that the 3rd-party server receives the registration ID. It may do so by saving the registration ID and sending it to the server.
-If the network is down or there are errors, the application should retry sending the registration ID when the network is up again or the next time it starts.</p>
-
-<p class="note"><strong>Note:</strong> Although the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent is typically received after a request was made by the application,
-Google may periodically refresh the registration ID. So the application must be prepared to handle it at any time.</p>
-
-<p>When an unregistration succeeds, only the <code>unregistered</code> extra is set, and similar to the registration workflow,
-the application must contact the 3rd-party server to remove the registration ID (note that the registration ID is not available in the intent,
-but the application should have saved the registration ID when it got it).<p>
-
-<p>If the application request (be it register or unregister) fails, the <code>error</code> will be set with an error code, and the other extras will not be set.
-
-Here are the possible error codes:</p>
-
-<table>
- <tr>
- <th>Error Code</th>
- <th>Description</th>
- </tr>
- <tr>
- <td><code>SERVICE_NOT_AVAILABLE</code></td>
- <td>The device can't read the response, or there was a 500/503 from the
-server that can be retried later. The Android application should use exponential back-off and retry. See <a href="adv.html#retry">Advanced Topics</a> for more information. </td>
- </tr>
- <tr>
- <td><code>ACCOUNT_MISSING</code></td>
- <td>There is no Google account on the phone. The Android application should ask the
-user to open the account manager and add a Google account. Fix on the device
-side.</td>
- </tr>
- <tr>
- <td><code>AUTHENTICATION_FAILED</code></td>
- <td>Bad Google Account password. The Android application should ask the user to enter his/her Google Account
-password, and let the user retry manually later. Fix on the device side.</td>
- </tr>
- <tr>
- <td><code>INVALID_SENDER</code></td>
- <td>The sender account is not recognized. This must be fixed on the Android application side. The developer must fix the application to provide the right <code>sender</code> extra in the <code>com.google.android.c2dm.intent.REGISTER</code> intent.</td>
- </tr>
- <tr>
- <td><code>PHONE_REGISTRATION_ERROR</code></td>
- <td> Incorrect phone registration with Google. This
-phone doesn't currently support GCM.</td>
- </tr>
- <tr>
- <td><code>INVALID_PARAMETERS</code></td>
- <td>The request sent by the phone does not contain the expected parameters. This phone doesn't currently support GCM.</td>
- </tr>
-</table>
-
-
-
-
-<p>Here's an example on how to handle the registration in the <code>MyIntentService</code> example:</p>
-
-<pre class="prettyprint pretty-java">
-private void handleRegistration(Intent intent) {
- String registrationId = intent.getStringExtra("registration_id");
- String error = intent.getStringExtra("error");
- String unregistered = intent.getStringExtra("unregistered");
- // registration succeeded
- if (registrationId != null) {
- // store registration ID on shared preferences
- // notify 3rd-party server about the registered ID
- }
-
- // unregistration succeeded
- if (unregistered != null) {
- // get old registration ID from shared preferences
- // notify 3rd-party server about the unregistered ID
- }
-
- // last operation (registration or unregistration) returned an error;
- if (error != null) {
- if ("SERVICE_NOT_AVAILABLE".equals(error)) {
- // optionally retry using exponential back-off
- // (see <a href="adv.html#retry">Advanced Topics</a>)
- } else {
- // Unrecoverable error, log it
- Log.i(TAG, "Received error: " + error);
- }
- }
-}</pre>
-
-
-
-<h4 id="received_data">Handling Received Data</h4>
-
-<p>The <code>com.google.android.c2dm.intent.RECEIVE</code> intent is used by GCM to
-deliver the messages sent by the 3rd-party server to the application running in the device.
-If the server included key-pair values in the <code>data</code> parameter, they are available as
-extras in this intent, with the keys being the extra names. GCM also includes an extra called
-<code>from</code> which contains the sender ID as an string, and another called <code>collapse_key</code> containing the collapse key (when in use).
-
-<p>Here is an example, again using the <code>MyIntentReceiver</code> class:</p>
-
-<pre class="prettyprint pretty-java">
-private void handleMessage(Intent intent) {
- // server sent 2 key-value pairs, score and time
- String score = intent.getExtra("score");
- String time = intent.getExtra("time");
- // generates a system notification to display the score and time
-}</pre>
-
-<h3 id="testing">Developing and Testing Your Android Applications</h3>
-
-<p>Here are some guidelines for developing and testing an Android application
-that uses the GCM feature:</p>
-
-<ul>
- <li>To develop and test your Android applications, you need to run and debug the
-applications on an Android 2.2 system image that includes the necessary
-underlying Google services. </li>
- <li>To develop and debug on an actual device, you need a device running an
-Android 2.2 system image that includes the Google Play Store application. </li>
- <li>To develop and test on the Android Emulator, you need to download the
-Android 2.2 version of the Google APIs Add-On into your SDK using the <em>Android
-SDK and AVD Manager</em>. Specifically, you need to download the component named
-"Google APIs by Google Inc, Android API 8". Then, you need to set up
-an AVD that uses that system image. </li>
- <li>If the GCM feature is critical to the Android application's function, be sure to
-set <code>android:minSdkVersion="8"</code> in the manifest. This
-ensures that the Android application cannot be installed in an environment in which it
-could not run properly. </li>
-</ul>
-
<h2 id="server">Role of the 3rd-party Application Server</h2>
@@ -1105,6 +760,4 @@
</ol>
<p class="note"><strong>Note:</strong> Stats on the Google API Console are not enabled for GCM. You must use the <a href="http://play.google.com/apps/publish">Developer Console</a>.</p>
-<h2 id="example">Examples</h2>
-<p>See the <a href="demo.html">GCM Demo Application</a> document.</p>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index d938bd6..8ceea0cc 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -12,14 +12,14 @@
<li><a href="#create-proj">Creating a Google API Project</a></li>
<li><a href="#gcm-service">Enabling the GCM Service</a></li>
<li><a href="#access-key">Obtaining an API Key</a></li>
-<li><a href="#android-app">Writing the Android Application</a>
+<li><a href="#client">Writing a Client App</a></li>
+<li><a href="#server">Writing the Server Code</a></li>
</ol>
<h2>See Also</h2>
<ol class="toc">
<li><a href="https://code.google.com/apis/console">Google APIs Console page</a></li>
-<li><a href="{@docRoot}google/gcm/helper.html">Using the GCM Helper Libraries</a></li>
<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
</ol>
@@ -29,20 +29,9 @@
<p>The sections below guide you through the process of setting up a GCM
implementation.
Before you start, make sure to <a href="/google/play-services/setup.html">set up
-the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> methods. Strictly speaking, the only thing you absolutely need this API for is upstream (device-to-cloud) messaging, but it also offers a streamlined registration API that is recommended.</p>
+the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> methods.</p>
-
-<!--the basic steps are:
-
-<ul>
-<li>Creating a Google APIs Project</li>
-<li>Setting up GCM in your apps</li>
-<li>Integrating </li>
-
-<p>Note that a full GCM implementation requires a server-side implementation, in addition to the client implementation in your app. For complete information, make sure to read the <a href="/google/gcm/index.html">Google Cloud Messaging documentation</a>.
--->
-
-
+<p>Note that a full GCM implementation requires a server-side implementation, in addition to the client implementation in your app. This document offers a complete example that includes both the client and server.</p>
<h2 id="create-proj">Creating a Google API project</h2>
@@ -95,17 +84,21 @@
<p> Take note of the <strong>API key</strong> value (<code>YourKeyWillBeShownHere</code>) in this example, as it will be used later on.</p>
<p class="note"><strong>Note:</strong> If you need to rotate the key, click <strong>Generate new key</strong>. A new key will be created while the old one will still be active for up to 24 hours. If you want to get rid of the old key immediately (for example, if you feel it was compromised), click <strong>Delete key</strong>.</p>
+<p>The following sections walk you through the steps of creating client and server-side code.</p>
-<h2 id="android-app">Writing the Android Application</h2>
-<p>This section describes the steps involved in writing an Android application that uses GCM.</p>
+<h2 id="client">Writing a Client App</h2>
-<h4 id="manifest">Step 1: Make the following changes in the application's Android manifest</h4>
+<p>This section walks you through the steps involved in writing a client-side application—that is, the GCM-enabled application that runs on an Android device. This client sample is designed to work in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>, below.</p>
+
+
+
+<h3 id="manifest">Step 1: Edit Your App's Manifest</h3>
<ul>
<li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
<li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd party server.</li>
<li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
<li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional—use only if the app wants to keep the device from sleeping.</li>
- <li>An <code>applicationPackage + ".permission.C2D_MESSAGE</code> permission to prevent other Android applications from registering and receiving the Android application's
+ <li>An <code>applicationPackage + ".permission.C2D_MESSAGE"</code> permission to prevent other Android applications from registering and receiving the Android application's
messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.</li>
<li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code>, with the category set
as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
@@ -149,106 +142,199 @@
</pre>
-<h4>Step 2: Register for GCM</h4>
+<h3 id="register">Step 2: Register for GCM</h3>
<p>An Android application running on a mobile device registers to receive messages by calling
the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous
-GCM registration process.</p>
+GCM registration process. See the example below for details.</p>
-<h4> Step 3: Write your application</h4>
+<h3 id="app"> Step 3: Write Your Application</h3>
<p>Finally, write your application. GCM offers a variety of ways to get the job done:</p>
<ul>
- <li>For your messaging server, you can either use the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), the older <a href="gcm.html">GCM HTTP server</a>, or both in tandem.</li>
- <li>To write your client application, you can use any of the following:
- <ul>
- <li>The helper libraries, which are described in the <a href="{@docRoot}google/gcm/demo.html">Demo App Tutorial</a> and <a href="{@docRoot}google/gcm/helper.html">Using the GCM Helper Libraries</a>.</li>
- <li>The approach described in the <a href="{@docRoot}google/gcm/gcm.html#writing_apps">GCM Architectural Overview</a>.</li>
- <li>Regardless, you must use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs if you are doing upstream (device-to-cloud) messaging. Even if you are not doing upstream messaging, we recommend that you use this API to take advantage of the streamlined registration process—described above and shown in the following sample.</li>
+ <li>For your messaging server, you can either use the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), the older <a href="gcm.html">GCM HTTP server</a>, or both in tandem. For more discussion, see see <a href="server.html">GCM Server</a>.</li>
+ <li>To write your client application (that is, the GCM-enabled app that runs on an Android device), use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs as shown below. Don't forget to set up your project to use the Google Play services SDK as described in <a href="/google/play-services/setup.html">Setup Google Play Services SDK</a>.</li>
</ul>
</li>
</ul>
-<h5 id="gs_example">Example</h5>
+<h4 id="example">Example</h4>
-<p>Here is a sample application that illustrates how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. In this example, the sender is a <a href="{@docRoot}google/gcm/ccs.html">CCS</a> echo server. The sample consists of a main Activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}).</p>
+<p>Here is a sample client application that illustrates how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}). You can use this client sample code in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>.</p>
+<p>Note the following:</p>
+
+<ul>
+ <li>The sample primarily illustrates two things: registration, and upstream messaging. Upstream messaging only applies to apps that are running against a <a href="ccs.html">CCS</a> server; HTTP-based servers don't support upstream messaging.</li>
+ <li>The <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs replace the old registration process, which was based on the now-obsolete client helper library. While the old registration process still works, we encourage you to use the newer <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs, regardless of your underlying server.</li>
+</ul>
+
+<h5>Registering</h5>
<p>An Android application needs to register with GCM servers before it can receive messages. So in its {@code onCreate()} method, {@code DemoActivity} checks to see whether the app is registered with GCM and with the server:</p>
-<pre>public class DemoActivity extends Activity {
+<pre>/**
+ * Main UI for the demo app.
+ */
+public class DemoActivity extends Activity {
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
+ private static final String PROPERTY_APP_VERSION = "appVersion";
+ private static final String PROPERTY_ON_SERVER_EXPIRATION_TIME =
+ "onServerExpirationTimeMs";
/**
- * You can use your own project ID instead. This sender is a test CCS
- * echo server.
+ * Default lifespan (7 days) of a reservation until it is considered expired.
*/
- String GCM_SENDER_ID = "Your-Sender-ID";
+ public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7;
- // Tag for log messages.
+ /**
+ * Substitute you own sender ID here.
+ */
+ String SENDER_ID = "Your-Sender-ID";
+
+ /**
+ * Tag used on log messages.
+ */
static final String TAG = "GCMDemo";
TextView mDisplay;
GoogleCloudMessaging gcm;
AtomicInteger msgId = new AtomicInteger();
SharedPreferences prefs;
+ Context context;
+
String regid;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Make sure the app is registered with GCM and with the server
- prefs = getSharedPreferences(DemoActivity.class.getSimpleName(),
- Context.MODE_PRIVATE);
setContentView(R.layout.main);
-
mDisplay = (TextView) findViewById(R.id.display);
- regid = prefs.getString(PROPERTY_REG_ID, null);
-
- // If there is no registration ID, the app isn't registered.
- // Call registerBackground() to register it.
- if (regid == null) {
+ context = getApplicationContext();
+ regid = getRegistrationId(context);
+
+ if (regid.length() == 0) {
registerBackground();
}
-
gcm = GoogleCloudMessaging.getInstance(this);
- }</pre>
+ }
+...
+}</pre>
-<p>If the app isn't registered, {@code DemoActivity} calls the following {@code registerBackground()} method to register it. Note that because GCM methods are blocking, this has to take place on a background thread. This sample uses {@link android.os.AsyncTask} to accomplish this:</p>
+<p>The app calls {@code getRegistrationId()} to see whether there is an existing registration ID stored in shared preferences:</p>
-<pre>private void registerBackground() {
+<pre>/**
+ * Gets the current registration id for application on GCM service.
+ * <p>
+ * If result is empty, the registration has failed.
+ *
+ * @return registration id, or empty string if the registration is not
+ * complete.
+ */
+private String getRegistrationId(Context context) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ String registrationId = prefs.getString(PROPERTY_REG_ID, "");
+ if (registrationId.length() == 0) {
+ Log.v(TAG, "Registration not found.");
+ return "";
+ }
+ // check if app was updated; if so, it must clear registration id to
+ // avoid a race condition if GCM sends a message
+ int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
+ int currentVersion = getAppVersion(context);
+ if (registeredVersion != currentVersion || isRegistrationExpired()) {
+ Log.v(TAG, "App version changed or registration expired.");
+ return "";
+ }
+ return registrationId;
+}
+
+...
+
+/**
+ * @return Application's {@code SharedPreferences}.
+ */
+private SharedPreferences getGCMPreferences(Context context) {
+ return getSharedPreferences(DemoActivity.class.getSimpleName(),
+ Context.MODE_PRIVATE);
+}</pre>
+
+<p>If the registration ID doesn't exist, or the app was updated, or the registration ID has expired, {@code getRegistrationId()} returns an empty string to indicate that the app needs to get a new regID. {@code getRegistrationId()} calls the following methods to check the app version and whether the regID has expired:</p>
+
+<pre>/**
+ * @return Application's version code from the {@code PackageManager}.
+ */
+private static int getAppVersion(Context context) {
+ try {
+ PackageInfo packageInfo = context.getPackageManager()
+ .getPackageInfo(context.getPackageName(), 0);
+ return packageInfo.versionCode;
+ } catch (NameNotFoundException e) {
+ // should never happen
+ throw new RuntimeException("Could not get package name: " + e);
+ }
+}
+
+/**
+ * Checks if the registration has expired.
+ *
+ * <p>To avoid the scenario where the device sends the registration to the
+ * server but the server loses it, the app developer may choose to re-register
+ * after REGISTRATION_EXPIRY_TIME_MS.
+ *
+ * @return true if the registration has expired.
+ */
+private boolean isRegistrationExpired() {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ // checks if the information is not stale
+ long expirationTime =
+ prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
+ return System.currentTimeMillis() > expirationTime;
+}</pre>
+
+
+<p>If there isn't a valid existing registration ID, {@code DemoActivity} calls the following {@code registerBackground()} method to register. Note that because GCM methods are blocking, this has to take place on a background thread. This sample uses {@link android.os.AsyncTask} to accomplish this:</p>
+
+<pre>
+/**
+ * Registers the application with GCM servers asynchronously.
+ * <p>
+ * Stores the registration id, app versionCode, and expiration time in the
+ * application's shared preferences.
+ */
+private void registerBackground() {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
String msg = "";
try {
- regid = gcm.register(GCM_SENDER_ID);
+ if (gcm == null) {
+ gcm = GoogleCloudMessaging.getInstance(context);
+ }
+ regid = gcm.register(SENDER_ID);
msg = "Device registered, registration id=" + regid;
- // You should send the registration ID to your server over HTTP,
+ // You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
- // For this demo: we don't need to send it because the device
- // will send upstream messages to a server that will echo back
- // the message using the 'from' address in the message.
-
- // Save the regid for future use - no need to register again.
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(PROPERTY_REG_ID, regid);
- editor.commit();
+ // For this demo: we don't need to send it because the device
+ // will send upstream messages to a server that echo back the message
+ // using the 'from' address in the message.
+
+ // Save the regid - no need to register again.
+ setRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
- // Once registration is done, display the registration status
- // string in the Activity's UI.
+
@Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
@@ -256,7 +342,33 @@
}.execute(null, null, null);
}</pre>
-<p>When the user clicks the app's <strong>Echo</strong> button, the app generates the necessary XMPP stanza for the message, which it sends to the echo server:</p>
+<p>After registering, the app calls {@code setRegistrationId()} to store the registration ID in shared preferences for future use:</p>
+
+<pre>/**
+ * Stores the registration id, app versionCode, and expiration time in the
+ * application's {@code SharedPreferences}.
+ *
+ * @param context application's context.
+ * @param regId registration id
+ */
+private void setRegistrationId(Context context, String regId) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ int appVersion = getAppVersion(context);
+ Log.v(TAG, "Saving regId on app version " + appVersion);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PROPERTY_REG_ID, regId);
+ editor.putInt(PROPERTY_APP_VERSION, appVersion);
+ long expirationTime = System.currentTimeMillis() + REGISTRATION_EXPIRY_TIME_MS;
+
+ Log.v(TAG, "Setting registration expiry time to " +
+ new Timestamp(expirationTime));
+ editor.putLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, expirationTime);
+ editor.commit();
+}</pre>
+
+<h5>Sending a message</h5>
+<p>When the user clicks the app's <strong>Send</strong> button, the app sends an upstream message using the new <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message, your server should be connected to CCS. You can use the code shown in <a href="#server">Writing the Server Code</a> as a sample XMPP client to connect to CCS.</p>
+
<pre>public void onClick(final View view) {
if (view == findViewById(R.id.send)) {
new AsyncTask<Void, Void, String>() {
@@ -265,11 +377,10 @@
String msg = "";
try {
Bundle data = new Bundle();
- // data is a key-value pair.
- data.putString("hello", "world");
+ data.putString("hello", "World");
String id = Integer.toString(msgId.incrementAndGet());
- gcm.send(GCM_SENDER_ID + "@gcm.googleapis.com", id, data);
- msg = "Sending message";
+ gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);
+ msg = "Sent message";
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
@@ -278,23 +389,25 @@
@Override
protected void onPostExecute(String msg) {
- // Displays the text "Sending message"
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
- }
+ } else if (view == findViewById(R.id.clear)) {
+ mDisplay.setText("");
+ }
}</pre>
<p>As described above in <a href="#manifest">Step 1</a>, the app includes a broadcast receiver for the <code>com.google.android.c2dm.intent.RECEIVE</code> intent. This is the mechanism GCM uses to deliver messages. When {@code onClick()} calls {@code gcm.send()}, it triggers the broadcast receiver's {@code onReceive()} method, which has the responsibility of handling the GCM message. In this sample the receiver's {@code onReceive()} method calls {@code sendNotification()} to put the message into a notification:</p>
-<pre>public class GcmBroadcastReceiver extends BroadcastReceiver {
+<pre>/**
+ * Handling of GCM messages.
+ */
+public class GcmBroadcastReceiver extends BroadcastReceiver {
static final String TAG = "GCMDemo";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
-
-
@Override
public void onReceive(Context context, Intent intent) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
@@ -303,7 +416,7 @@
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
- sendNotification("Deleted messages on server: " +
+ sendNotification("Deleted messages on server: " +
intent.getExtras().toString());
} else {
sendNotification("Received: " + intent.getExtras().toString());
@@ -313,21 +426,98 @@
// Put the GCM message into a notification and post it.
private void sendNotification(String msg) {
- mNotificationManager = (NotificationManager)
- ctx.getSystemService(Context.NOTIFICATION_SERVICE);
-
- PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
- new Intent(ctx, DemoActivity.class), 0);
-
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(ctx)
- .setSmallIcon(R.drawable.ic_stat_notification)
- .setContentTitle("GCM Notification")
- .setStyle(new NotificationCompat.BigTextStyle()
- .bigText(msg))
- .setContentText(msg);
-
- mBuilder.setContentIntent(contentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
+ mNotificationManager = (NotificationManager)
+ ctx.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
+ new Intent(ctx, DemoActivity.class), 0);
+
+ NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(ctx)
+ .setSmallIcon(R.drawable.ic_stat_gcm)
+ .setContentTitle("GCM Notification")
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(msg))
+ .setContentText(msg);
+
+ mBuilder.setContentIntent(contentIntent);
+ mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}</pre>
+
+<h2 id="server">Writing the Server Code</h2>
+
+<p>Here is an example of a CCS server written in Python. You can use this in conjunction with the sample client code shown above. This sample echo server sends an initial message, and for every upstream message received, it sends a dummy response back to the application that sent the upstream message. This example illustrates how to connect,
+send, and receive GCM messages using XMPP. It shouldn't be used as-is
+on a production deployment. For examples of HTTP-based servers, see <a href="server.html">GCM Server</a>.</p>
+
+<pre>
+#!/usr/bin/python
+import sys, json, xmpp, random, string
+
+SERVER = 'gcm.googleapis.com'
+PORT = 5235
+USERNAME = ''
+PASSWORD = ''
+REGISTRATION_ID = ''
+
+unacked_messages_quota = 1000
+send_queue = []
+
+# Return a random alphanumerical id
+def random_id():
+ rid = ''
+ for x in range(8): rid += random.choice(string.ascii_letters + string.digits)
+ return rid
+
+def message_callback(session, message):
+ global unacked_messages_quota
+ gcm = message.getTags('gcm')
+ if gcm:
+ gcm_json = gcm[0].getData()
+ msg = json.loads(gcm_json)
+ if not msg.has_key('message_type'):
+ # Acknowledge the incoming message immediately.
+ send({'to': msg['from'],
+ 'message_type': 'ack',
+ 'message_id': msg['message_id']})
+ # Queue a response back to the server.
+ if msg.has_key('from'):
+ # Send a dummy echo response back to the app that sent the upstream message.
+ send_queue.append({'to': msg['from'],
+ 'message_id': random_id(),
+ 'data': {'pong': 1}})
+ elif msg['message_type'] == 'ack' or msg['message_type'] == 'nack':
+ unacked_messages_quota += 1
+
+def send(json_dict):
+ template = ("<message><gcm xmlns='google:mobile:data'>{1}</gcm></message>")
+ client.send(xmpp.protocol.Message(
+ node=template.format(client.Bind.bound[0], json.dumps(json_dict))))
+
+def flush_queued_messages():
+ global unacked_messages_quota
+ while len(send_queue) and unacked_messages_quota > 0:
+ send(send_queue.pop(0))
+ unacked_messages_quota -= 1
+
+client = xmpp.Client('gcm.googleapis.com', debug=['socket'])
+client.connect(server=(SERVER,PORT), secure=1, use_srv=False)
+auth = client.auth(USERNAME, PASSWORD)
+if not auth:
+ print 'Authentication failed!'
+ sys.exit(1)
+
+client.RegisterHandler('message', message_callback)
+
+send_queue.append({'to': REGISTRATION_ID,
+ 'message_id': 'reg_id',
+ 'data': {'message_destination': 'RegId',
+ 'message_id': random_id()}})
+
+while True:
+ client.Process(1)
+ flush_queued_messages()</pre>
+
+
+
diff --git a/docs/html/google/gcm/helper.jd b/docs/html/google/gcm/helper.jd
index bde2df0..e7f2f73 100644
--- a/docs/html/google/gcm/helper.jd
+++ b/docs/html/google/gcm/helper.jd
@@ -2,6 +2,23 @@
page.tags="cloud","push","messaging"
@jd:body
+<div id="deprecatedSticker">
+ <a href="#"
+ onclick="$('#naMessage').show();$('#deprecatedSticker').hide();return false">
+ <strong>This doc is deprecated</strong></a>
+</div>
+
+
+<div id="naMessage" style="display:block">
+<div><p><strong>The information in this document has been superseded by <a href="server.html">GCM Server</a> and <a href="client.html">GCM Client</a></strong>. Please use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> API instead of the GCM client helper library. The GCM server helper library is still valid.</p>
+
+ <input style="margin-top:1em;padding:5px" type="button"
+ value="That's nice, but I still want to read this document"
+onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
+</div>
+</div>
+
+
<div id="qv-wrapper">
<div id="qv">
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index aeba86f..8f325b8 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -49,6 +49,9 @@
<h4>Seamless multi-device messaging</h4>
<p>Maps a single user to a notification key, which you can then use to send a single message to multiple devices owned by the user. Use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for User Notifications. <a href="{@docRoot}google/gcm/notifications.html">Learn more »</a></p>
+
+ <h4>Get Started</h4>
+ <p>Get started using the new features with a tutorial that walks you through creating a GCM app. <a href="{@docRoot}google/gcm/gs.html">Learn more »</a></p>
</div>
</div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 6a4b34a..df171cf 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -52,6 +52,9 @@
<p>The way this works is that during registration, the 3rd-party server requests a {@code notification_key}. The {@code notification_key} maps a particular user to all of the user's associated registration IDs (a regID represents a particular Android application running on a particular device). Then instead of sending one message to one regID at a time, the 3rd-party server can send a message to to the {@code notification_key}, which then sends the message to all of the user's regIDs.</p>
+<p class="note"><strong>Note:</strong> A notification dismissal message is like any other upstream message, meaning that it will be delivered to the other devices that belong to the specified {@code notification_key}. You should design your app to handle cases where the app receives a dismissal message, but has not yet displayed the notification that is being dismissed. You can solve this by caching the dismissal and then reconciling it with the corresponding notification.
+</p>
+
<p>You can use this feature with either the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), or the older <a href="gcm.html">GCM HTTP server</a>.</p>
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
new file mode 100644
index 0000000..92a1531
--- /dev/null
+++ b/docs/html/google/gcm/server.jd
@@ -0,0 +1,160 @@
+page.title=GCM Server
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Quickview</h2>
+
+<ul>
+<li>Understand how to set up the server side of a GCM app.</li>
+<li>Become familiar with the <a href="{@docRoot}reference/com/google/android/gcm/server/package-summary.html">GCM server helper library</a>.</li>
+</ul>
+
+
+<h2>In this document</h2>
+
+<ol>
+ <li><a href="#requirements">Requirements</a> </li>
+ <li><a href="#gcm-setup">Setting Up GCM</a></li>
+ <li><a href="#server-setup">Setting Up an HTTP Server</a>
+ <ol>
+ <li><a href="#webserver-setup">Using a standard web server</a></li>
+ <li><a href="#appengine-setup">Using App Engine for Java</a></li>
+ </ol>
+ </li>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="gs.html">Getting Started</a></li>
+<li><a href="client.html">GCM Client</a></li>
+<li><a href="ccs.html">Cloud Connection Server</a></li>
+
+
+</ol>
+
+</div>
+</div>
+
+
+
+
+<p>This document gives examples of GCM server-side code for HTTP. For an example of an XMPP server (<a href="ccs.html">Cloud Connection Server</a>), see <a href="gs.html#server">Getting Started</a>. Note that a full GCM implementation requires a client-side implementation, in addition to the server. For a complete working example that includes client and server-side code, see <a href="gs.html">Getting Started</a>.</a>
+
+<h2 id="requirements">Requirements</h2>
+<p>For the web server:</p>
+<ul>
+ <li> <a href="http://ant.apache.org/">Ant 1.8</a> (it might work with earlier versions, but it's not guaranteed).</li>
+ <li>One of the following:
+ <ul>
+ <li>A running web server compatible with Servlets API version 2.5, such as <a href="http://tomcat.apache.org/">Tomcat 6</a> or <a href="http://jetty.codehaus.org/">Jetty</a>, or</li>
+ <li><a href="http://code.google.com/appengine/">Java App Engine SDK</a> version 1.6 or later.</li>
+ </ul>
+ </li>
+ <li>A Google account registered to use GCM.</li>
+ <li>The API key for that account.</li>
+</ul>
+<p>For the Android application:</p>
+<ul>
+ <li>Emulator (or device) running Android 2.2 with Google APIs.</li>
+ <li>The Google API project number of the account registered to use GCM.</li>
+</ul>
+<h2 id="gcm-setup">Setting Up GCM</h2>
+<p>Before proceeding with the server and client setup, it's necessary to register a Google account with the Google API Console, enable Google Cloud Messaging in GCM, and obtain an API key from the <a href="https://code.google.com/apis/console">Google API Console</a>.</p>
+<p>For instructions on how to set up GCM, see <a href="gs.html">Getting Started</a>.</p>
+
+
+<h2 id="server-setup">Setting Up an HTTP Server</h2>
+<p>This section describes the different options for setting up an HTTP server.</p>
+<h3 id="webserver-setup">Using a standard web server</h3>
+<p>To set up the server using a standard, servlet-compliant web server:</p>
+<ol>
+ <li>From the <a href="http://code.google.com/p/gcm">open source site</a>, download the following directories: <code>gcm-server</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
+
+
+ <li>In a text editor, edit the <code>samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
+ <li>In a shell window, go to the <code>samples/gcm-demo-server</code> directory.</li>
+ <li>Generate the server's WAR file by running <code>ant war</code>:</li>
+
+ <pre class="prettyprint">$ ant war
+
+Buildfile:build.xml
+
+init:
+ [mkdir] Created dir: build/classes
+ [mkdir] Created dir: dist
+
+compile:
+ [javac] Compiling 6 source files to build/classes
+
+war:
+ [war] Building war: <strong>dist/gcm-demo.war</strong>
+
+BUILD SUCCESSFUL
+Total time: 0 seconds
+</pre>
+
+ <li>Deploy the <code>dist/gcm-demo.war</code> to your running server. For instance, if you're using Jetty, copy <code>gcm-demo.war</code> to the <code>webapps</code> directory of the Jetty installation.</li>
+ <li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/gcm-demo/home</code>, where <code>gcm-demo</code> is the application context and <code>/home</code> is the path of the main servlet.
+
+ </li>
+</ol>
+<p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows. </p>
+
+<p> You server is now ready.</p>
+
+<h3 id="appengine-setup">Using App Engine for Java</h3>
+
+<p>To set up the server using a standard App Engine for Java:</p>
+<ol>
+ <li>Get the files from the <a href="http://code.google.com/p/gcm">open source site</a>, as described above.</p>
+ </li>
+ <li>In a text editor, edit <code>samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code> and replace the existing text with the API key obtained above.
+
+ <p class="note"><strong>Note:</strong> The API key value set in that class will be used just once to create a persistent entity on App Engine. If you deploy the application, you can use App Engine's <code>Datastore Viewer</code> to change it later.</p>
+
+ </li>
+ <li>In a shell window, go to the <code>samples/gcm-demo-appengine</code> directory.</li>
+ <li>Start the development App Engine server by <code>ant runserver</code>, using the <code>-Dsdk.dir</code> to indicate the location of the App Engine SDK and <code>-Dserver.host</code> to set your server's hostname or IP address:</li>
+
+<pre class="prettyprint">
+$ ant -Dsdk.dir=/opt/google/appengine-java-sdk runserver -Dserver.host=192.168.1.10
+Buildfile: gcm-demo-appengine/build.xml
+
+init:
+ [mkdir] Created dir: gcm-demo-appengine/dist
+
+copyjars:
+
+compile:
+
+datanucleusenhance:
+ [enhance] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
+ [enhance] DataNucleus Enhancer completed with success for 0 classes. Timings : input=28 ms, enhance=0 ms, total=28 ms. Consult the log for full details
+ [enhance] DataNucleus Enhancer completed and no classes were enhanced. Consult the log for full details
+
+runserver:
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.jetty.JettyLogger info
+ [java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
+ [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/appengine-web.xml
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
+ [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/web.xml
+ [java] Jun 15, 2012 8:46:09 PM com.google.android.gcm.demo.server.ApiKeyInitializer contextInitialized
+ [java] SEVERE: Created fake key. Please go to App Engine admin console, change its value to your API Key (the entity type is 'Settings' and its field to be changed is 'ApiKey'), then restart the server!
+ [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
+ [java] INFO: The server is running at http://192.168.1.10:8080/
+ [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
+ [java] INFO: The admin console is running at http://192.168.1.10:8080/_ah/admin
+</pre>
+
+ <li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/home</code>, where <code>/home</code> is the path of the main servlet.</li>
+
+ <p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows.</p>
+
+</ol>
+<p> You server is now ready.</p>
+
+
diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs
index 13d3eb3..891819b 100644
--- a/docs/html/google/google_toc.cs
+++ b/docs/html/google/google_toc.cs
@@ -132,11 +132,11 @@
<li><a href="<?cs var:toroot?>google/gcm/notifications.html">
<span class="en">User Notifications</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/gcm/demo.html">
- <span class="en">Demo App Tutorial</span></a>
+ <li><a href="<?cs var:toroot?>google/gcm/client.html">
+ <span class="en">GCM Client</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/gcm/helper.html">
- <span class="en">Using the Helper Libraries</span></a>
+ <li><a href="<?cs var:toroot?>google/gcm/server.html">
+ <span class="en">GCM Server</span></a>
</li>
<li><a href="<?cs var:toroot?>google/gcm/adv.html">
<span class="en">Advanced Topics</span></a>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 5f9f530..16dca9d 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -326,11 +326,11 @@
</a></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html">
- <span class="en">Renderscript</span></a>
+ <span class="en">RenderScript</span></a>
</li>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/advanced.html">
- <span class="en">Advanced Renderscript</span></a>
+ <span class="en">Advanced RenderScript</span></a>
</li>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/reference.html">
<span class="en">Runtime API Reference</span></a>
diff --git a/docs/html/guide/topics/renderscript/advanced.jd b/docs/html/guide/topics/renderscript/advanced.jd
index 58f5e1f..6a72b97 100644
--- a/docs/html/guide/topics/renderscript/advanced.jd
+++ b/docs/html/guide/topics/renderscript/advanced.jd
@@ -1,4 +1,4 @@
-page.title=Advanced Renderscript
+page.title=Advanced RenderScript
parent.title=Computation
parent.link=index.html
@@ -9,7 +9,7 @@
<h2>In this document</h2>
<ol>
- <li><a href="#native">Renderscript Runtime Layer</a></li>
+ <li><a href="#native">RenderScript Runtime Layer</a></li>
<li><a href="#reflected">Reflected Layer</a>
<ol>
<li><a href="#func">Functions</a></li>
@@ -25,7 +25,7 @@
<li>
<a href="#memory">Working with Memory</a>
<ol>
- <li><a href="#allocating-mem">Allocating and binding memory to the Renderscript</a></li>
+ <li><a href="#allocating-mem">Allocating and binding memory to the RenderScript</a></li>
<li><a href="#read-write">Reading and writing to memory</a></li>
@@ -37,36 +37,36 @@
<p></p>
- <p>Because applications that utilize Renderscript still run inside of the Android VM,
+ <p>Because applications that utilize RenderScript still run inside of the Android VM,
you have access to all of the framework APIs that you are familiar with, but can
- utilize Renderscript when appropriate. To facilitate this interaction between
- the framework and the Renderscript runtime, an intermediate layer of code is also
+ utilize RenderScript when appropriate. To facilitate this interaction between
+ the framework and the RenderScript runtime, an intermediate layer of code is also
present to facilitate communication and memory management between the two levels of code.
This document goes into more detail about these
different layers of code as well as how memory is shared between the Android VM and
- Renderscript runtime.</p>
+ RenderScript runtime.</p>
- <h2 id="native">Renderscript Runtime Layer</h2>
+ <h2 id="native">RenderScript Runtime Layer</h2>
- <p>Your Renderscript code is compiled and
- executed in a compact and well-defined runtime layer. The Renderscript runtime APIs offer support for
+ <p>Your RenderScript code is compiled and
+ executed in a compact and well-defined runtime layer. The RenderScript runtime APIs offer support for
intensive computation that is portable and automatically scalable to the
amount of cores available on a processor.
</p>
<p class="note"><strong>Note:</strong> The standard C functions in the NDK must be
- guaranteed to run on a CPU, so Renderscript cannot access these libraries,
- because Renderscript is designed to run on different types of processors.</p>
+ guaranteed to run on a CPU, so RenderScript cannot access these libraries,
+ because RenderScript is designed to run on different types of processors.</p>
-<p>You define your Renderscript code in <code>.rs</code>
+<p>You define your RenderScript code in <code>.rs</code>
and <code>.rsh</code> files in the <code>src/</code> directory of your Android project. The code
is compiled to intermediate bytecode by the
<code>llvm</code> compiler that runs as part of an Android build. When your application
runs on a device, the bytecode is then compiled (just-in-time) to machine code by another
<code>llvm</code> compiler that resides on the device. The machine code is optimized for the
- device and also cached, so subsequent uses of the Renderscript enabled application does not
+ device and also cached, so subsequent uses of the RenderScript enabled application does not
recompile the bytecode.</p>
- <p>Some key features of the Renderscript runtime libraries include:</p>
+ <p>Some key features of the RenderScript runtime libraries include:</p>
<ul>
@@ -79,20 +79,20 @@
<li>Conversion routines for primitive data types and vectors, matrix routines, and date and time
routines</li>
- <li>Data types and structures to support the Renderscript system such as Vector types for
+ <li>Data types and structures to support the RenderScript system such as Vector types for
defining two-, three-, or four-vectors.</li>
<li>Logging functions</li>
</ul>
- <p>See the Renderscript runtime API reference for more information on the available functions.
+ <p>See the RenderScript runtime API reference for more information on the available functions.
<h2 id="reflected">Reflected Layer</h2>
<p>The reflected layer is a set of classes that the Android build tools generate to allow access
- to the Renderscript runtime from the Android framework. This layer also provides methods
+ to the RenderScript runtime from the Android framework. This layer also provides methods
and constructors that allow you to allocate and work with memory for pointers that are defined in
-your Renderscript code. The following list describes the major
+your RenderScript code. The following list describes the major
components that are reflected:</p>
<ul>
@@ -105,9 +105,9 @@
<ul>
<li>Non-static functions</li>
- <li>Non-static, global Renderscript variables. Accessor methods are generated for each
- variable, so you can read and write the Renderscript variables from the Android
- framework. If a global variable is initialized at the Renderscript runtime layer, those
+ <li>Non-static, global RenderScript variables. Accessor methods are generated for each
+ variable, so you can read and write the RenderScript variables from the Android
+ framework. If a global variable is initialized at the RenderScript runtime layer, those
values are used to initialize the corresponding values in the Android framework layer. If global
variables are marked as <code>const</code>, then a <code>set</code> method is not
generated.</p></li>
@@ -128,7 +128,7 @@
<h3 id="func">Functions</h3>
<p>Functions are reflected into the script class itself, located in
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. For
-example, if you declare the following function in your Renderscript code:</p>
+example, if you declare the following function in your RenderScript code:</p>
<pre>
void touch(float x, float y, float pressure, int id) {
@@ -155,14 +155,14 @@
}
</pre>
<p>
-Functions cannot have a return value, because the Renderscript system is designed to be
-asynchronous. When your Android framework code calls into Renderscript, the call is queued and is
-executed when possible. This restriction allows the Renderscript system to function without constant
+Functions cannot have a return value, because the RenderScript system is designed to be
+asynchronous. When your Android framework code calls into RenderScript, the call is queued and is
+executed when possible. This restriction allows the RenderScript system to function without constant
interruption and increases efficiency. If functions were allowed to have return values, the call
would block until the value was returned.</p>
<p>
-If you want the Renderscript code to send a value back to the Android framework, use the
+If you want the RenderScript code to send a value back to the Android framework, use the
<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a>
function.
</p>
@@ -172,7 +172,7 @@
<p>Variables of supported types are reflected into the script class itself, located in
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. A set of accessor
methods are generated for each variable. For example, if you declare the following variable in
-your Renderscript code:</p>
+your RenderScript code:</p>
<pre>uint32_t unsignedInteger = 1;</pre>
<p>then the following code is generated:</p>
@@ -329,7 +329,7 @@
</pre>
<p>The generated code is provided to you as a convenience to allocate memory for structs requested
-by the Renderscript runtime and to interact with <code>struct</code>s
+by the RenderScript runtime and to interact with <code>struct</code>s
in memory. Each <code>struct</code>'s class defines the following methods and constructors:</p>
<ul>
@@ -356,11 +356,11 @@
</ul>
<p>You can specify multiple memory spaces by using the bitwise <code>OR</code> operator. Doing so
- notifies the Renderscript runtime that you intend on accessing the data in the
+ notifies the RenderScript runtime that you intend on accessing the data in the
specified memory spaces. The following example allocates memory for a custom data type
in both the script and vertex memory spaces:</p>
<pre>
- ScriptField_Point touchPoints = new ScriptField_Point(myRenderscript, 2,
+ ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2,
Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_VERTEX);
</pre>
</li>
@@ -370,13 +370,13 @@
with the <code>struct</code> in your Android code. When you are done manipulating the object,
you can push the object to the allocated memory by calling <code>set(Item i, int index,
boolean copyNow)</code> and setting the <code>Item</code> to the desired position in
-the array. The Renderscript runtime automatically has access to the newly written memory.
+the array. The RenderScript runtime automatically has access to the newly written memory.
<li>Accessor methods to get and set the values of each field in a struct. Each of these
accessor methods have an <code>index</code> parameter to specify the <code>struct</code> in
the array that you want to read or write to. Each setter method also has a
<code>copyNow</code> parameter that specifies whether or not to immediately sync this memory
-to the Renderscript runtime. To sync any memory that has not been synced, call
+to the RenderScript runtime. To sync any memory that has not been synced, call
<code>copyAll()</code>.</li>
<li>The <code>createElement()</code> method creates a description of the struct in memory. This
@@ -387,7 +387,7 @@
created.</li>
<li><code>copyAll()</code> synchronizes memory that was set on the framework level to the
-Renderscript runtime. When you call a set accessor method on a member, there is an optional
+RenderScript runtime. When you call a set accessor method on a member, there is an optional
<code>copyNow</code> boolean parameter that you can specify. Specifying
<code>true</code> synchronizes the memory when you call the method. If you specify false,
you can call <code>copyAll()</code> once, and it synchronizes memory for all the
@@ -397,7 +397,7 @@
<h3 id="pointer">Pointers</h3>
<p>Pointers are reflected into the script class itself, located in
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. You
-can declare pointers to a <code>struct</code> or any of the supported Renderscript types, but a
+can declare pointers to a <code>struct</code> or any of the supported RenderScript types, but a
<code>struct</code> cannot contain pointers or nested arrays. For example, if you declare the
following pointers to a <code>struct</code> and <code>int32_t</code></p>
@@ -438,7 +438,7 @@
<p>A <code>get</code> method and a special method named <code>bind_<em>pointer_name</em></code>
(instead of a <code>set()</code> method) is generated. This method allows you to bind the memory
-that is allocated in the Android VM to the Renderscript runtime (you cannot allocate
+that is allocated in the Android VM to the RenderScript runtime (you cannot allocate
memory in your <code>.rs</code> file). For more information, see <a href="#memory">Working
with Allocated Memory</a>.
</p>
@@ -446,14 +446,14 @@
<h2 id="mem-allocation">Memory Allocation APIs</h2>
- <p>Applications that use Renderscript still run in the Android VM. The actual Renderscript code, however, runs natively and
+ <p>Applications that use RenderScript still run in the Android VM. The actual RenderScript code, however, runs natively and
needs access to the memory allocated in the Android VM. To accomplish this, you must
- attach the memory that is allocated in the VM to the Renderscript runtime. This
-process, called binding, allows the Renderscript runtime to seamlessly work with memory that it
+ attach the memory that is allocated in the VM to the RenderScript runtime. This
+process, called binding, allows the RenderScript runtime to seamlessly work with memory that it
requests but cannot explicitly allocate. The end result is essentially the same as if you had
called <code>malloc</code> in C. The added benefit is that the Android VM can carry out garbage collection as well as
-share memory with the Renderscript runtime layer. Binding is only necessary for dynamically allocated memory. Statically
-allocated memory is automatically created for your Renderscript code at compile time. See <a href="#figure1">Figure 1</a>
+share memory with the RenderScript runtime layer. Binding is only necessary for dynamically allocated memory. Statically
+allocated memory is automatically created for your RenderScript code at compile time. See <a href="#figure1">Figure 1</a>
for more information on how memory allocation occurs.
</p>
@@ -479,11 +479,11 @@
<p>In most situations, you do not need to call these memory allocation APIs directly. The reflected layer
classes generate code to use these APIs automatically and all you need to do to allocate memory is call a
constructor that is declared in one of the reflected layer classes and then bind
- the resulting memory {@link android.renderscript.Allocation} to the Renderscript.
+ the resulting memory {@link android.renderscript.Allocation} to the RenderScript.
There are some situations where you would want to use these classes directly to allocate memory on your
own, such as loading a bitmap from a resource or when you want to allocate memory for pointers to
primitive types. You can see how to do this in the
- <a href="#allocating-mem">Allocating and binding memory to the Renderscript</a> section.
+ <a href="#allocating-mem">Allocating and binding memory to the RenderScript</a> section.
The following table describes the three memory management classes in more detail:</p>
<table id="mem-mgmt-table">
@@ -500,12 +500,12 @@
<p>An element describes one cell of a memory allocation and can have two forms: basic or
complex.</p>
- <p>A basic element contains a single component of data of any valid Renderscript data type.
+ <p>A basic element contains a single component of data of any valid RenderScript data type.
Examples of basic element data types include a single <code>float</code> value, a <code>float4</code> vector, or a
single RGB-565 color.</p>
<p>Complex elements contain a list of basic elements and are created from
- <code>struct</code>s that you declare in your Renderscript code. For instance an allocation
+ <code>struct</code>s that you declare in your RenderScript code. For instance an allocation
can contain multiple <code>struct</code>s arranged in order in memory. Each struct is considered as its
own element, rather than each data type within that struct.</p>
</td>
@@ -552,64 +552,64 @@
<h2 id="memory">Working with Memory</h2>
-<p>Non-static, global variables that you declare in your Renderscript are allocated memory at compile time.
-You can work with these variables directly in your Renderscript code without having to allocate
+<p>Non-static, global variables that you declare in your RenderScript are allocated memory at compile time.
+You can work with these variables directly in your RenderScript code without having to allocate
memory for them at the Android framework level. The Android framework layer also has access to these variables
with the provided accessor methods that are generated in the reflected layer classes. If these variables are
-initialized at the Renderscript runtime layer, those values are used to initialize the corresponding
+initialized at the RenderScript runtime layer, those values are used to initialize the corresponding
values in the Android framework layer. If global variables are marked as const, then a <code>set</code> method is
not generated.</p>
-<p class="note"><strong>Note:</strong> If you are using certain Renderscript structures that contain pointers, such as
+<p class="note"><strong>Note:</strong> If you are using certain RenderScript structures that contain pointers, such as
<code>rs_program_fragment</code> and <code>rs_allocation</code>, you have to obtain an object of the
corresponding Android framework class first and then call the <code>set</code> method for that
-structure to bind the memory to the Renderscript runtime. You cannot directly manipulate these structures
-at the Renderscript runtime layer. This restriction is not applicable to user-defined structures
+structure to bind the memory to the RenderScript runtime. You cannot directly manipulate these structures
+at the RenderScript runtime layer. This restriction is not applicable to user-defined structures
that contain pointers, because they cannot be exported to a reflected layer class
in the first place. A compiler error is generated if you try to declare a non-static, global
struct that contains a pointer.
</p>
-<p>Renderscript also has support for pointers, but you must explicitly allocate the memory in your
+<p>RenderScript also has support for pointers, but you must explicitly allocate the memory in your
Android framework code. When you declare a global pointer in your <code>.rs</code> file, you
allocate memory through the appropriate reflected layer class and bind that memory to the native
-Renderscript layer. You can interact with this memory from the Android framework layer as well as
-the Renderscript layer, which offers you the flexibility to modify variables in the most
+RenderScript layer. You can interact with this memory from the Android framework layer as well as
+the RenderScript layer, which offers you the flexibility to modify variables in the most
appropriate layer.</p>
- <h3 id="allocating-mem">Allocating and binding dynamic memory to the Renderscript</h3>
+ <h3 id="allocating-mem">Allocating and binding dynamic memory to the RenderScript</h3>
<p>To allocate dynamic memory, you need to call the constructor of a
{@link android.renderscript.Script.FieldBase} class, which is the most common way. An alternative is to create an
{@link android.renderscript.Allocation} manually, which is required for things such as primitive type pointers. You should
use a {@link android.renderscript.Script.FieldBase} class constructor whenever available for simplicity.
After obtaining a memory allocation, call the reflected <code>bind</code> method of the pointer to bind the allocated memory to the
- Renderscript runtime.</p>
+ RenderScript runtime.</p>
<p>The example below allocates memory for both a primitive type pointer,
<code>intPointer</code>, and a pointer to a struct, <code>touchPoints</code>. It also binds the memory to the
- Renderscript:</p>
+ RenderScript:</p>
<pre>
-private RenderScript myRenderscript;
+private RenderScript myRenderScript;
private ScriptC_example script;
private Resources resources;
public void init(RenderScript rs, Resources res) {
- myRenderscript = rs;
+ myRenderScript = rs;
resources = res;
//allocate memory for the struct pointer, calling the constructor
- ScriptField_Point touchPoints = new ScriptField_Point(myRenderscript, 2);
+ ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2);
//Create an element manually and allocate memory for the int pointer
- intPointer = Allocation.createSized(myRenderscript, Element.I32(myRenderscript), 2);
+ intPointer = Allocation.createSized(myRenderScript, Element.I32(myRenderScript), 2);
- //create an instance of the Renderscript, pointing it to the bytecode resource
- mScript = new ScriptC_example(myRenderscript, resources, R.raw.example);
+ //create an instance of the RenderScript, pointing it to the bytecode resource
+ mScript = new ScriptC_example(myRenderScript, resources, R.raw.example);
- //bind the struct and int pointers to the Renderscript
+ //bind the struct and int pointers to the RenderScript
mScript.bind_touchPoints(touchPoints);
script.bind_intPointer(intPointer);
@@ -618,29 +618,29 @@
</pre>
<h3>Reading and writing to memory</h3>
- <p>You can read and write to statically and dynamically allocated memory both at the Renderscript runtime
+ <p>You can read and write to statically and dynamically allocated memory both at the RenderScript runtime
and Android framework layer.</p>
<p>Statically allocated memory comes with a one-way communication restriction
-at the Renderscript runtime level. When Renderscript code changes the value of a variable, it is not
+at the RenderScript runtime level. When RenderScript code changes the value of a variable, it is not
communicated back to the Android framework layer for efficiency purposes. The last value
that is set from the Android framework is always returned during a call to a <code>get</code>
method. However, when Android framework code modifies a variable, that change can be communicated to
-the Renderscript runtime automatically or synchronized at a later time. If you need to send data
-from the Renderscript runtime to the Android framework layer, you can use the
+the RenderScript runtime automatically or synchronized at a later time. If you need to send data
+from the RenderScript runtime to the Android framework layer, you can use the
<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a> function
to overcome this limitation.
</p>
-<p>When working with dynamically allocated memory, any changes at the Renderscript runtime layer are propagated
+<p>When working with dynamically allocated memory, any changes at the RenderScript runtime layer are propagated
back to the Android framework layer if you modified the memory allocation using its associated pointer.
-Modifying an object at the Android framework layer immediately propagates that change back to the Renderscript
+Modifying an object at the Android framework layer immediately propagates that change back to the RenderScript
runtime layer.</p>
<h4>Reading and writing to global variables</h4>
<p>Reading and writing to global variables is a straightforward process. You can use the accessor methods
- at the Android framework level or set them directly in the Renderscript code. Keep in mind that any
- changes that you make in your Renderscript code are not propagated back to the Android framework layer.</p>
+ at the Android framework level or set them directly in the RenderScript code. Keep in mind that any
+ changes that you make in your RenderScript code are not propagated back to the Android framework layer.</p>
<p>For example, given the following struct declared in a file named <code>rsfile.rs</code>:</p>
<pre>
@@ -659,8 +659,8 @@
point.y = 1;
</pre>
-<p>You can assign values to the struct at the Android framework layer like this. These values are
-propagated back to the Renderscript runtime level:</p>
+<p>You can assign values to the struct at the Android framework layer like this. These values are
+propagated back to the RenderScript runtime level:</p>
<pre>
ScriptC_rsfile mScript;
@@ -672,7 +672,7 @@
mScript.set_point(i);
</pre>
-<p>You can read the values in your Renderscript code like this:</p>
+<p>You can read the values in your RenderScript code like this:</p>
<pre>
rsDebug("Printing out a Point", point.x, point.y);
@@ -680,7 +680,7 @@
<p>You can read the values in the Android framework layer with the following code. Keep in mind that this
code only returns a value if one was set at the Android framework level. You will get a null pointer
-exception if you only set the value at the Renderscript runtime level:</p>
+exception if you only set the value at the RenderScript runtime level:</p>
<pre>
Log.i("TAGNAME", "Printing out a Point: " + mScript.get_point().x + " " + mScript.get_point().y);
@@ -689,9 +689,9 @@
<h4>Reading and writing global pointers</h4>
-<p>Assuming that memory has been allocated in the Android framework level and bound to the Renderscript runtime,
+<p>Assuming that memory has been allocated in the Android framework level and bound to the RenderScript runtime,
you can read and write memory from the Android framework level by using the <code>get</code> and <code>set</code> methods for that pointer.
-In the Renderscript runtime layer, you can read and write to memory with pointers as normal and the changes are propagated
+In the RenderScript runtime layer, you can read and write to memory with pointers as normal and the changes are propagated
back to the Android framework layer, unlike with statically allocated memory.</p>
<p>For example, given the following pointer to a <code>struct</code> in a file named <code>rsfile.rs</code>:</p>
@@ -726,5 +726,5 @@
points.get_x(0);
</pre>
-<p>Once memory is already bound, you do not have to rebind the memory to the Renderscript
+<p>Once memory is already bound, you do not have to rebind the memory to the RenderScript
runtime every time you make a change to a value.</p>
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 5f466ce..607d16e 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -1,4 +1,4 @@
-page.title=Renderscript Computation
+page.title=RenderScript
parent.title=Computation
parent.link=index.html
@@ -9,15 +9,8 @@
<h2>In this document</h2>
<ol>
- <li><a href="#overview">Renderscript System Overview</a></li>
- <li><a href="#filterscript">Filterscript</a></li>
- <li>
- <a href="#creating-renderscript">Creating a Computation Renderscript</a>
- <ol>
- <li><a href="#creating-rs-file">Creating the Renderscript file</a></li>
- <li><a href="#calling">Calling the Renderscript code</a></li>
- </ol>
- </li>
+ <li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li>
+ <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li>
</ol>
<h2>Related Samples</h2>
@@ -29,371 +22,204 @@
</div>
</div>
- <p>Renderscript offers a high performance computation API at the native
-level that you write in C (C99 standard). Renderscript gives your apps the ability to run
-operations with automatic parallelization across all available processor cores.
-It also supports different types of processors such as the CPU, GPU or DSP. Renderscript
-is useful for apps that do image processing, mathematical modeling, or any operations
-that require lots of mathematical computation.</p>
+<p>RenderScript is a framework for running computationally intensive tasks at high performance on
+Android. RenderScript is primarily oriented for use with data-parallel computation, although serial
+computationally intensive workloads can benefit as well. The RenderScript runtime will parallelize
+work across all processors available on a device, such as multi-core CPUs, GPUs, or DSPs, allowing
+you to focus on expressing algorithms rather than scheduling work or load balancing. RenderScript is
+especially useful for applications performing image processing, computational photography, or
+computer vision.</p>
-<p>In addition, you have access to all of these features without having to write code to
-support different architectures or a different amount of processing cores. You also
-do not need to recompile your application for different processor types, because Renderscript
-code is compiled on the device at runtime.</p>
-
-<p class="note"><strong>Deprecation Notice</strong>: Earlier versions of Renderscript included
- an experimental graphics engine component. This component
-is now deprecated as of Android 4.1 (most of the APIs in <code>rs_graphics.rsh</code>
-and the corresponding APIs in {@link android.renderscript}).
-If you have apps that render graphics with Renderscript, we highly
-recommend you convert your code to another Android graphics rendering option.</p>
-
- <h2 id="overview">Renderscript System Overview</h2>
- <p>The Renderscript runtime operates at the native level and still needs to communicate
-with the Android VM, so the way a Renderscript application is set up is different from a pure VM
-application. An application that uses Renderscript is still a traditional Android application that
-runs in the VM, but you write Renderscript code for the parts of your program that require
-it. No matter what you use it for, Renderscript remains platform
-independent, so you do not have to target multiple architectures (for example,
-ARM v5, ARM v7, x86).</p>
-
-<p>The Renderscript system adopts a control and slave architecture where the low-level Renderscript runtime
-code is controlled by the higher level Android system that runs in a virtual machine (VM). The
-Android VM still retains all control of memory management and binds memory that it allocates to
-the Renderscript runtime, so the Renderscript code can access it. The Android framework makes
-asynchronous calls to Renderscript, and the calls are placed in a message queue and processed
-as soon as possible. Figure 1 shows how the Renderscript system is structured.</p>
-
- <img id="figure1" src="{@docRoot}images/rs_overview.png" />
- <p class="img-caption"><strong>Figure 1.</strong> Renderscript system overview</p>
-
- <p>When using Renderscript, there are three layers of APIs that enable communication between the
- Renderscript runtime and Android framework code:</p>
-
- <ul>
- <li>The Renderscript runtime APIs allow you to do the computation
- that is required by your application.</li>
-
- <li>The reflected layer APIs are a set of classes that are reflected from your Renderscript
-runtime code. It is basically a wrapper around the Renderscript code that allows the Android
-framework to interact with the Renderscript runtime. The Android build tools automatically generate the
-classes for this layer during the build process. These classes eliminate the need to write JNI glue
-code, like with the NDK.</li>
-
- <li>The Android framework layer calls the reflected layer to access the Renderscript
- runtime.</li>
- </ul>
-
-<p>Because of the way Renderscript is structured, the main advantages are:</p>
- <ul>
- <li>Portability: Renderscript is designed to run on many types of devices with different
- processor (CPU, GPU, and DSP for instance) architectures. It supports all of these architectures without
- having to target each device, because the code is compiled and cached on the device
- at runtime.</li>
-
- <li>Performance: Renderscript provides a high performance computation API with seamless parallelization
- across the amount of cores on the device.</li>
-
- <li>Usability: Renderscript simplifies development when possible, such as eliminating JNI glue code.</li>
- </ul>
-
- <p>The main disadvantages are:</p>
-
- <ul>
- <li>Development complexity: Renderscript introduces a new set of APIs that you have to learn.</li>
-
- <li>Debugging visibility: Renderscript can potentially execute (planned feature for later releases)
- on processors other than the main CPU (such as the GPU), so if this occurs, debugging becomes more difficult.
- </li>
- </ul>
-
-<p>For a more detailed explanation of how all of these layers work together, see
- <a href="{@docRoot}guide/topics/renderscript/advanced.html">Advanced Renderscript</a>.<p>
-
-<h2 id="filterscript">Filterscript</h2>
-
-<p>Introduced in Android 4.2 (API Level 17), Filterscript defines a subset of Renderscript
-that focuses on image processing operations, such as those
-that you would typically write with an OpenGL ES fragment shader. You still write your scripts
-using the standard Renderscript runtime APIs, but within stricter
-constraints that ensure wider compatibility and improved optimization across
-CPUs, GPUs, and DSPs. At compile time, the precompiler evaluates Filterscript files and
-applies a more stringent set of warnings and errors than
-it does for standard Renderscript files. The following list describes the major constraints
-of Filterscript when compared to Renderscript:</p>
-
+<p>To begin with RenderScript, there are two main concepts you should understand:</p>
<ul>
-<li>Inputs and return values of root functions cannot contain pointers. The default root function
-signature contains pointers, so you must use the <code>__attribute__((kernel))</code> attribute to declare a custom
-root function when using Filterscript.</li>
-<li>Built-in types cannot exceed 32-bits.</li>
-<li>Filterscript must always use relaxed floating point precision by using the
-<code>rs_fp_relaxed</code> pragma.</li>
-<li>Filterscript files must end with an <code>.fs</code> extension, instead of an <code>.rs</code> extension.</li>
+
+<li>High-performance compute kernels are written in a C99-derived language.</li>
+
+<li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel
+execution.</li>
</ul>
-<h2 id="creating-renderscript">Creating a Renderscript</h2>
+<h2 id="writing-an-rs-kernel">Writing a RenderScript Kernel</h2>
-<p>Renderscript scales to the amount of
-processing cores available on the device. This is enabled through a function named
-<code>rsForEach()</code> (or the <code>forEach_root()</code> method at the Android framework level).
-that automatically partitions work across available processing cores on the device.</p>
-
-<p>Implementing a Renderscript involves creating a <code>.rs</code> file that contains
-your Renderscript code and calling it at the Android framework level with the
-<code>forEach_root()</code> or at the Renderscript runtime level with the
-<code>rsForEach()</code> function. The following diagram describes how a typical
-Renderscript is set up:</p><img src="{@docRoot}images/rs_compute.png">
-
-<p class="img-caption"><strong>Figure 1.</strong> Renderscript overview</p>
-
-<p>The following sections describe how to create a simple Renderscript and use it in an
-Android application. This example uses the <a href=
-"{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">HelloCompute Renderscript
-sample</a> that is provided in the SDK as a guide (some code has been modified from its original
-form for simplicity).</p>
-
-<h3 id="creating-rs-file">Creating the Renderscript file</h3>
-
-<p>Your Renderscript code resides in <code>.rs</code> and <code>.rsh</code> files in the
-<code><project_root>/src/</code> directory. This code contains the computation logic
-and declares all necessary variables and pointers.
-Every <code>.rs</code> file generally contains the following items:</p>
+<p>A RenderScript kernel typically resides in a <code>.rs</code> file in the
+<code><project_root>/src/</code> directory; each <code>.rs</code> file is called a
+script. Every script contains its own set of kernels, functions, and variables. A script can
+contain:</p>
<ul>
- <li>A pragma declaration (<code>#pragma rs java_package_name(<em>package.name</em>)</code>)
- that declares the package name of the <code>.java</code> reflection of this Renderscript.</li>
+<li>A pragma declaration (<code>#pragma version(1)</code>) that declares the version of the
+RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
- <li>A pragma declaration (<code>#pragma version(1)</code>) that declares the version of
- Renderscript that you are using (1 is the only value for now).</li>
-
- <li><p>A root function (or kernel) that is the main entry point to your Renderscript.
- The default <code>root()</code> function must return
- <code>void</code> and accept the following arguments:</p>
+<li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
+declares the package name of the Java classes reflected from this script.</li>
- <ul>
- <li>Pointers to memory allocations that are used for the input and output of the
- Renderscript. Both of these pointers are required for Android 3.2 (API level 13) platform
- versions or older. Android 4.0 (API level 14) and later requires one or both of these
- allocations.</li>
- </ul>
+<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
+function that you can call from your Java code with arbitrary arguments. These are often useful for
+initial setup or serial computations within a larger processing pipeline.</li>
- <p>The following arguments are optional, but both must be supplied if you choose to use
- them:</p>
+<li>Some number of script globals. A script global is equivalent to a global variable in C. You can
+access script globals from Java code, and these are often used for parameter passing to RenderScript
+kernels.</li>
- <ul>
- <li>A pointer for user-defined data that the Renderscript might need to carry out
- computations in addition to the necessary allocations. This can be a pointer to a simple
- primitive or a more complex struct.</li>
+<li>Some number of compute kernels. A kernel is a parallel function that executes across every
+{@link android.renderscript.Element} within an {@link android.renderscript.Allocation}.
- <li>The size of the user-defined data.</li>
- </ul>
+<p>A simple kernel may look like the following:</p>
- <p>Starting in Android 4.1 (API Level 16), you can choose to define your own root function arguments
- without adhering to the default root function signature described previously. In addition,
- you can declare multiple root functions in the same Renderscript. To do this, use the <code>__attribute__((kernel))</code>
- attribute to define a custom root function. For example, here's a root function
- that returns a <code>uchar4</code> and accepts two <code>uint32_t</code> types: </p>
+<pre>uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
+ uchar4 out = in;
+ out.r = 255 - in.r;
+ out.g = 255 - in.g;
+ out.b = 255 - in.b;
+ return out;
+}</pre>
- <pre>
- uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
- ...
- }
- </pre>
- </li>
+<p>In most respects, this is identical to a standard C function. The first notable feature is the
+<code>__attribute__((kernel))</code> applied to the function prototype. This denotes that the
+function is a RenderScript kernel instead of an invokable function. The next feature is the
+<code>in</code> argument and its type. In a RenderScript kernel, this is a special argument that is
+automatically filled in based on the input {@link android.renderscript.Allocation} passed to the
+kernel launch. By default, the kernel is run across an entire {@link
+android.renderscript.Allocation}, with one execution of the kernel body per {@link
+android.renderscript.Element} in the {@link android.renderscript.Allocation}. The third notable
+feature is the return type of the kernel. The value returned from the kernel is automatically
+written to the appropriate location in the output {@link android.renderscript.Allocation}. The
+RenderScript runtime checks to ensure that the {@link android.renderscript.Element} types of the
+input and output Allocations match the kernel's prototype; if they do not match, an exception is
+thrown.</p>
- <li>An optional <code>init()</code> function. This allows you to do any initialization
- before the root function runs, such as initializing variables. This
- function runs once and is called automatically when the Renderscript starts, before anything
- else in your Renderscript.</li>
+<p>A kernel may have an input {@link android.renderscript.Allocation}, an output {@link
+android.renderscript.Allocation}, or both. A kernel may not have more than one input or one output
+{@link android.renderscript.Allocation}. If more than one input or output is required, those objects
+should be bound to <code>rs_allocation</code> script globals and accessed from a kernel or invokable
+function via <code>rsGetElementAt_<em>type</em>()</code> or
+<code>rsSetElementAt_<em>type</em>()</code>.</p>
- <li>Any variables, pointers, and structures that you wish to use in your Renderscript code (can
- be declared in <code>.rsh</code> files if desired)</li>
-</ul>
+<p>A kernel may access the coordinates of the current execution using the <code>x</code>,
+<code>y</code>, and <code>z</code> arguments. These arguments are optional, but the type of the
+coordinate arguments must be <code>uint32_t</code>.</p></li>
-<p>The following code shows how the <a href=
-"{@docRoot}resources/samples/RenderScript/HelloCompute/src/com/example/android/rs/hellocompute/mono.html">
-mono.rs</a> file is implemented:</p>
-<pre>
-#pragma version(1)
-#pragma rs java_package_name(com.example.android.rs.hellocompute)
+<li>An optional <code>init()</code> function. An <code>init()</code> function is a special type of
+invokable function that is run when the script is first instantiated. This allows for some
+computation to occur automatically at script creation.</li>
-//multipliers to convert a RGB colors to black and white
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- //unpack a color to a float4
- float4 f4 = rsUnpackColor8888(*v_in);
- //take the dot product of the color and the multiplier
- float3 mono = dot(f4.rgb, gMonoMult);
- //repack the float to a color
- *v_out = rsPackColorTo8888(mono);
-}
-</pre>
+<li>Some number of static script globals and functions. A static script global is equivalent to a
+script global except that it cannot be set from Java code. A static function is a standard C
+function that can be called from any kernel or invokable function in the script but is not exposed
+to the Java API. If a script global or function does not need to be called from Java code, it is
+highly recommended that those be declared <code>static</code>.</li> </ul>
<h4>Setting floating point precision</h4>
-<p>You can define the floating point precision required by your compute algorithms. This is useful if you
- require less precision than the IEEE 754-2008 standard (used by default). You can define
-the floating-point precision level of your script with the following pragmas:</p>
+
+<p>You can control the required level of floating point precision in a script. This is useful if
+full IEEE 754-2008 standard (used by default) is not required. The following pragmas can set a
+different level of floating point precision:</p>
<ul>
- <li><code>#pragma rs_fp_full</code> (default if nothing is specified): For apps that
- require floating point precision as outlined by the IEEE 754-2008 standard.
+
+<li><code>#pragma rs_fp_full</code> (default if nothing is specified): For apps that require
+ floating point precision as outlined by the IEEE 754-2008 standard.
+
</li>
- <li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require
- strict IEEE 754-2008 compliance and can tolerate less precision. This mode enables
- flush-to-zero for denorms and round-towards-zero.
+
+ <li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require strict IEEE 754-2008
+ compliance and can tolerate less precision. This mode enables flush-to-zero for denorms and
+ round-towards-zero.
+
</li>
- <li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision requirements. This mode enables
- everything in <code>rs_fp_relaxed</code> along with the following:
+
+ <li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision
+ requirements. This mode enables everything in <code>rs_fp_relaxed</code> along with the
+ following:
+
<ul>
+
<li>Operations resulting in -0.0 can return +0.0 instead.</li>
<li>Operations on INF and NAN are undefined.</li>
</ul>
</li>
</ul>
-<h4>Script intrinsics</h4>
-<p>Renderscript adds support for a set of script intrinsics, which are pre-implemented
-filtering primitives that reduce the amount of
-code that you need to write. They also are implemented to ensure that your app gets the
-maximum performance gain possible.</p>
+<p>Most applications can use <code>rs_fp_relaxed</code> without any side effects. This may be very
+beneficial on some architectures due to additional optimizations only available with relaxed
+precision (such as SIMD CPU instructions).</p>
-<p>
-Intrinsics are available for the following:
+<h2 id="using-rs-from-java">Using RenderScript from Java Code</h2>
+
+<p>Using RenderScript from Java code relies on the {@link android.renderscript} APIs. Most
+applications follow the same basic usage patterns:</p>
+
+<ol>
+
+<li><strong>Initialize a RenderScript context.</strong> The {@link
+android.renderscript.RenderScript} context, created with {@link
+android.renderscript.RenderScript#create}, ensures that RenderScript can be used and provides an
+object to control the lifetime of all subsequent RenderScript objects. You should consider context
+creation to be a potentially long-running operation, since it may create resources on different
+pieces of hardware; it should not be in an application's critical path if at all
+possible. Typically, an application will have only a single RenderScript context at a time.</li>
+
+<li><strong>Create at least one {@link android.renderscript.Allocation} to be passed to a
+script.</strong> An {@link android.renderscript.Allocation} is a RenderScript object that provides
+storage for a fixed amount of data. Kernels in scripts take {@link android.renderscript.Allocation}
+objects as their input and output, and {@link android.renderscript.Allocation} objects can be
+accessed in kernels using <code>rsGetElementAt_<em>type</em>()</code> and
+<code>rsSetElementAt_<em>type</em>()</code> when bound as script globals. {@link
+android.renderscript.Allocation} objects allow arrays to be passed from Java code to RenderScript
+code and vice-versa. {@link android.renderscript.Allocation} objects are typically created using
+{@link android.renderscript.Allocation#createTyped} or {@link
+android.renderscript.Allocation#createFromBitmap}.</li>
+
+<li><strong>Create whatever scripts are necessary.</strong> There are two types of scripts available
+to you when using RenderScript:
+
<ul>
- <li>{@link android.renderscript.ScriptIntrinsicBlend Blends}</li>
- <li>{@link android.renderscript.ScriptIntrinsicBlur Blur}</li>
- <li>{@link android.renderscript.ScriptIntrinsicColorMatrix Color matrix}</li>
- <li>{@link android.renderscript.ScriptIntrinsicConvolve3x3 3x3 convolve}</li>
- <li>{@link android.renderscript.ScriptIntrinsicConvolve5x5 5x5 convolve}</li>
- <li>{@link android.renderscript.ScriptIntrinsicLUT Per-channel lookup table}</li>
- <li>{@link android.renderscript.ScriptIntrinsicYuvToRGB Converting an Android YUV buffer to RGB}</li>
-</ul>
-<h3 id="calling">Calling the Renderscript code</h3>
+<li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a
+href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class
+reflected by the RenderScript compiler in order to make it easy to access the script from Java code;
+this class will have the name <code>ScriptC_<em>filename</em></code>. For example, if the kernel
+above was located in <code>invert.rs</code> and a RenderScript context was already located in
+<code>mRS</code>, the Java code to instantiate the script would be:
-<p>You can call the Renderscript from your Android framework code by
-creating a Renderscript object by instantiating the (<code>ScriptC_<em>script_name</em></code>)
-class. This class contains a method, <code>forEach_root()</code>, that lets you invoke
-<code>rsForEach</code>. You give it the same parameters that you would if you were invoking it
-at the Renderscript runtime level. This technique allows your Android application to offload
-intensive mathematical calculations to Renderscript. See the <a href=
-"{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">HelloCompute</a> sample to see
-how a simple Android application can utilize Renderscript.</p>
+<pre>ScriptC_invert invert = new ScriptC_invert(mRenderScript);</pre></li>
-<p>To call Renderscript at the Android framework level:</p>
+<li><strong>ScriptIntrinsic</strong>: These are built-in RenderScript kernels for common operations,
+such as Gaussian blur, convolution, and image blending. For more information, see the subclasses of
+{@link android.renderscript.ScriptIntrinsic}.</li>
-<ol>
- <li>Allocate memory that is needed by the Renderscript in your Android framework code.
- You need an input and output {@link android.renderscript.Allocation} for Android 3.2 (API level
- 13) platform versions and older. The Android 4.0 (API level 14) platform version requires only
- one or both {@link android.renderscript.Allocation}s.</li>
+</ul></li>
- <li>Create an instance of the <code>ScriptC_<em>script_name</em></code> class.</li>
+<li><strong>Populate Allocations with data.</strong> Except for Allocations created with {@link
+android.renderscript#createFromBitmap}, an Allocation will be populated with empty data when it is
+first created. To populate an Allocation, use one of the <code>copy</code> methods in {@link
+android.renderscript.Allocation}.</li>
- <li>Call <code>forEach_root()</code>, passing in the allocations, the
- Renderscript, and any optional user-defined data. The output allocation will contain the output
- of the Renderscript.</li>
-</ol>
+<li><strong>Set any necessary script globals.</strong> Globals may be set using methods in the same
+<code>ScriptC_<em>filename</em></code> class with methods named
+<code>set_<em>globalname</em></code>. For example, in order to set an <code>int</code> named
+<code>elements</code>, use the Java method <code>set_elements(int)</code>. RenderScript objects can
+also be set in kernels; for example, the <code>rs_allocation</code> variable named
+<code>lookup</code> can be set with the method <code>set_lookup(Allocation)</code>.</li>
-<p>The following example, taken from the <a href=
-"{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">HelloCompute</a> sample, processes
-a bitmap and outputs a black and white version of it. The
-<code>createScript()</code> method carries out the steps described previously. This method calls the
-Renderscript, <code>mono.rs</code>, passing in memory allocations that store the bitmap to be processed
-as well as the eventual output bitmap. It then displays the processed bitmap onto the screen:</p>
-<pre>
-package com.example.android.rs.hellocompute;
+<li><strong>Launch the appropriate kernels.</strong> Methods to launch a given kernel will be
+reflected in the same <code>ScriptC_<em>filename</em></code> class with methods named
+<code>forEach_<em>kernelname</em>()</code>. These launches are asynchronous, and launches will be
+serialized in the order in which they are launched. Depending on the arguments to the kernel, the
+method will take either one or two Allocations. By default, a kernel will execute over the entire
+input or output Allocation; to execute over a subset of that Allocation, pass an appropriate {@link
+android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> method.
-import android.app.Activity;
-import android.os.Bundle;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.renderscript.RenderScript;
-import android.renderscript.Allocation;
-import android.widget.ImageView;
+<p>Invoked functions can be launched using the <code>invoke_<em>functionname</em></code> methods
+reflected in the same <code>ScriptC_<em>filename</em></code> class.</p></li>
-public class HelloCompute extends Activity {
- private Bitmap mBitmapIn;
- private Bitmap mBitmapOut;
+<li><strong>Copy data out of {@link android.renderscript.Allocation} objects.</strong> In order to
+access data from an {@link android.renderscript.Allocation} from Java code, that data must be copied
+back to Java buffers using one of the <code>copy</code> methods in {@link
+android.renderscript.Allocation}. These functions will synchronize with asynchronous kernel and
+function launches as necessary.</li>
- private RenderScript mRS;
- private Allocation mInAllocation;
- private Allocation mOutAllocation;
- private ScriptC_mono mScript;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- mBitmapIn = loadBitmap(R.drawable.data);
- mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
- mBitmapIn.getConfig());
-
- ImageView in = (ImageView) findViewById(R.id.displayin);
- in.setImageBitmap(mBitmapIn);
-
- ImageView out = (ImageView) findViewById(R.id.displayout);
- out.setImageBitmap(mBitmapOut);
-
- createScript();
- }
- private void createScript() {
- mRS = RenderScript.create(this);
- mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
- mOutAllocation = Allocation.createTyped(mRS, mInAllocation.getType());
- mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono);
- mScript.forEach_root(mInAllocation, mOutAllocation);
- mOutAllocation.copyTo(mBitmapOut);
- }
-
- private Bitmap loadBitmap(int resource) {
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- return BitmapFactory.decodeResource(getResources(), resource, options);
- }
-}
-</pre>
-
-<p>To call Renderscript from another Renderscript file:</p>
-<ol>
- <li>Allocate memory that is needed by the Renderscript in your Android framework code.
- You need an input and output {@link android.renderscript.Allocation} for Android 3.2 (API level
- 13) platform versions and older. The Android 4.0 (API level 14) platform version requires only
- one or both {@link android.renderscript.Allocation}s.</li>
-
- <li>Call <code>rsForEach()</code>, passing in the allocations and any optional user-defined data.
- The output allocation will contain the output of the Renderscript.</li>
-</ol>
-
-<pre>
-rs_script script;
-rs_allocation in_allocation;
-rs_allocation out_allocation;
-UserData_t data;
-...
-rsForEach(script, in_allocation, out_allocation, &data, sizeof(data));
-</pre>
-</p>
-<p>In this example, assume that the script and memory allocations have already been
-allocated and bound at the Android framework level and that <code>UserData_t</code> is a struct
-declared previously. Passing a pointer to a struct and the size of the struct to <code>rsForEach</code>
-is optional, but useful if your Renderscript requires additional information other than
-the necessary memory allocations.</p>
-
-
-<h4>Script groups</h4>
-
-<p>You can group Renderscript scripts together and execute them all with a single call as though
-they were part of a single script. This allows Renderscript to optimize execution of the scripts
-in ways that it could not do if the scripts were executed individually.</p>
-
-<p>To build a script groupm, use the {@link android.renderscript.ScriptGroup.Builder} class to create a {@link android.renderscript.ScriptGroup}
-defining the operations. At execution time, Renderscript optimizes the run order and the connections between these
-operations for best performance.
-
-<p class="note"><strong>Important:</strong> The script group must be a direct acyclic graph for this feature to work.</p>
+<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
+with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
+object to be garbage collected. This will cause any further use of any object belonging to that
+context to throw an exception.</li> </ol>
\ No newline at end of file
diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd
index b5c53ff..d23ba69 100644
--- a/docs/html/guide/topics/renderscript/index.jd
+++ b/docs/html/guide/topics/renderscript/index.jd
@@ -1,6 +1,6 @@
page.title=Computation
page.landing=true
-page.landing.intro=Renderscript provides a platform-independent computation engine that operates at the native level. Use it to accelerate your apps that require extensive computational horsepower.
+page.landing.intro=RenderScript provides a platform-independent computation engine that operates at the native level. Use it to accelerate your apps that require extensive computational horsepower.
page.landing.image=
@jd:body
@@ -12,16 +12,16 @@
<a
href="http://android-developers.blogspot.com/2013/01/evolution-of-renderscript-performance.html">
- <h4>Evolution of Renderscript Performance</h4>
- <p>It’s been a year since the last blog post on Renderscript, and with the release
+ <h4>Evolution of RenderScript Performance</h4>
+ <p>It’s been a year since the last blog post on RenderScript, and with the release
of Android 4.2, it’s a good time to talk about the performance work that we’ve done
since then. One of the major goals of this past year was to improve the performance
- of common image-processing operations with Renderscript.</p> </a>
+ of common image-processing operations with RenderScript.</p> </a>
<a
href="http://android-developers.blogspot.com/2012/01/levels-in-renderscript.html">
- <h4>Levels in Renderscript</h4>
- <p>For ICS, Renderscript (RS) has been updated with several new features to simplify
+ <h4>Levels in RenderScript</h4>
+ <p>For ICS, RenderScript (RS) has been updated with several new features to simplify
adding compute acceleration to your application. RS is interesting for compute
acceleration when you have large buffers of data on which you need to do significant
processing. In this example we will look at applying a levels/saturation operation
@@ -30,11 +30,11 @@
<a
href="http://android-developers.blogspot.com/2011/03/renderscript.html">
- <h4>Renderscript Part 2</h4>
- <p>In Introducing Renderscript I gave a brief overview of this technology.
- In this post I’ll look at "compute" in more detail. In Renderscript we use
+ <h4>RenderScript Part 2</h4>
+ <p>In Introducing RenderScript I gave a brief overview of this technology.
+ In this post I’ll look at "compute" in more detail. In RenderScript we use
"compute" to mean offloading of data processing from Dalvik code to
- Renderscript code which may run on the same or different processor(s).</p>
+ RenderScript code which may run on the same or different processor(s).</p>
</a>
</div>
diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd
index 480fe65..55c8dc42 100644
--- a/docs/html/guide/topics/resources/localization.jd
+++ b/docs/html/guide/topics/resources/localization.jd
@@ -480,4 +480,4 @@
<h2 id="checklist">Localization Checklist</h2>
-<p>For an overview of the process of localizing an Android application, see the <a href="{@docRoot}distribute/googleplay/publish/localization.html">Localization Checklist</a>.</p>
+<p>For an overview of the process of localizing an Android application, see the <a href="{@docRoot}distribute/googleplay/publish/localizing.html">Localization Checklist</a>.</p>
diff --git a/docs/html/reference/com/google/android/gcm/GCMBaseIntentService.html b/docs/html/reference/com/google/android/gcm/GCMBaseIntentService.html
index b230b88..ad50a35 100644
--- a/docs/html/reference/com/google/android/gcm/GCMBaseIntentService.html
+++ b/docs/html/reference/com/google/android/gcm/GCMBaseIntentService.html
@@ -838,6 +838,9 @@
<h2>Class Overview</h2>
+<div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;"><strong>DEPRECATED.</strong> Please use the <a href=
+"http://developer.android.com/reference/com/google/android/gms/gcm/GoogleCloudMessaging.html"><code>GoogleCloudMessaging</code></a> API instead.</div>
+
<p itemprop="articleBody">Skeleton for application-specific <code><a href="/reference/android/app/IntentService.html">IntentService</a></code>s responsible for
handling communication from Google Cloud Messaging service.
<p>
diff --git a/docs/html/reference/com/google/android/gcm/GCMBroadcastReceiver.html b/docs/html/reference/com/google/android/gcm/GCMBroadcastReceiver.html
index 91c0994..ea36df4 100644
--- a/docs/html/reference/com/google/android/gcm/GCMBroadcastReceiver.html
+++ b/docs/html/reference/com/google/android/gcm/GCMBroadcastReceiver.html
@@ -737,6 +737,10 @@
<h2>Class Overview</h2>
+
+<div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;"><strong>DEPRECATED.</strong> Please use the <a href=
+"http://developer.android.com/reference/com/google/android/gms/gcm/GoogleCloudMessaging.html"><code>GoogleCloudMessaging</code></a> API instead.</div>
+
<p itemprop="articleBody"><code><a href="/reference/android/content/BroadcastReceiver.html">BroadcastReceiver</a></code> that receives GCM messages and delivers them to
an application-specific <code><a href="/reference/com/google/android/gcm/GCMBaseIntentService.html">GCMBaseIntentService</a></code> subclass.
<p>
diff --git a/docs/html/reference/com/google/android/gcm/GCMConstants.html b/docs/html/reference/com/google/android/gcm/GCMConstants.html
index cb260e0..8b782b6 100644
--- a/docs/html/reference/com/google/android/gcm/GCMConstants.html
+++ b/docs/html/reference/com/google/android/gcm/GCMConstants.html
@@ -710,6 +710,8 @@
<h2>Class Overview</h2>
+<div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;"><strong>DEPRECATED.</strong> Please use the <a href=
+"http://developer.android.com/reference/com/google/android/gms/gcm/GoogleCloudMessaging.html"><code>GoogleCloudMessaging</code></a> API instead.</div>
<p itemprop="articleBody">Constants used by the GCM library.
</p>
diff --git a/docs/html/reference/com/google/android/gcm/GCMRegistrar.html b/docs/html/reference/com/google/android/gcm/GCMRegistrar.html
index 545abe2..21a990f 100644
--- a/docs/html/reference/com/google/android/gcm/GCMRegistrar.html
+++ b/docs/html/reference/com/google/android/gcm/GCMRegistrar.html
@@ -713,6 +713,10 @@
<h2>Class Overview</h2>
+
+<div style="background-color:#fffdeb;width:100%;margin-bottom:1em;padding:.5em;"><strong>DEPRECATED.</strong> Please use the <a href=
+"http://developer.android.com/reference/com/google/android/gms/gcm/GoogleCloudMessaging.html"><code>GoogleCloudMessaging</code></a> API instead.</div>
+
<p itemprop="articleBody">Utilities for device registration.
<p>
<strong>Note:</strong> this class uses a private <code><a href="/reference/android/content/SharedPreferences.html">SharedPreferences</a></code>
diff --git a/docs/html/reference/com/google/android/gcm/package-summary.html b/docs/html/reference/com/google/android/gcm/package-summary.html
index d2b05e6..6c8a993 100644
--- a/docs/html/reference/com/google/android/gcm/package-summary.html
+++ b/docs/html/reference/com/google/android/gcm/package-summary.html
@@ -642,21 +642,19 @@
<table class="jd-sumtable-expando">
<tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="/reference/com/google/android/gcm/GCMBaseIntentService.html">GCMBaseIntentService</a></td>
- <td class="jd-descrcol" width="100%">Skeleton for application-specific <code><a href="/reference/android/app/IntentService.html">IntentService</a></code>s responsible for
- handling communication from Google Cloud Messaging service. </td>
+ <td class="jd-descrcol" width="100%">DEPRECATED. </td>
</tr>
<tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="/reference/com/google/android/gcm/GCMBroadcastReceiver.html">GCMBroadcastReceiver</a></td>
- <td class="jd-descrcol" width="100%"><code><a href="/reference/android/content/BroadcastReceiver.html">BroadcastReceiver</a></code> that receives GCM messages and delivers them to
- an application-specific <code><a href="/reference/com/google/android/gcm/GCMBaseIntentService.html">GCMBaseIntentService</a></code> subclass. </td>
+ <td class="jd-descrcol" width="100%">DEPRECATED. </td>
</tr>
<tr class="alt-color api apilevel-" >
<td class="jd-linkcol"><a href="/reference/com/google/android/gcm/GCMConstants.html">GCMConstants</a></td>
- <td class="jd-descrcol" width="100%">Constants used by the GCM library. </td>
+ <td class="jd-descrcol" width="100%">DEPRECATED. </td>
</tr>
<tr class=" api apilevel-" >
<td class="jd-linkcol"><a href="/reference/com/google/android/gcm/GCMRegistrar.html">GCMRegistrar</a></td>
- <td class="jd-descrcol" width="100%">Utilities for device registration. </td>
+ <td class="jd-descrcol" width="100%">DEPRECATED. </td>
</tr>
</table>
</div>
diff --git a/docs/html/reference/gcm-packages.html b/docs/html/reference/gcm-packages.html
index 8065be9..2b5dc2d 100644
--- a/docs/html/reference/gcm-packages.html
+++ b/docs/html/reference/gcm-packages.html
@@ -623,14 +623,15 @@
<tr class="alt-color api apilevel-" >
<td class="jd-linkcol">
<a href="/reference/com/google/android/gcm/package-summary.html">com.google.android.gcm</a></td>
- <td class="jd-descrcol" width="100%"></td>
+ <td class="jd-descrcol" width="100%"><strong>DEPRECATED.</strong> Please use the <a href=
+"http://developer.android.com/reference/com/google/android/gms/gcm/GoogleCloudMessaging.html"><code>GoogleCloudMessaging</code></a> API instead of this client helper library. See <a href="http://developer.android.com/google/gcm/client.html">GCM Client</a> for more information.</td>
</tr>
<tr class=" api apilevel-" >
<td class="jd-linkcol">
<a href="/reference/com/google/android/gcm/server/package-summary.html">com.google.android.gcm.server</a></td>
- <td class="jd-descrcol" width="100%"></td>
+ <td class="jd-descrcol" width="100%">Helper library for GCM HTTP server operations. See <a href="http://developer.android.com/google/gcm/server.html">GCM Server</a> for more information.</td>
</tr>
diff --git a/docs/html/sdk/installing/migrate.jd b/docs/html/sdk/installing/migrate.jd
index 20a698b..db1b5dd 100644
--- a/docs/html/sdk/installing/migrate.jd
+++ b/docs/html/sdk/installing/migrate.jd
@@ -2,6 +2,17 @@
@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+<h2>See also</h2>
+<ul>
+ <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Working+in+Eclipse+Compatibility+Mode" class="external-link"
+ >Eclipse Compatibility Mode</a></li>
+ <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA" class="external-link"
+ >FAQ on Migrating</a></li>
+</ul>
+</div>
+</div>
<p>If you've previously developed for Android using Eclipse and would like to migrate
to Android Studio, you should export your projects from Eclipse in order to generate
diff --git a/docs/html/sdk/installing/studio-tips.jd b/docs/html/sdk/installing/studio-tips.jd
index 259087b..a686efd 100644
--- a/docs/html/sdk/installing/studio-tips.jd
+++ b/docs/html/sdk/installing/studio-tips.jd
@@ -2,6 +2,17 @@
@jd:body
+<div id="qv-wrapper">
+<div id="qv">
+<h2>See also</h2>
+<ul>
+ <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Working+in+Eclipse+Compatibility+Mode" class="external-link"
+ >Eclipse Compatibility Mode</a></li>
+ <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA" class="external-link"
+ >FAQ on Migrating</a></li>
+</ul>
+</div>
+</div>
<p>If you're unfamiliar with the IntelliJ IDEA interface, you might be wondering
how to accomplish some common tasks in Android Studio. This page provides some tips
diff --git a/docs/html/tools/extras/support-library.jd b/docs/html/tools/extras/support-library.jd
index 60168f4..a82a98a 100644
--- a/docs/html/tools/extras/support-library.jd
+++ b/docs/html/tools/extras/support-library.jd
@@ -18,8 +18,7 @@
<h2>See also</h2>
<ol>
<li><a
-href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android 3.0</a></li>
- <li><a href="http://code.google.com/p/iosched/">Google I/O App source code</a></li>
+href="{@docRoot}training/basics/fragments/support-lib.html">Using the Support Library</a></li>
</ol>
</div>
@@ -708,8 +707,8 @@
</div>
<p>For more information about how you can optimize your application for the latest
-Android-powered devices, read <a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing
-Apps for Android 3.0</a>.</p>
+Android-powered devices, read <a href="{@docRoot}guide/practices/tablets-and-handsets.html"
+>Supporting Tablets and Handsets</a>.</p>
<h2 id="Docs">Reference Docs</h2>
diff --git a/docs/html/training/basics/data-storage/databases.jd b/docs/html/training/basics/data-storage/databases.jd
index 61fb758..6ea2140 100644
--- a/docs/html/training/basics/data-storage/databases.jd
+++ b/docs/html/training/basics/data-storage/databases.jd
@@ -73,25 +73,23 @@
<pre>
-public static abstract class FeedEntry implements BaseColumns {
- public static final String TABLE_NAME = "entry";
- public static final String COLUMN_NAME_ENTRY_ID = "entryid";
- public static final String COLUMN_NAME_TITLE = "title";
- public static final String COLUMN_NAME_SUBTITLE = "subtitle";
- ...
+public final class FeedReaderContract {
+ // To prevent someone from accidentally instantiating the contract class,
+ // give it an empty constructor.
+ public FeedReaderContract() {}
+
+ /* Inner class that defines the table contents */
+ public static abstract class FeedEntry implements BaseColumns {
+ public static final String TABLE_NAME = "entry";
+ public static final String COLUMN_NAME_ENTRY_ID = "entryid";
+ public static final String COLUMN_NAME_TITLE = "title";
+ public static final String COLUMN_NAME_SUBTITLE = "subtitle";
+ ...
+ }
}
</pre>
-<p>To prevent someone from accidentally instantiating the contract class, give
-it an empty constructor. </p>
-
-<pre>
-// Prevents the FeedReaderContract class from being instantiated.
-private FeedReaderContract() {}
-</pre>
-
-
<h2 id="DbHelper">Create a Database Using a SQL Helper</h2>
@@ -103,15 +101,15 @@
private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
- "CREATE TABLE " + FeedReaderContract.FeedEntry.TABLE_NAME + " (" +
- FeedReaderContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
- FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
- FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
+ "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
+ FeedEntry._ID + " INTEGER PRIMARY KEY," +
+ FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
+ FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
... // Any other options for the CREATE command
" )";
private static final String SQL_DELETE_ENTRIES =
- "DROP TABLE IF EXISTS " + TABLE_NAME_ENTRIES;
+ "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
</pre>
<p>Just like files that you save on the device's <a
@@ -191,15 +189,15 @@
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
-values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID, id);
-values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title);
-values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_CONTENT, content);
+values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
+values.put(FeedEntry.COLUMN_NAME_TITLE, title);
+values.put(FeedEntry.COLUMN_NAME_CONTENT, content);
// Insert the new row, returning the primary key value of the new row
long newRowId;
newRowId = db.insert(
- FeedReaderContract.FeedEntry.TABLE_NAME,
- FeedReaderContract.FeedEntry.COLUMN_NAME_NULLABLE,
+ FeedEntry.TABLE_NAME,
+ FeedEntry.COLUMN_NAME_NULLABLE,
values);
</pre>
@@ -227,18 +225,18 @@
// Define a <em>projection</em> that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
- FeedReaderContract.FeedEntry._ID,
- FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE,
- FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED,
+ FeedEntry._ID,
+ FeedEntry.COLUMN_NAME_TITLE,
+ FeedEntry.COLUMN_NAME_UPDATED,
...
};
// How you want the results sorted in the resulting Cursor
String sortOrder =
- FeedReaderContract.FeedEntry.COLUMN_NAME_UPDATED + " DESC";
+ FeedEntry.COLUMN_NAME_UPDATED + " DESC";
Cursor c = db.query(
- FeedReaderContract.FeedEntry.TABLE_NAME, // The table to query
+ FeedEntry.TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
@@ -262,7 +260,7 @@
<pre>
cursor.moveToFirst();
long itemId = cursor.getLong(
- cursor.getColumnIndexOrThrow(FeedReaderContract.FeedEntry._ID)
+ cursor.getColumnIndexOrThrow(FeedEntry._ID)
);
</pre>
@@ -282,7 +280,7 @@
<pre>
// Define 'where' part of query.
-String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
+String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
// Specify arguments in placeholder order.
String[] selectionArgs = { String.valueOf(rowId) };
// Issue SQL statement.
@@ -305,10 +303,10 @@
// New value for one column
ContentValues values = new ContentValues();
-values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title);
+values.put(FeedEntry.COLUMN_NAME_TITLE, title);
// Which row to update, based on the ID
-String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
+String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };
int count = db.update(
diff --git a/docs/html/training/location/receive-location-updates.jd b/docs/html/training/location/receive-location-updates.jd
index c33f075..e6e8c51 100644
--- a/docs/html/training/location/receive-location-updates.jd
+++ b/docs/html/training/location/receive-location-updates.jd
@@ -417,7 +417,7 @@
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
// Update frequency in milliseconds
private static final long UPDATE_INTERVAL =
- MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN SECONDS;
+ MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
// A fast frequency ceiling in milliseconds
@@ -425,7 +425,7 @@
MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
...
// Define an object that holds accuracy and frequency parameters
- LocationResult mLocationRequest;
+ LocationRequest mLocationRequest;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -458,9 +458,11 @@
the request by calling
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#requestLocationUpdates(com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">requestLocationUpdates()</a></code>.
Since your client must be connected for your app to receive updates, you should
- connect the client and make the request in
+ connect the client in
{@link android.support.v4.app.FragmentActivity#onStart onStart()}. This ensures that you always
- have a valid, connected client while your app is visible.
+ have a valid, connected client while your app is visible. Since you need a connection before you
+ can request updates, make the update request in
+<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">ConnectionCallbacks.onConnected()</a></code>
</p>
<p>
Remember that the user may want to turn off location updates for various reasons. You should
@@ -536,6 +538,21 @@
}
}
...
+ /*
+ * Called by Location Services when the request to connect the
+ * client finishes successfully. At this point, you can
+ * request the current location or start periodic updates
+ */
+ @Override
+ public void onConnected(Bundle dataBundle) {
+ // Display the connection status
+ Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
+ // If already requested, start periodic updates
+ if (mUpdatesRequested) {
+ mLocationClient.requestLocationUpdates(mLocationRequest, this);
+ }
+ }
+ ...
}
</pre>
<p>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 78ee7c6..deccac1 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -50,29 +50,30 @@
* reuse this bitmap when loading content. If the decode operation cannot
* use this bitmap, the decode method will return <code>null</code> and
* will throw an IllegalArgumentException. The current implementation
- * necessitates that the reused bitmap be mutable and of a size that is
- * equal to or larger than the source content. The source content must be
- * in jpeg or png format (whether as a resource or as a stream). The
- * {@link android.graphics.Bitmap.Config configuration} of the reused
- * bitmap will override the setting of {@link #inPreferredConfig}, if set.
- * The reused bitmap will continue to remain mutable even when decoding a
+ * necessitates that the reused bitmap be mutable, and the resulting
+ * reused bitmap will continue to remain mutable even when decoding a
* resource which would normally result in an immutable bitmap.
*
- * <p>As of {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, the reused
- * bitmap can be used to decode any other bitmaps as long as the resulting
+ * <p>As of {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, any mutable
+ * bitmap can be reused to decode any other bitmaps as long as the resulting
* {@link Bitmap#getByteCount() byte count} of the decoded bitmap is less
* than or equal to the {@link Bitmap#getAllocationByteCount() allocated byte count}
* of the reused bitmap. This can be because the intrinsic size is smaller,
- * or the sampled size is smaller. Prior to
- * {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, only equal sized
- * bitmaps are supported, with {@link #inSampleSize} set to 1.
+ * or the size after density / sampled size scaling is smaller.
+ *
+ * <p>Prior to {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE} additional
+ * constraints apply: The image being decoded (whether as a resource or
+ * as a stream) must be in jpeg or png format. Only equal sized bitmaps
+ * are supported, with {@link #inSampleSize} set to 1. Additionally, the
+ * {@link android.graphics.Bitmap.Config configuration} of the reused
+ * bitmap will override the setting of {@link #inPreferredConfig}, if set.
*
* <p>You should still always use the returned Bitmap of the decode
* method and not assume that reusing the bitmap worked, due to the
* constraints outlined above and failure situations that can occur.
* Checking whether the return value matches the value of the inBitmap
- * set in the Options structure is a way to see if the bitmap was reused,
- * but in all cases you should use the returned Bitmap to make sure
+ * set in the Options structure will indicate if the bitmap was reused,
+ * but in all cases you should use the Bitmap returned by the decoding function to ensure
* that you are using the bitmap that was used as the decode destination.</p>
*/
public Bitmap inBitmap;
@@ -440,6 +441,7 @@
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
+ setDensityFromOptions(bm, opts);
return bm;
}
@@ -457,6 +459,31 @@
}
/**
+ * Set the newly decoded bitmap's density based on the Options.
+ */
+ private static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
+ if (outputBitmap == null || opts == null) return;
+
+ final int density = opts.inDensity;
+ if (density != 0) {
+ outputBitmap.setDensity(density);
+ final int targetDensity = opts.inTargetDensity;
+ if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
+ return;
+ }
+
+ byte[] np = outputBitmap.getNinePatchChunk();
+ final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
+ if (opts.inScaled || isNinePatch) {
+ outputBitmap.setDensity(targetDensity);
+ }
+ } else if (opts.inBitmap != null) {
+ // bitmap was reused, ensure density is reset
+ outputBitmap.setDensity(Bitmap.getDefaultDensity());
+ }
+ }
+
+ /**
* Decode an input stream into a bitmap. If the input stream is null, or
* cannot be used to decode a bitmap, the function returns null.
* The stream's position will be where ever it was after the encoded data
@@ -497,25 +524,7 @@
if (is instanceof AssetManager.AssetInputStream) {
final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
-
- if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
- float scale = 1.0f;
- int targetDensity = 0;
- if (opts != null) {
- final int density = opts.inDensity;
- targetDensity = opts.inTargetDensity;
- if (density != 0 && targetDensity != 0) {
- scale = targetDensity / (float) density;
- }
- }
-
- bm = nativeDecodeAsset(asset, outPadding, opts, true, scale);
- if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
-
- finish = false;
- } else {
- bm = nativeDecodeAsset(asset, outPadding, opts);
- }
+ bm = nativeDecodeAsset(asset, outPadding, opts);
} else {
// pass some temp storage down to the native code. 1024 is made up,
// but should be large enough to avoid too many small calls back
@@ -523,81 +532,18 @@
// to mark(...) above.
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
- if (tempStorage == null) tempStorage = new byte[16 * 1024];
-
- if (opts == null || (opts.inScaled && opts.inBitmap == null)) {
- float scale = 1.0f;
- int targetDensity = 0;
- if (opts != null) {
- final int density = opts.inDensity;
- targetDensity = opts.inTargetDensity;
- if (density != 0 && targetDensity != 0) {
- scale = targetDensity / (float) density;
- }
- }
-
- bm = nativeDecodeStream(is, tempStorage, outPadding, opts, true, scale);
- if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
-
- finish = false;
- } else {
- bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
- }
+ if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
+ bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
}
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
- return finish ? finishDecode(bm, outPadding, opts) : bm;
- }
-
- private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
- if (bm == null || opts == null) {
- return bm;
- }
-
- final int density = opts.inDensity;
- if (density == 0) {
- return bm;
- }
-
- bm.setDensity(density);
- final int targetDensity = opts.inTargetDensity;
- if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
- return bm;
- }
- byte[] np = bm.getNinePatchChunk();
- int[] lb = bm.getLayoutBounds();
- final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
- if (opts.inScaled || isNinePatch) {
- float scale = targetDensity / (float) density;
- if (scale != 1.0f) {
- final Bitmap oldBitmap = bm;
- bm = Bitmap.createScaledBitmap(oldBitmap,
- Math.max(1, (int) (bm.getWidth() * scale + 0.5f)),
- Math.max(1, (int) (bm.getHeight() * scale + 0.5f)), true);
- if (bm != oldBitmap) oldBitmap.recycle();
-
- if (isNinePatch) {
- np = nativeScaleNinePatch(np, scale, outPadding);
- bm.setNinePatchChunk(np);
- }
- if (lb != null) {
- int[] newLb = new int[lb.length];
- for (int i=0; i<lb.length; i++) {
- newLb[i] = (int)((lb[i]*scale)+.5f);
- }
- bm.setLayoutBounds(newLb);
- }
- }
-
- bm.setDensity(targetDensity);
- }
-
+ setDensityFromOptions(bm, opts);
return bm;
}
-
+
/**
* Decode an input stream into a bitmap. If the input stream is null, or
* cannot be used to decode a bitmap, the function returns null.
@@ -632,7 +578,7 @@
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
- return finishDecode(bm, outPadding, opts);
+ return bm;
} else {
FileInputStream fis = new FileInputStream(fd);
try {
@@ -659,8 +605,6 @@
private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
Rect padding, Options opts);
- private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
- Rect padding, Options opts, boolean applyScale, float scale);
private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
Rect padding, Options opts);
private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts);
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bbba778..a1c87cb 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1070,9 +1070,23 @@
*
* @hide
*/
+ public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
+ }
+
+ /**
+ * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
+ *
+ * Note: Only supported by hardware accelerated canvas at the moment.
+ *
+ * @param patch The ninepatch object to render
+ * @param dst The destination rectangle.
+ * @param paint The paint to draw the bitmap with. may be null
+ *
+ * @hide
+ */
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
- }
-
+ }
+
/**
* Draw the specified bitmap, with its top/left corner at (x,y), using
* the specified paint, transformed by the current matrix.
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index f6b747a..972ce47 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -100,6 +100,41 @@
public static final int JPEG = 0x100;
/**
+ * <p>Multi-plane Android YUV format</p>
+ *
+ * <p>This format is a generic YCbCr format, capable of describing any 4:2:0
+ * chroma-subsampled planar or semiplanar buffer, with 8 bits per color
+ * sample.</p>
+ *
+ * <p>Images in this format are always represented by three separate buffers
+ * of data, one for each color plane. Additional information always
+ * accompanies the buffers, describing the row stride and the pixel stride
+ * for each plane.</p>
+ *
+ * <p>For example, the {@link android.media.Image} object can provide data
+ * in this format from a {@link android.hardware.photography.CameraDevice}
+ * through a {@link android.media.ImageReader} object.</p>
+ *
+ * @see android.media.Image
+ * @see android.media.ImageReader
+ * @see android.hardware.camera.CameraDevice
+ */
+ public static final int YUV_420_888 = 0x23;
+
+ /**
+ * <p>General raw camera sensor image format, usually representing a
+ * single-channel Bayer-mosaic image. Each pixel color sample is stored with
+ * 16 bits of precision.</p>
+ *
+ * <p>The layout of the color mosaic, the maximum and minimum encoding
+ * values of the raw pixel data, the color space of the image, and all other
+ * needed information to interpret a raw sensor image must be queried from
+ * the {@link android.hardware.photography.CameraDevice} which produced the
+ * image.</p>
+ */
+ public static final int RAW_SENSOR = 0x201;
+
+ /**
* Raw bayer format used for images, which is 10 bit precision samples
* stored in 16 bit words. The filter pattern is RGGB. Whether this format
* is supported by the camera hardware can be determined by
@@ -129,6 +164,10 @@
return 12;
case NV21:
return 12;
+ case YUV_420_888:
+ return 12;
+ case RAW_SENSOR:
+ return 16;
case BAYER_RGGB:
return 16;
}
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 81e9d84..932e474 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -42,8 +42,18 @@
public final byte[] mChunk;
private Paint mPaint;
private String mSrcName; // Useful for debugging
- private final RectF mRect = new RectF();
-
+
+ /**
+ * Create a drawable projection from a bitmap to nine patches.
+ *
+ * @param bitmap The bitmap describing the patches.
+ * @param chunk The 9-patch data chunk describing how the underlying
+ * bitmap is split apart and drawn.
+ */
+ public NinePatch(Bitmap bitmap, byte[] chunk) {
+ this(bitmap, chunk, null);
+ }
+
/**
* Create a drawable projection from a bitmap to nine patches.
*
@@ -90,13 +100,13 @@
* @param location Where to draw the bitmap.
*/
public void draw(Canvas canvas, RectF location) {
- if (!canvas.isHardwareAccelerated()) {
+ if (canvas.isHardwareAccelerated()) {
+ canvas.drawPatch(this, location, mPaint);
+ } else {
nativeDraw(canvas.mNativeCanvas, location,
mBitmap.ni(), mChunk,
mPaint != null ? mPaint.mNativePaint : 0,
canvas.mDensity, mBitmap.mDensity);
- } else {
- canvas.drawPatch(this, location, mPaint);
}
}
@@ -107,14 +117,13 @@
* @param location Where to draw the bitmap.
*/
public void draw(Canvas canvas, Rect location) {
- if (!canvas.isHardwareAccelerated()) {
+ if (canvas.isHardwareAccelerated()) {
+ canvas.drawPatch(this, location, mPaint);
+ } else {
nativeDraw(canvas.mNativeCanvas, location,
mBitmap.ni(), mChunk,
mPaint != null ? mPaint.mNativePaint : 0,
canvas.mDensity, mBitmap.mDensity);
- } else {
- mRect.set(location);
- canvas.drawPatch(this, mRect, mPaint);
}
}
@@ -126,13 +135,12 @@
* @param paint The Paint to draw through.
*/
public void draw(Canvas canvas, Rect location, Paint paint) {
- if (!canvas.isHardwareAccelerated()) {
+ if (canvas.isHardwareAccelerated()) {
+ canvas.drawPatch(this, location, paint);
+ } else {
nativeDraw(canvas.mNativeCanvas, location,
mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
canvas.mDensity, mBitmap.mDensity);
- } else {
- mRect.set(location);
- canvas.drawPatch(this, mRect, paint);
}
}
@@ -170,6 +178,5 @@
private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
byte[] c, int paint_instance_or_null,
int destDensity, int srcDensity);
- private static native int nativeGetTransparentRegion(
- int bitmap, byte[] chunk, Rect location);
+ private static native int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location);
}
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 7c7cd01..bde978d 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -167,7 +167,7 @@
* @return The Drawable at the specified frame index
*/
public Drawable getFrame(int index) {
- return mAnimationState.getChildren()[index];
+ return mAnimationState.getChild(index);
}
/**
@@ -322,7 +322,7 @@
mDurations = orig.mDurations;
mOneShot = orig.mOneShot;
} else {
- mDurations = new int[getChildren().length];
+ mDurations = new int[getCapacity()];
mOneShot = true;
}
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 762e27d..e75ec75 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -250,18 +250,21 @@
return mCurrDrawable != null ? mCurrDrawable.getMinimumHeight() : 0;
}
+ @Override
public void invalidateDrawable(Drawable who) {
if (who == mCurrDrawable && getCallback() != null) {
getCallback().invalidateDrawable(this);
}
}
+ @Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (who == mCurrDrawable && getCallback() != null) {
getCallback().scheduleDrawable(this, what, when);
}
}
+ @Override
public void unscheduleDrawable(Drawable who, Runnable what) {
if (who == mCurrDrawable && getCallback() != null) {
getCallback().unscheduleDrawable(this, what);
@@ -415,11 +418,7 @@
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- final int N = mDrawableContainerState.getChildCount();
- final Drawable[] drawables = mDrawableContainerState.getChildren();
- for (int i = 0; i < N; i++) {
- if (drawables[i] != null) drawables[i].mutate();
- }
+ mDrawableContainerState.mutate();
mMutated = true;
}
return this;
@@ -544,14 +543,33 @@
return pos;
}
+ final int getCapacity() {
+ return mDrawables.length;
+ }
+
public final int getChildCount() {
return mNumChildren;
}
+ /*
+ * @deprecated Use {@link #getChild} instead.
+ */
public final Drawable[] getChildren() {
return mDrawables;
}
+ public final Drawable getChild(int index) {
+ return mDrawables[index];
+ }
+
+ final void mutate() {
+ final int N = getChildCount();
+ final Drawable[] drawables = mDrawables;
+ for (int i = 0; i < N; i++) {
+ if (drawables[i] != null) drawables[i].mutate();
+ }
+ }
+
/** A boolean value indicating whether to use the maximum padding value of
* all frames in the set (false), or to use the padding value of the frame
* being shown (true). Default value is false.
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index 21be983..872fdce 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -164,8 +164,8 @@
mLows = orig.mLows;
mHighs = orig.mHighs;
} else {
- mLows = new int[getChildren().length];
- mHighs = new int[getChildren().length];
+ mLows = new int[getCapacity()];
+ mHighs = new int[getCapacity()];
}
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index b83815b..86e4bad 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -52,7 +52,7 @@
*/
public class NinePatchDrawable extends Drawable {
// dithering helps a lot, and is pretty cheap, so default is true
- private static final boolean DEFAULT_DITHER = true;
+ private static final boolean DEFAULT_DITHER = false;
private NinePatchState mNinePatchState;
private NinePatch mNinePatch;
private Rect mPadding;
@@ -197,10 +197,8 @@
mBitmapHeight = mNinePatch.getHeight();
mOpticalInsets = mNinePatchState.mOpticalInsets;
} else {
- mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(),
- sdensity, tdensity);
- mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(),
- sdensity, tdensity);
+ mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(), sdensity, tdensity);
+ mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(), sdensity, tdensity);
if (mNinePatchState.mPadding != null && mPadding != null) {
Rect dest = mPadding;
Rect src = mNinePatchState.mPadding;
@@ -271,6 +269,7 @@
@Override
public void setDither(boolean dither) {
+ //noinspection PointlessBooleanExpression
if (mPaint == null && dither == DEFAULT_DITHER) {
// Fast common case -- leave at default dither.
return;
@@ -299,8 +298,7 @@
}
final boolean dither = a.getBoolean(
- com.android.internal.R.styleable.NinePatchDrawable_dither,
- DEFAULT_DITHER);
+ com.android.internal.R.styleable.NinePatchDrawable_dither, DEFAULT_DITHER);
final BitmapFactory.Options options = new BitmapFactory.Options();
if (dither) {
options.inDither = false;
@@ -330,8 +328,7 @@
": <nine-patch> requires a valid 9-patch source image");
}
- setNinePatchState(new NinePatchState(
- new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"),
+ setNinePatchState(new NinePatchState(new NinePatch(bitmap, bitmap.getNinePatchChunk()),
padding, opticalInsets, dither), r);
mNinePatchState.mTargetDensity = mTargetDensity;
@@ -429,7 +426,8 @@
// Copy constructor
NinePatchState(NinePatchState state) {
- mNinePatch = new NinePatch(state.mNinePatch);
+ // Note we don't copy the nine patch because it is immutable.
+ mNinePatch = state.mNinePatch;
// Note we don't copy the padding because it is immutable.
mPadding = state.mPadding;
mOpticalInsets = state.mOpticalInsets;
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f8f3ac9..5ecd296 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -228,7 +228,7 @@
* @see #getStateSet(int)
*/
public Drawable getStateDrawable(int index) {
- return mStateListState.getChildren()[index];
+ return mStateListState.getChild(index);
}
/**
@@ -278,9 +278,9 @@
super(orig, owner, res);
if (orig != null) {
- mStateSets = orig.mStateSets;
+ mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length);
} else {
- mStateSets = new int[getChildren().length][];
+ mStateSets = new int[getCapacity()][];
}
}
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index e1b8c6c..362b586 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -31,46 +31,29 @@
import android.os.Trace;
/**
- * <p>
- * Memory allocation class for renderscript. An allocation combines a
- * {@link android.renderscript.Type} with the memory to provide storage for user data and objects.
- * This implies that all memory in Renderscript is typed.
- * </p>
+ * <p> This class provides the primary method through which data is passed to
+ * and from RenderScript kernels. An Allocation provides the backing store for
+ * a given {@link android.renderscript.Type}. </p>
*
- * <p>Allocations are the primary way data moves into and out of scripts. Memory is user
- * synchronized and it's possible for allocations to exist in multiple memory spaces
- * concurrently. Currently those spaces are:</p>
- * <ul>
- * <li>Script: accessable by RS scripts.</li>
- * <li>Graphics Texture: accessable as a graphics texture.</li>
- * <li>Graphics Vertex: accessable as graphical vertex data.</li>
- * <li>Graphics Constants: Accessable as constants in user shaders</li>
- * </ul>
- * </p>
- * <p>
- * For example, when creating a allocation for a texture, the user can
- * specify its memory spaces as both script and textures. This means that it can both
- * be used as script binding and as a GPU texture for rendering. To maintain
- * synchronization if a script modifies an allocation used by other targets it must
- * call a synchronizing function to push the updates to the memory, otherwise the results
- * are undefined.
- * </p>
- * <p>By default, Android system side updates are always applied to the script accessable
- * memory. If this is not present, they are then applied to the various HW
- * memory types. A {@link android.renderscript.Allocation#syncAll syncAll()}
- * call is necessary after the script data is updated to
- * keep the other memory spaces in sync.</p>
+ * <p>An Allocation also contains a set of usage flags that denote how the
+ * Allocation could be used. For example, an Allocation may have usage flags
+ * specifying that it can be used from a script as well as input to a {@link
+ * android.renderscript.Sampler}. A developer must synchronize across these
+ * different usages using {@link android.renderscript.Allocation#syncAll} in
+ * order to ensure that different users of the Allocation have a consistent view
+ * of memory. For example, in the case where an Allocation is used as the output
+ * of one kernel and as Sampler input in a later kernel, a developer must call
+ * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
+ * second kernel to ensure correctness.
*
- * <p>Allocation data is uploaded in one of two primary ways. For simple
- * arrays there are copyFrom() functions that take an array from the control code and
- * copy it to the slave memory store. Both type checked and unchecked copies are provided.
- * The unchecked variants exist to allow apps to copy over arrays of structures from a
- * control language that does not support structures.</p>
+ * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
+ * more complex Element types, the {@link #copyFromUnchecked} methods can be
+ * used to copy from byte arrays or similar constructs.</p>
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
**/
public class Allocation extends BaseObj {
@@ -98,97 +81,102 @@
new HashMap<Integer, Allocation>();
IoInputNotifier mBufferNotifier;
+ /**
+ * The usage of the Allocation. These signal to RenderScript where to place
+ * the Allocation in memory.
+ *
+ */
/**
- * The usage of the allocation. These signal to renderscript
- * where to place the allocation in memory.
- *
- * SCRIPT The allocation will be bound to and accessed by
- * scripts.
+ * The Allocation will be bound to and accessed by scripts.
*/
public static final int USAGE_SCRIPT = 0x0001;
/**
- * GRAPHICS_TEXTURE The allocation will be used as a texture
- * source by one or more graphics programs.
+ * The Allocation will be used as a texture source by one or more graphics
+ * programs.
*
*/
public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
/**
- * GRAPHICS_VERTEX The allocation will be used as a graphics
- * mesh.
+ * The Allocation will be used as a graphics mesh.
+ *
+ * This was deprecated in API level 16.
*
*/
public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
/**
- * GRAPHICS_CONSTANTS The allocation will be used as the source
- * of shader constants by one or more programs.
+ * The Allocation will be used as the source of shader constants by one or
+ * more programs.
+ *
+ * This was deprecated in API level 16.
*
*/
public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
/**
- * USAGE_GRAPHICS_RENDER_TARGET The allocation will be used as a
- * target for offscreen rendering
+ * The Allocation will be used as a target for offscreen rendering
+ *
+ * This was deprecated in API level 16.
*
*/
public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
/**
- * USAGE_IO_INPUT The allocation will be used as SurfaceTexture
- * consumer. This usage will cause the allocation to be created
- * read only.
+ * The Allocation will be used as a {@link android.graphics.SurfaceTexture}
+ * consumer. This usage will cause the Allocation to be created as
+ * read-only.
*
*/
public static final int USAGE_IO_INPUT = 0x0020;
/**
- * USAGE_IO_OUTPUT The allocation will be used as a
- * SurfaceTexture producer. The dimensions and format of the
- * SurfaceTexture will be forced to those of the allocation.
+ * The Allocation will be used as a {@link android.graphics.SurfaceTexture}
+ * producer. The dimensions and format of the {@link
+ * android.graphics.SurfaceTexture} will be forced to those of the
+ * Allocation.
*
*/
public static final int USAGE_IO_OUTPUT = 0x0040;
/**
- * USAGE_SHARED The allocation's backing store will be inherited
- * from another object (usually a Bitmap); calling appropriate
- * copy methods will be significantly faster than if the entire
- * allocation were copied every time.
+ * The Allocation's backing store will be inherited from another object
+ * (usually a {@link android.graphics.Bitmap}); copying to or from the
+ * original source Bitmap will cause a synchronization rather than a full
+ * copy. {@link #syncAll} may also be used to synchronize the Allocation
+ * and the source Bitmap.
*
- * This is set by default for allocations created with
- * CreateFromBitmap(RenderScript, Bitmap) in API version 18 and
- * higher.
+ * <p>This is set by default for allocations created with {@link
+ * #createFromBitmap} in API version 18 and higher.</p>
*
*/
public static final int USAGE_SHARED = 0x0080;
/**
- * Controls mipmap behavior when using the bitmap creation and
- * update functions.
+ * Controls mipmap behavior when using the bitmap creation and update
+ * functions.
*/
public enum MipmapControl {
/**
- * No mipmaps will be generated and the type generated from the
- * incoming bitmap will not contain additional LODs.
+ * No mipmaps will be generated and the type generated from the incoming
+ * bitmap will not contain additional LODs.
*/
MIPMAP_NONE(0),
/**
- * A Full mipmap chain will be created in script memory. The
- * type of the allocation will contain a full mipmap chain. On
- * upload to graphics the full chain will be transfered.
+ * A full mipmap chain will be created in script memory. The Type of
+ * the Allocation will contain a full mipmap chain. On upload, the full
+ * chain will be transferred.
*/
MIPMAP_FULL(1),
/**
- * The type of the allocation will be the same as MIPMAP_NONE.
- * It will not contain mipmaps. On upload to graphics the
- * graphics copy of the allocation data will contain a full
- * mipmap chain generated from the top level in script memory.
+ * The Type of the Allocation will be the same as MIPMAP_NONE. It will
+ * not contain mipmaps. On upload, the allocation data will contain a
+ * full mipmap chain generated from the top level in script memory.
*/
MIPMAP_ON_SYNC_TO_TEXTURE(2);
@@ -208,10 +196,10 @@
/**
- * Get the element of the type of the Allocation.
+ * Get the {@link android.renderscript.Element} of the {@link
+ * android.renderscript.Type} of the Allocation.
*
- * @return Element that describes the structure of data in the
- * allocation
+ * @return Element
*
*/
public Element getElement() {
@@ -221,8 +209,7 @@
/**
* Get the usage flags of the Allocation.
*
- * @return usage flags associated with the allocation. e.g.
- * script, texture, etc.
+ * @return usage this Allocation's set of the USAGE_* flags OR'd together
*
*/
public int getUsage() {
@@ -351,7 +338,7 @@
}
/**
- * Get the type of the Allocation.
+ * Get the {@link android.renderscript.Type} of the Allocation.
*
* @return Type
*
@@ -361,8 +348,8 @@
}
/**
- * Propagate changes from one usage of the allocation to the
- * remaining usages of the allocation.
+ * Propagate changes from one usage of the Allocation to the
+ * other usages of the Allocation.
*
*/
public void syncAll(int srcLocation) {
@@ -391,8 +378,10 @@
}
/**
- * Send a buffer to the output stream. The contents of the
- * Allocation will be undefined after this operation.
+ * Send a buffer to the output stream. The contents of the Allocation will
+ * be undefined after this operation. This operation is only valid if {@link
+ * #USAGE_IO_OUTPUT} is set on the Allocation.
+ *
*
*/
public void ioSend() {
@@ -415,7 +404,8 @@
}
/**
- * Receive the latest input into the Allocation.
+ * Receive the latest input into the Allocation. This operation
+ * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
*
*/
public void ioReceive() {
@@ -430,7 +420,7 @@
}
/**
- * Copy an array of RS objects to the allocation.
+ * Copy an array of RS objects to the Allocation.
*
* @param d Source array.
*/
@@ -506,9 +496,9 @@
}
/**
- * Copy an allocation from an array. This variant is not type
- * checked which allows an application to fill in structured
- * data from an array.
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
*
* @param d the source data array
*/
@@ -526,9 +516,9 @@
}
/**
- * Copy an allocation from an array. This variant is not type
- * checked which allows an application to fill in structured
- * data from an array.
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
*
* @param d the source data array
*/
@@ -546,9 +536,9 @@
}
/**
- * Copy an allocation from an array. This variant is not type
- * checked which allows an application to fill in structured
- * data from an array.
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
*
* @param d the source data array
*/
@@ -566,9 +556,9 @@
}
/**
- * Copy an allocation from an array. This variant is not type
- * checked which allows an application to fill in structured
- * data from an array.
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
*
* @param d the source data array
*/
@@ -587,9 +577,9 @@
/**
- * Copy an allocation from an array. This variant is type
- * checked and will generate exceptions if the Allocation type
- * is not a 32 bit integer type.
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 32 bit integer type.
*
* @param d the source data array
*/
@@ -607,9 +597,9 @@
}
/**
- * Copy an allocation from an array. This variant is type
- * checked and will generate exceptions if the Allocation type
- * is not a 16 bit integer type.
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 16 bit integer type.
*
* @param d the source data array
*/
@@ -627,9 +617,9 @@
}
/**
- * Copy an allocation from an array. This variant is type
- * checked and will generate exceptions if the Allocation type
- * is not a 8 bit integer type.
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not an 8 bit integer type.
*
* @param d the source data array
*/
@@ -647,9 +637,9 @@
}
/**
- * Copy an allocation from an array. This variant is type
- * checked and will generate exceptions if the Allocation type
- * is not a 32 bit float type.
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 32 bit float type.
*
* @param d the source data array
*/
@@ -667,8 +657,15 @@
}
/**
- * Copy an allocation from a bitmap. The height, width, and
- * format of the bitmap must match the existing allocation.
+ * Copy into an Allocation from a {@link android.graphics.Bitmap}. The
+ * height, width, and format of the bitmap must match the existing
+ * allocation.
+ *
+ * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
+ * android.graphics.Bitmap} used to create the Allocation with {@link
+ * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
+ * this will synchronize the Allocation with the latest data from the {@link
+ * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
*
* @param b the source bitmap
*/
@@ -689,7 +686,7 @@
}
/**
- * Copy an allocation from an allocation. The types of both allocations
+ * Copy an Allocation from an Allocation. The types of both allocations
* must be identical.
*
* @param a the source allocation
@@ -705,8 +702,8 @@
}
/**
- * This is only intended to be used by auto-generate code reflected from the
- * renderscript script files.
+ * This is only intended to be used by auto-generated code reflected from
+ * the RenderScript script files and should not be used by developers.
*
* @param xoff
* @param fp
@@ -725,8 +722,8 @@
}
/**
- * This is only intended to be used by auto-generate code reflected from the
- * renderscript script files.
+ * This is only intended to be used by auto-generated code reflected from
+ * the RenderScript script files.
*
* @param xoff
* @param component_number
@@ -772,23 +769,22 @@
}
/**
- * Generate a mipmap chain. Requires the type of the allocation
- * include mipmaps.
+ * Generate a mipmap chain. This is only valid if the Type of the Allocation
+ * includes mipmaps.
*
- * This function will generate a complete set of mipmaps from
- * the top level lod and place them into the script memoryspace.
+ * <p>This function will generate a complete set of mipmaps from the top
+ * level LOD and place them into the script memory space.</p>
*
- * If the allocation is also using other memory spaces a
- * followup sync will be required.
+ * <p>If the Allocation is also using other memory spaces, a call to {@link
+ * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
*/
public void generateMipmaps() {
mRS.nAllocationGenerateMipmaps(getID(mRS));
}
/**
- * Copy part of an allocation from an array. This variant is
- * not type checked which allows an application to fill in
- * structured data from an array.
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -803,9 +799,8 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * not type checked which allows an application to fill in
- * structured data from an array.
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -820,9 +815,8 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * not type checked which allows an application to fill in
- * structured data from an array.
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -837,9 +831,8 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * not type checked which allows an application to fill in
- * structured data from an array.
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -854,9 +847,9 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * type checked and will generate exceptions if the Allocation
- * type is not a 32 bit integer type.
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 32 bit
+ * integer type.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -870,9 +863,9 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * type checked and will generate exceptions if the Allocation
- * type is not a 16 bit integer type.
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 16 bit
+ * integer type.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -886,9 +879,9 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * type checked and will generate exceptions if the Allocation
- * type is not a 8 bit integer type.
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not an 8 bit
+ * integer type.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -902,9 +895,9 @@
}
/**
- * Copy part of an allocation from an array. This variant is
- * type checked and will generate exceptions if the Allocation
- * type is not a 32 bit float type.
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 32 bit float
+ * type.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -917,7 +910,7 @@
Trace.traceEnd(RenderScript.TRACE_TAG);
}
/**
- * Copy part of an allocation from another allocation.
+ * Copy part of an Allocation into this Allocation.
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
@@ -987,14 +980,14 @@
}
/**
- * Copy a rectangular region from the array into the allocation.
- * The incoming array is assumed to be tightly packed.
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
*
- * @param xoff X offset of the region to update
- * @param yoff Y offset of the region to update
- * @param w Width of the incoming region to update
- * @param h Height of the incoming region to update
- * @param data to be placed into the allocation
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
@@ -1003,6 +996,16 @@
Trace.traceEnd(RenderScript.TRACE_TAG);
}
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsInt16();
@@ -1010,6 +1013,16 @@
Trace.traceEnd(RenderScript.TRACE_TAG);
}
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsInt32();
@@ -1017,6 +1030,16 @@
Trace.traceEnd(RenderScript.TRACE_TAG);
}
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsFloat32();
@@ -1025,16 +1048,16 @@
}
/**
- * Copy a rectangular region into the allocation from another
- * allocation.
+ * Copy a rectangular region from an Allocation into a rectangular region in
+ * this Allocation.
*
- * @param xoff X offset of the region to update.
- * @param yoff Y offset of the region to update.
- * @param w Width of the incoming region to update.
- * @param h Height of the incoming region to update.
- * @param data source allocation.
- * @param dataXoff X offset in data of the region to update.
- * @param dataYoff Y offset in data of the region to update.
+ * @param xoff X offset of the region in this Allocation
+ * @param yoff Y offset of the region in this Allocation
+ * @param w Width of the region to update.
+ * @param h Height of the region to update.
+ * @param data source Allocation.
+ * @param dataXoff X offset in source Allocation
+ * @param dataYoff Y offset in source Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
Allocation data, int dataXoff, int dataYoff) {
@@ -1049,13 +1072,13 @@
}
/**
- * Copy a bitmap into an allocation. The height and width of
- * the update will use the height and width of the incoming
- * bitmap.
+ * Copy a {@link android.graphics.Bitmap} into an Allocation. The height
+ * and width of the update will use the height and width of the {@link
+ * android.graphics.Bitmap}.
*
- * @param xoff X offset of the region to update
- * @param yoff Y offset of the region to update
- * @param data the bitmap to be copied
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param data the Bitmap to be copied
*/
public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
@@ -1138,14 +1161,14 @@
/**
* @hide
* Copy a rectangular region from the array into the allocation.
- * The incoming array is assumed to be tightly packed.
+ * The array is assumed to be tightly packed.
*
- * @param xoff X offset of the region to update
- * @param yoff Y offset of the region to update
- * @param zoff Z offset of the region to update
- * @param w Width of the incoming region to update
- * @param h Height of the incoming region to update
- * @param d Depth of the incoming region to update
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param zoff Z offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param d Depth of the region to update
* @param data to be placed into the allocation
*/
public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) {
@@ -1185,15 +1208,16 @@
* Copy a rectangular region into the allocation from another
* allocation.
*
- * @param xoff X offset of the region to update.
- * @param yoff Y offset of the region to update.
- * @param w Width of the incoming region to update.
- * @param h Height of the incoming region to update.
- * @param d Depth of the incoming region to update.
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param zoff Z offset of the region to update in this Allocation
+ * @param w Width of the region to update.
+ * @param h Height of the region to update.
+ * @param d Depth of the region to update.
* @param data source allocation.
- * @param dataXoff X offset in data of the region to update.
- * @param dataYoff Y offset in data of the region to update.
- * @param dataZoff Z offset in data of the region to update
+ * @param dataXoff X offset of the region in the source Allocation
+ * @param dataYoff Y offset of the region in the source Allocation
+ * @param dataZoff Z offset of the region in the source Allocation
*/
public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
Allocation data, int dataXoff, int dataYoff, int dataZoff) {
@@ -1206,8 +1230,8 @@
/**
- * Copy from the Allocation into a Bitmap. The bitmap must
- * match the dimensions of the Allocation.
+ * Copy from the Allocation into a {@link android.graphics.Bitmap}. The
+ * bitmap must match the dimensions of the Allocation.
*
* @param b The bitmap to be set from the Allocation.
*/
@@ -1221,9 +1245,9 @@
}
/**
- * Copy from the Allocation into a byte array. The array must
- * be at least as large as the Allocation. The allocation must
- * be of an 8 bit elemental type.
+ * Copy from the Allocation into a byte array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 8 bit integer
+ * {@link android.renderscript.Element} type.
*
* @param d The array to be set from the Allocation.
*/
@@ -1236,9 +1260,9 @@
}
/**
- * Copy from the Allocation into a short array. The array must
- * be at least as large as the Allocation. The allocation must
- * be of an 16 bit elemental type.
+ * Copy from the Allocation into a short array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 16 bit integer
+ * {@link android.renderscript.Element} type.
*
* @param d The array to be set from the Allocation.
*/
@@ -1251,9 +1275,9 @@
}
/**
- * Copy from the Allocation into a int array. The array must be
- * at least as large as the Allocation. The allocation must be
- * of an 32 bit elemental type.
+ * Copy from the Allocation into a int array. The array must be at least as
+ * large as the Allocation. The allocation must be of an 32 bit integer
+ * {@link android.renderscript.Element} type.
*
* @param d The array to be set from the Allocation.
*/
@@ -1266,9 +1290,9 @@
}
/**
- * Copy from the Allocation into a float array. The array must
- * be at least as large as the Allocation. The allocation must
- * be of an 32 bit float elemental type.
+ * Copy from the Allocation into a float array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 32 bit float
+ * {@link android.renderscript.Element} type.
*
* @param d The array to be set from the Allocation.
*/
@@ -1281,20 +1305,19 @@
}
/**
- * Resize a 1D allocation. The contents of the allocation are
- * preserved. If new elements are allocated objects are created
- * with null contents and the new region is otherwise undefined.
+ * Resize a 1D allocation. The contents of the allocation are preserved.
+ * If new elements are allocated objects are created with null contents and
+ * the new region is otherwise undefined.
*
- * If the new region is smaller the references of any objects
- * outside the new region will be released.
+ * <p>If the new region is smaller the references of any objects outside the
+ * new region will be released.</p>
*
- * A new type will be created with the new dimension.
+ * <p>A new type will be created with the new dimension.</p>
*
* @param dimX The new size of the allocation.
*
- * @deprecated Renderscript objects should be immutable once
- * created. The replacement is to create a new allocation and copy the
- * contents.
+ * @deprecated RenderScript objects should be immutable once created. The
+ * replacement is to create a new allocation and copy the contents.
*/
public synchronized void resize(int dimX) {
if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
@@ -1318,11 +1341,13 @@
}
/**
+ * Creates a new Allocation with the given {@link
+ * android.renderscript.Type}, mipmap flag, and usage flags.
*
- * @param type renderscript type describing data layout
+ * @param type RenderScript type describing data layout
* @param mips specifies desired mipmap behaviour for the
* allocation
- * @param usage bit field specifying how the allocation is
+ * @param usage bit field specifying how the Allocation is
* utilized
*/
static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
@@ -1340,8 +1365,8 @@
}
/**
- * Creates a renderscript allocation with the size specified by
- * the type and no mipmaps generated by default
+ * Creates an Allocation with the size specified by the type and no mipmaps
+ * generated by default
*
* @param rs Context to which the allocation will belong.
* @param type renderscript type describing data layout
@@ -1355,12 +1380,11 @@
}
/**
- * Creates a renderscript allocation for use by the script with
- * the size specified by the type and no mipmaps generated by
- * default
+ * Creates an Allocation for use by scripts with a given {@link
+ * android.renderscript.Type} and no mipmaps
*
- * @param rs Context to which the allocation will belong.
- * @param type renderscript type describing data layout
+ * @param rs Context to which the Allocation will belong.
+ * @param type RenderScript Type describing data layout
*
* @return allocation
*/
@@ -1369,13 +1393,12 @@
}
/**
- * Creates a renderscript allocation with a specified number of
- * given elements
+ * Creates an Allocation with a specified number of given elements
*
- * @param rs Context to which the allocation will belong.
- * @param e describes what each element of an allocation is
- * @param count specifies the number of element in the allocation
- * @param usage bit field specifying how the allocation is
+ * @param rs Context to which the Allocation will belong.
+ * @param e Element to use in the Allocation
+ * @param count the number of Elements in the Allocation
+ * @param usage bit field specifying how the Allocation is
* utilized
*
* @return allocation
@@ -1397,12 +1420,11 @@
}
/**
- * Creates a renderscript allocation with a specified number of
- * given elements
+ * Creates an Allocation with a specified number of given elements
*
- * @param rs Context to which the allocation will belong.
- * @param e describes what each element of an allocation is
- * @param count specifies the number of element in the allocation
+ * @param rs Context to which the Allocation will belong.
+ * @param e Element to use in the Allocation
+ * @param count the number of Elements in the Allocation
*
* @return allocation
*/
@@ -1438,16 +1460,16 @@
}
/**
- * Creates a renderscript allocation from a bitmap
+ * Creates an Allocation from a {@link android.graphics.Bitmap}.
*
* @param rs Context to which the allocation will belong.
- * @param b bitmap source for the allocation data
+ * @param b Bitmap source for the allocation data
* @param mips specifies desired mipmap behaviour for the
* allocation
* @param usage bit field specifying how the allocation is
* utilized
*
- * @return renderscript allocation containing bitmap data
+ * @return Allocation containing bitmap data
*
*/
static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
@@ -1494,9 +1516,9 @@
}
/**
- * For allocations used with io operations, returns the handle
- * onto a raw buffer that is being managed by the screen
- * compositor.
+ * Returns the handle to a raw buffer that is being managed by the screen
+ * compositor. This operation is only valid for Allocations with {@link
+ * #USAGE_IO_INPUT}.
*
* @return Surface object associated with allocation
*
@@ -1516,7 +1538,8 @@
}
/**
- * Associate a surface for io output with this allocation
+ * Associate a {@link android.view.Surface} with this Allocation. This
+ * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
*
* @param sur Surface to associate with allocation
*/
@@ -1530,16 +1553,17 @@
}
/**
- * Creates a RenderScript allocation from a bitmap.
+ * Creates an Allocation from a {@link android.graphics.Bitmap}.
*
- * With target API version 18 or greater, this allocation will be
- * created with USAGE_SHARED. With target API version 17 or lower,
- * this allocation will be created with USAGE_GRAPHICS_TEXTURE.
+ * <p>With target API version 18 or greater, this Allocation will be created
+ * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
+ * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
+ * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
*
* @param rs Context to which the allocation will belong.
* @param b bitmap source for the allocation data
*
- * @return renderscript allocation containing bitmap data
+ * @return Allocation containing bitmap data
*
*/
static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
@@ -1552,12 +1576,13 @@
}
/**
- * Creates a cubemap allocation from a bitmap containing the
- * horizontal list of cube faces. Each individual face must be
- * the same size and power of 2
+ * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
+ * containing the horizontal list of cube faces. Each face must be a square,
+ * have the same size as all other faces, and have a width that is a power
+ * of 2.
*
* @param rs Context to which the allocation will belong.
- * @param b bitmap with cubemap faces layed out in the following
+ * @param b Bitmap with cubemap faces layed out in the following
* format: right, left, top, bottom, front, back
* @param mips specifies desired mipmap behaviour for the cubemap
* @param usage bit field specifying how the cubemap is utilized
@@ -1600,10 +1625,10 @@
}
/**
- * Creates a non-mipmapped cubemap allocation for use as a
- * graphics texture from a bitmap containing the horizontal list
- * of cube faces. Each individual face must be the same size and
- * power of 2
+ * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
+ * from a {@link android.graphics.Bitmap} containing the horizontal list of
+ * cube faces. Each face must be a square, have the same size as all other
+ * faces, and have a width that is a power of 2.
*
* @param rs Context to which the allocation will belong.
* @param b bitmap with cubemap faces layed out in the following
@@ -1619,9 +1644,9 @@
}
/**
- * Creates a cubemap allocation from 6 bitmaps containing
- * the cube faces. All the faces must be the same size and
- * power of 2
+ * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
+ * objects containing the cube faces. Each face must be a square, have the
+ * same size as all other faces, and have a width that is a power of 2.
*
* @param rs Context to which the allocation will belong.
* @param xpos cubemap face in the positive x direction
@@ -1686,10 +1711,10 @@
}
/**
- * Creates a non-mipmapped cubemap allocation for use as a
- * graphics texture from 6 bitmaps containing
- * the cube faces. All the faces must be the same size and
- * power of 2
+ * Creates a non-mipmapped cubemap Allocation for use as a sampler input
+ * from 6 {@link android.graphics.Bitmap} objects containing the cube
+ * faces. Each face must be a square, have the same size as all other faces,
+ * and have a width that is a power of 2.
*
* @param rs Context to which the allocation will belong.
* @param xpos cubemap face in the positive x direction
@@ -1715,8 +1740,8 @@
}
/**
- * Creates a renderscript allocation from the bitmap referenced
- * by resource id
+ * Creates an Allocation from the Bitmap referenced
+ * by resource ID.
*
* @param rs Context to which the allocation will belong.
* @param res application resources
@@ -1726,7 +1751,7 @@
* @param usage bit field specifying how the allocation is
* utilized
*
- * @return renderscript allocation containing resource data
+ * @return Allocation containing resource data
*
*/
static public Allocation createFromBitmapResource(RenderScript rs,
@@ -1746,18 +1771,19 @@
}
/**
- * Creates a non-mipmapped renderscript allocation to use as a
- * graphics texture from the bitmap referenced by resource id
+ * Creates a non-mipmapped Allocation to use as a graphics texture from the
+ * {@link android.graphics.Bitmap} referenced by resource ID.
*
- * With target API version 18 or greater, this allocation will be
- * created with USAGE_SHARED. With target API version 17 or lower,
- * this allocation will be created with USAGE_GRAPHICS_TEXTURE.
+ * <p>With target API version 18 or greater, this allocation will be created
+ * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
+ * target API version 17 or lower, this allocation will be created with
+ * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
*
* @param rs Context to which the allocation will belong.
* @param res application resources
* @param id resource id to load the data from
*
- * @return renderscript allocation containing resource data
+ * @return Allocation containing resource data
*
*/
static public Allocation createFromBitmapResource(RenderScript rs,
@@ -1774,8 +1800,7 @@
}
/**
- * Creates a renderscript allocation containing string data
- * encoded in UTF-8 format
+ * Creates an Allocation containing string data encoded in UTF-8 format.
*
* @param rs Context to which the allocation will belong.
* @param str string to create the allocation from
@@ -1802,11 +1827,10 @@
/**
* @hide
*
- * Interface to handle notification when new buffers are
- * available via USAGE_IO_INPUT. An application will receive
- * one notification when a buffer is available. Additional
- * buffers will not trigger new notifications until a buffer is
- * processed.
+ * Interface to handle notification when new buffers are available via
+ * {@link #USAGE_IO_INPUT}. An application will receive one notification
+ * when a buffer is available. Additional buffers will not trigger new
+ * notifications until a buffer is processed.
*/
public interface IoInputNotifier {
public void onBufferAvailable(Allocation a);
@@ -1815,7 +1839,7 @@
/**
* @hide
*
- * Set a notification handler for USAGE_IO_INPUT
+ * Set a notification handler for {@link #USAGE_IO_INPUT}.
*
* @param callback instance of the IoInputNotifier class to be called
* when buffer arrive.
@@ -1839,4 +1863,3 @@
}
-
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index 85d86e5..a6645bb 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -22,6 +22,7 @@
import android.util.TypedValue;
/**
+ * Only intended for use by generated reflected code.
*
**/
public class AllocationAdapter extends Allocation {
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index f464f9b..e17d79a 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -19,9 +19,9 @@
import android.util.Log;
/**
- * BaseObj is the base class for interfacing with native renderscript objects.
- * It primarly contains code for tracking the native object ID and forcably
- * disconecting the object from the native allocation for early cleanup.
+ * BaseObj is the base class for all RenderScript objects owned by a RS context.
+ * It is responsible for lifetime management and resource tracking. This class
+ * should not be used by a user application.
*
**/
public class BaseObj {
@@ -75,8 +75,7 @@
/**
* setName assigns a name to an object. This object can later be looked up
- * by this name. This name will also be retained if the object is written
- * to an A3D file.
+ * by this name.
*
* @param name The name to assign to the object.
*/
@@ -125,10 +124,9 @@
}
/**
- * destroy disconnects the object from the native object effectively
- * rendering this java object dead. The primary use is to force immediate
- * cleanup of resources when it is believed the GC will not respond quickly
- * enough.
+ * Frees any native resources associated with this object. The
+ * primary use is to force immediate cleanup of resources when it is
+ * believed the GC will not respond quickly enough.
*/
synchronized public void destroy() {
if(mDestroyed) {
diff --git a/graphics/java/android/renderscript/Byte2.java b/graphics/java/android/renderscript/Byte2.java
index 7df5f2e..cf34f3a 100644
--- a/graphics/java/android/renderscript/Byte2.java
+++ b/graphics/java/android/renderscript/Byte2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript byte2 type back to the Android system.
+ * Class for exposing the native RenderScript byte2 type back to the Android system.
*
**/
public class Byte2 {
diff --git a/graphics/java/android/renderscript/Byte3.java b/graphics/java/android/renderscript/Byte3.java
index 02a01c1..266e94d 100644
--- a/graphics/java/android/renderscript/Byte3.java
+++ b/graphics/java/android/renderscript/Byte3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript byte3 type back to the Android system.
+ * Class for exposing the native RenderScript byte3 type back to the Android system.
*
**/
public class Byte3 {
diff --git a/graphics/java/android/renderscript/Byte4.java b/graphics/java/android/renderscript/Byte4.java
index a55a696..68c8f52 100644
--- a/graphics/java/android/renderscript/Byte4.java
+++ b/graphics/java/android/renderscript/Byte4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript byte4 type back to the Android system.
+ * Class for exposing the native RenderScript byte4 type back to the Android system.
*
**/
public class Byte4 {
diff --git a/graphics/java/android/renderscript/Double2.java b/graphics/java/android/renderscript/Double2.java
index 9f4f328..29fd515 100644
--- a/graphics/java/android/renderscript/Double2.java
+++ b/graphics/java/android/renderscript/Double2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript double2 type back
+ * Class for exposing the native RenderScript double2 type back
* to the Android system.
*
**/
diff --git a/graphics/java/android/renderscript/Double3.java b/graphics/java/android/renderscript/Double3.java
index eb55142..818952e 100644
--- a/graphics/java/android/renderscript/Double3.java
+++ b/graphics/java/android/renderscript/Double3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript double3 type back
+ * Class for exposing the native RenderScript double3 type back
* to the Android system.
*
**/
diff --git a/graphics/java/android/renderscript/Double4.java b/graphics/java/android/renderscript/Double4.java
index 4755a76..7775ab7 100644
--- a/graphics/java/android/renderscript/Double4.java
+++ b/graphics/java/android/renderscript/Double4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript double4 type back
+ * Class for exposing the native RenderScript double4 type back
* to the Android system.
*
**/
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index f6c07d1..3838c61 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -20,31 +20,37 @@
import android.util.Log;
/**
- * <p>The most basic data type. An element represents one cell of a memory allocation.
- * Element is the basic data type of Renderscript. An element can be of two forms: Basic elements or Complex forms.
- * Examples of basic elements are:</p>
- * <ul>
- * <li>Single float value</li>
- * <li>4 element float vector</li>
- * <li>single RGB-565 color</li>
- * <li>single unsigned int 16</li>
- * </ul>
- * <p>Complex elements contain a list of sub-elements and names that
- * represents a structure of data. The fields can be accessed by name
- * from a script or shader. The memory layout is defined and ordered. Data
- * alignment is determined by the most basic primitive type. i.e. a float4
- * vector will be aligned to sizeof(float) and not sizeof(float4). The
- * ordering of elements in memory will be the order in which they were added
- * with each component aligned as necessary. No re-ordering will be done.</p>
+ * <p>An Element represents one item within an {@link
+ * android.renderscript.Allocation}. An Element is roughly equivalent to a C
+ * type in a RenderScript kernel. Elements may be basic or complex. Some basic
+ * elements are</p> <ul> <li>A single float value (equivalent to a float in a
+ * kernel)</li> <li>A four-element float vector (equivalent to a float4 in a
+ * kernel)</li> <li>An unsigned 32-bit integer (equivalent to an unsigned int in
+ * a kernel)</li> <li>A single signed 8-bit integer (equivalent to a char in a
+ * kernel)</li> </ul> <p>A complex element is roughly equivalent to a C struct
+ * and contains a number of basic or complex Elements. From Java code, a complex
+ * element contains a list of sub-elements and names that represents a
+ * particular data structure. Structs used in RS scripts are available to Java
+ * code by using the {@code ScriptField_structname} class that is reflected from
+ * a particular script.</p>
*
- * <p>The primary source of elements are from scripts. A script that exports a
- * bind point for a data structure generates a Renderscript element to represent the
- * data exported by the script. The other common source of elements is from bitmap formats.</p>
+ * <p>Basic Elements are comprised of a {@link
+ * android.renderscript.Element.DataType} and a {@link
+ * android.renderscript.Element.DataKind}. The DataType encodes C type
+ * information of an Element, while the DataKind encodes how that Element should
+ * be interpreted by a {@link android.renderscript.Sampler}. Note that {@link
+ * android.renderscript.Allocation} objects with DataKind {@link
+ * android.renderscript.Element.DataKind#USER} cannot be used as input for a
+ * {@link android.renderscript.Sampler}. In general, {@link
+ * android.renderscript.Allocation} objects that are intended for use with a
+ * {@link android.renderscript.Sampler} should use bitmap-derived Elements such
+ * as {@link android.renderscript.Element#RGBA_8888} or {@link
+ * android.renderscript#Element.A_8}.</p>
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
**/
public class Element extends BaseObj {
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index 730d973..fed97d6 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -21,7 +21,7 @@
/**
* Utility class for packing arguments and structures from Android system objects to
- * Renderscript objects.
+ * RenderScript objects.
*
* This class is only intended to be used to support the
* reflected code generated by the RS tool chain. It should not
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index 8b0222a..e41f02d 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -30,9 +30,9 @@
/**
* @hide
* @deprecated in API 16
- * FileA3D allows users to load Renderscript objects from files
+ * FileA3D allows users to load RenderScript objects from files
* or resources stored on disk. It could be used to load items
- * such as 3D geometry data converted to a Renderscript format from
+ * such as 3D geometry data converted to a RenderScript format from
* content creation tools. Currently only meshes are supported
* in FileA3D.
*
@@ -56,7 +56,7 @@
UNKNOWN (0),
/**
* @deprecated in API 16
- * Renderscript Mesh object
+ * RenderScript Mesh object
**/
MESH (1);
@@ -72,7 +72,7 @@
/**
* @deprecated in API 16
- * IndexEntry contains information about one of the Renderscript
+ * IndexEntry contains information about one of the RenderScript
* objects inside the file's index. It could be used to query the
* object's type and also name and load the object itself if
* necessary.
diff --git a/graphics/java/android/renderscript/Float2.java b/graphics/java/android/renderscript/Float2.java
index 1d4ce36..0f730fe 100644
--- a/graphics/java/android/renderscript/Float2.java
+++ b/graphics/java/android/renderscript/Float2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript float2 type back to the Android system.
+ * Class for exposing the native RenderScript float2 type back to the Android system.
*
**/
public class Float2 {
diff --git a/graphics/java/android/renderscript/Float3.java b/graphics/java/android/renderscript/Float3.java
index ffd1135..749865f1 100644
--- a/graphics/java/android/renderscript/Float3.java
+++ b/graphics/java/android/renderscript/Float3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript float2 type back to the Android system.
+ * Class for exposing the native RenderScript float2 type back to the Android system.
*
**/
public class Float3 {
diff --git a/graphics/java/android/renderscript/Float4.java b/graphics/java/android/renderscript/Float4.java
index c7cc3ae..7ddf6aa 100644
--- a/graphics/java/android/renderscript/Float4.java
+++ b/graphics/java/android/renderscript/Float4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript float2 type back to the Android system.
+ * Class for exposing the native RenderScript float2 type back to the Android system.
*
**/
public class Float4 {
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index 1a8d5bf..0375d2b 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -39,7 +39,7 @@
* faces, and different font sizes. During creation, the Android system quieries device's screen DPI to
* ensure proper sizing across multiple device configurations.</p>
* <p>Fonts are rendered using screen-space positions and no state setup beyond binding a
- * font to the Renderscript is required. A note of caution on performance, though the state changes
+ * font to the RenderScript is required. A note of caution on performance, though the state changes
* are transparent to the user, they do happen internally, and it is more efficient to
* render large batches of text in sequence. It is also more efficient to render multiple
* characters at once instead of one by one to improve draw call batching.</p>
diff --git a/graphics/java/android/renderscript/Int2.java b/graphics/java/android/renderscript/Int2.java
index 434af21..71b5dd5 100644
--- a/graphics/java/android/renderscript/Int2.java
+++ b/graphics/java/android/renderscript/Int2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript int2 type back to the Android system.
+ * Class for exposing the native RenderScript int2 type back to the Android system.
*
**/
public class Int2 {
diff --git a/graphics/java/android/renderscript/Int3.java b/graphics/java/android/renderscript/Int3.java
index 333ccf8..719c908 100644
--- a/graphics/java/android/renderscript/Int3.java
+++ b/graphics/java/android/renderscript/Int3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript int3 type back to the Android system.
+ * Class for exposing the native RenderScript int3 type back to the Android system.
*
**/
public class Int3 {
diff --git a/graphics/java/android/renderscript/Int4.java b/graphics/java/android/renderscript/Int4.java
index 8734c95..eefb349 100644
--- a/graphics/java/android/renderscript/Int4.java
+++ b/graphics/java/android/renderscript/Int4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript int4 type back to the Android system.
+ * Class for exposing the native RenderScript int4 type back to the Android system.
*
**/
public class Int4 {
diff --git a/graphics/java/android/renderscript/Long2.java b/graphics/java/android/renderscript/Long2.java
index 95ea18c..bd8382d 100644
--- a/graphics/java/android/renderscript/Long2.java
+++ b/graphics/java/android/renderscript/Long2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript long2 type back to the Android system.
+ * Class for exposing the native RenderScript long2 type back to the Android system.
**/
public class Long2 {
public Long2() {
diff --git a/graphics/java/android/renderscript/Long3.java b/graphics/java/android/renderscript/Long3.java
index 96ee885..3e94942 100644
--- a/graphics/java/android/renderscript/Long3.java
+++ b/graphics/java/android/renderscript/Long3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript long3 type back to the Android system.
+ * Class for exposing the native RenderScript long3 type back to the Android system.
**/
public class Long3 {
public Long3() {
diff --git a/graphics/java/android/renderscript/Long4.java b/graphics/java/android/renderscript/Long4.java
index 50e664c..00fb7e6 100644
--- a/graphics/java/android/renderscript/Long4.java
+++ b/graphics/java/android/renderscript/Long4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript long4 type back to the Android system.
+ * Class for exposing the native RenderScript long4 type back to the Android system.
**/
public class Long4 {
public Long4() {
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index 39abd4f..d3621fa 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript rs_matrix2x2 type back to the Android system.
+ * Class for exposing the native RenderScript rs_matrix2x2 type back to the Android system.
*
**/
public class Matrix2f {
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 5e9a7ca..8c3c330 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript rs_matrix3x3 type back to the Android system.
+ * Class for exposing the native RenderScript rs_matrix3x3 type back to the Android system.
*
**/
public class Matrix3f {
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index 4600424..cd18e30 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript rs_matrix4x4 type back to the Android system.
+ * Class for exposing the native RenderScript rs_matrix4x4 type back to the Android system.
*
**/
public class Matrix4f {
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index d0d383d..bca4aa3 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -24,7 +24,7 @@
* @hide
* @deprecated in API 16
* <p>This class is a container for geometric data displayed with
- * Renderscript. Internally, a mesh is a collection of allocations that
+ * RenderScript. Internally, a mesh is a collection of allocations that
* represent vertex data (positions, normals, texture
* coordinates) and index data such as triangles and lines. </p>
* <p>
@@ -32,7 +32,7 @@
* allocation that is provided separately, as multiple allocation
* objects, or done as a combination of both. When a
* vertex channel name matches an input in the vertex program,
- * Renderscript automatically connects the two together.
+ * RenderScript automatically connects the two together.
* </p>
* <p>
* Parts of the mesh can be rendered with either explicit
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index 9bd103e..bc2ca35 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -276,7 +276,7 @@
try {
mShader = new String(str, 0, strLength, "UTF-8");
} catch (UnsupportedEncodingException e) {
- Log.e("Renderscript shader creation", "Could not decode shader string");
+ Log.e("RenderScript shader creation", "Could not decode shader string");
}
return this;
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index dd0f9f5..b9ba3fd 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -23,7 +23,7 @@
/**
* @hide
* @deprecated in API 16
- * <p>The Renderscript fragment program, also known as fragment shader is responsible
+ * <p>The RenderScript fragment program, also known as fragment shader is responsible
* for manipulating pixel data in a user defined way. It's constructed from a GLSL
* shader string containing the program body, textures inputs, and a Type object
* that describes the constants used by the program. Similar to the vertex programs,
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 50e32f6..1c5a191 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -16,9 +16,9 @@
/**
* @hide
- * <p>The Renderscript vertex program, also known as a vertex shader, describes a stage in
+ * <p>The RenderScript vertex program, also known as a vertex shader, describes a stage in
* the graphics pipeline responsible for manipulating geometric data in a user-defined way.
- * The object is constructed by providing the Renderscript system with the following data:</p>
+ * The object is constructed by providing the RenderScript system with the following data:</p>
* <ul>
* <li>Element describing its varying inputs or attributes</li>
* <li>GLSL shader string that defines the body of the program</li>
@@ -28,7 +28,7 @@
* <p>Once the program is created, you bind it to the graphics context, RenderScriptGL, and it will be used for
* all subsequent draw calls until you bind a new program. If the program has constant inputs,
* the user needs to bind an allocation containing those inputs. The allocation's type must match
- * the one provided during creation. The Renderscript library then does all the necessary plumbing
+ * the one provided during creation. The RenderScript library then does all the necessary plumbing
* to send those constants to the graphics hardware. Varying inputs to the shader, such as position, normal,
* and texture coordinates are matched by name between the input Element and the Mesh object being drawn.
* The signatures don't have to be exact or in any strict order. As long as the input name in the shader
diff --git a/graphics/java/android/renderscript/RSDriverException.java b/graphics/java/android/renderscript/RSDriverException.java
index ce85b53..9e6507f 100644
--- a/graphics/java/android/renderscript/RSDriverException.java
+++ b/graphics/java/android/renderscript/RSDriverException.java
@@ -19,7 +19,7 @@
/**
* Base class for all exceptions thrown by the Android
- * Renderscript
+ * RenderScript
*/
public class RSDriverException extends RSRuntimeException {
public RSDriverException(String string) {
diff --git a/graphics/java/android/renderscript/RSIllegalArgumentException.java b/graphics/java/android/renderscript/RSIllegalArgumentException.java
index 954c0e8..5c68594 100644
--- a/graphics/java/android/renderscript/RSIllegalArgumentException.java
+++ b/graphics/java/android/renderscript/RSIllegalArgumentException.java
@@ -19,7 +19,7 @@
/**
* Base class for all exceptions thrown by the Android
- * Renderscript
+ * RenderScript
*/
public class RSIllegalArgumentException extends RSRuntimeException {
public RSIllegalArgumentException(String string) {
diff --git a/graphics/java/android/renderscript/RSInvalidStateException.java b/graphics/java/android/renderscript/RSInvalidStateException.java
index 691aeba..c881898 100644
--- a/graphics/java/android/renderscript/RSInvalidStateException.java
+++ b/graphics/java/android/renderscript/RSInvalidStateException.java
@@ -19,7 +19,7 @@
/**
* Base class for all exceptions thrown by the Android
- * Renderscript
+ * RenderScript
*/
public class RSInvalidStateException extends RSRuntimeException {
public RSInvalidStateException(String string) {
diff --git a/graphics/java/android/renderscript/RSRuntimeException.java b/graphics/java/android/renderscript/RSRuntimeException.java
index 5a16478..b4b629e 100644
--- a/graphics/java/android/renderscript/RSRuntimeException.java
+++ b/graphics/java/android/renderscript/RSRuntimeException.java
@@ -19,7 +19,7 @@
/**
* Base class for all exceptions thrown by the Android
- * Renderscript
+ * RenderScript
*/
public class RSRuntimeException
extends java.lang.RuntimeException {
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 3c6c720..308d97a 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -36,8 +36,8 @@
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
*/
public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 8071073..4de4766 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -33,15 +33,14 @@
import android.os.Trace;
/**
- * Renderscript base master class. An instance of this class creates native
- * worker threads for processing commands from this object. This base class
- * does not provide any extended capabilities beyond simple data processing.
- * For extended capabilities use derived classes such as RenderScriptGL.
+ * This class provides access to a RenderScript context, which controls RenderScript
+ * initialization, resource management, and teardown. An instance of the RenderScript
+ * class must be created before any other RS objects can be created.
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
**/
public class RenderScript {
@@ -912,11 +911,14 @@
//
/**
- * Base class application should derive from for handling RS messages
- * coming from their scripts. When a script calls sendToClient the data
- * fields will be filled in and then the run method called by a message
- * handling thread. This will occur some time after sendToClient completes
- * in the script.
+ * The base class from which an application should derive in order
+ * to receive RS messages from scripts. When a script calls {@code
+ * rsSendToClient}, the data fields will be filled, and the run
+ * method will be called on a separate thread. This will occur
+ * some time after {@code rsSendToClient} completes in the script,
+ * as {@code rsSendToClient} is asynchronous. Message handlers are
+ * not guaranteed to have completed when {@link
+ * android.renderscript.RenderScript#finish} returns.
*
*/
public static class RSMessageHandler implements Runnable {
@@ -927,9 +929,10 @@
}
}
/**
- * If an application is expecting messages it should set this field to an
- * instance of RSMessage. This instance will receive all the user messages
- * sent from sendToClient by scripts from this context.
+ * If an application is expecting messages, it should set this
+ * field to an instance of {@link RSMessageHandler}. This
+ * instance will receive all the user messages sent from {@code
+ * sendToClient} by scripts from this context.
*
*/
RSMessageHandler mMessageCallback = null;
@@ -953,9 +956,9 @@
}
/**
- * Runtime error base class. An application should derive from this class
- * if it wishes to install an error handler. When errors occur at runtime
- * the fields in this class will be filled and the run method called.
+ * The runtime error handler base class. An application should derive from this class
+ * if it wishes to install an error handler. When errors occur at runtime,
+ * the fields in this class will be filled, and the run method will be called.
*
*/
public static class RSErrorHandler implements Runnable {
@@ -968,7 +971,7 @@
/**
* Application Error handler. All runtime errors will be dispatched to the
* instance of RSAsyncError set here. If this field is null a
- * RSRuntimeException will instead be thrown with details about the error.
+ * {@link RSRuntimeException} will instead be thrown with details about the error.
* This will cause program termaination.
*
*/
@@ -982,10 +985,9 @@
}
/**
- * RenderScript worker threads priority enumeration. The default value is
- * NORMAL. Applications wishing to do background processing such as
- * wallpapers should set their priority to LOW to avoid starving forground
- * processes.
+ * RenderScript worker thread priority enumeration. The default value is
+ * NORMAL. Applications wishing to do background processing should set
+ * their priority to LOW to avoid starving forground processes.
*/
public enum Priority {
LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
@@ -1052,7 +1054,7 @@
}
if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
RS_MESSAGE_TO_CLIENT_USER) {
- throw new RSDriverException("Error processing message from Renderscript.");
+ throw new RSDriverException("Error processing message from RenderScript.");
}
if(mRS.mMessageCallback != null) {
@@ -1137,7 +1139,7 @@
}
/**
- * Create a basic RenderScript context.
+ * Create a RenderScript context.
*
* @hide
* @param ctx The context.
@@ -1163,7 +1165,7 @@
}
/**
- * Create a basic RenderScript context.
+ * Create a RenderScript context.
*
* @param ctx The context.
* @return RenderScript
@@ -1173,7 +1175,7 @@
}
/**
- * Create a basic RenderScript context.
+ * Create a RenderScript context.
*
*
* @param ctx The context.
@@ -1196,8 +1198,8 @@
}
/**
- * Wait for any commands in the fifo between the java bindings and native to
- * be processed.
+ * Wait for any pending asynchronous opeations (such as copies to a RS
+ * allocation or RS script executions) to complete.
*
*/
public void finish() {
@@ -1205,8 +1207,9 @@
}
/**
- * Destroy this renderscript context. Once this function is called its no
- * longer legal to use this or any objects created by this context.
+ * Destroys this RenderScript context. Once this function is called,
+ * using this context or any objects belonging to this context is
+ * illegal.
*
*/
public void destroy() {
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 52034b1..bac9c68 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -31,7 +31,7 @@
/**
* @hide
* @deprecated in API 16
- * The Graphics derivitive of Renderscript. Extends the basic context to add a
+ * The Graphics derivitive of RenderScript. Extends the basic context to add a
* root script which is the display window for graphical output. When the
* system needs to update the display the currently bound root script will be
* called. This script is expected to issue the rendering commands to repaint
@@ -39,8 +39,8 @@
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
**/
public class RenderScriptGL extends RenderScript {
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index 057e9b5..623055fe 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -28,9 +28,14 @@
import android.graphics.BitmapFactory;
/**
- * Sampler object which defines how data is extracted from textures. Samplers
- * are attached to Program objects (currently only ProgramFragment) when those objects
- * need to access texture data.
+ * Sampler object that defines how Allocations can be read as textures within a
+ * kernel. Samplers are used in conjunction with the {@code rsSample} runtime
+ * function to return values from normalized coordinates.
+ *
+ * Any Allocation used with a Sampler must have been created with {@link
+ * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE}; using a Sampler on
+ * an {@link android.renderscript.Allocation} that was not created with {@link
+ * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE} is undefined.
**/
public class Sampler extends BaseObj {
public enum Value {
@@ -275,9 +280,8 @@
}
/**
- * Builder for creating non-standard samplers. Usefull if mix and match of
- * wrap modes is necesary or if anisotropic filtering is desired.
- *
+ * Builder for creating non-standard samplers. This is only necessary if
+ * a Sampler with different min and mag modes is desired.
*/
public static class Builder {
RenderScript mRS;
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index f0579ca..0026e0e 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -19,7 +19,8 @@
import android.util.SparseArray;
/**
- *
+ * The parent class for all executable scripts. This should not be used by
+ * applications.
**/
public class Script extends BaseObj {
@@ -46,14 +47,6 @@
private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
/**
* Only to be used by generated reflected classes.
- *
- *
- * @param slot
- * @param sig
- * @param ein
- * @param eout
- *
- * @return KernelID
*/
protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
KernelID k = mKIDs.get(slot);
@@ -92,11 +85,6 @@
private final SparseArray<FieldID> mFIDs = new SparseArray();
/**
* Only to be used by generated reflected classes.
- *
- * @param slot
- * @param e
- *
- * @return FieldID
*/
protected FieldID createFieldID(int slot, Element e) {
FieldID f = mFIDs.get(slot);
@@ -118,7 +106,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param slot
*/
protected void invoke(int slot) {
mRS.nScriptInvoke(getID(mRS), slot);
@@ -127,8 +114,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param slot
- * @param v
*/
protected void invoke(int slot, FieldPacker v) {
if (v != null) {
@@ -141,10 +126,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param slot
- * @param ain
- * @param aout
- * @param v
*/
protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
if (ain == null && aout == null) {
@@ -169,11 +150,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param slot
- * @param ain
- * @param aout
- * @param v
- * @param sc
*/
protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) {
if (ain == null && aout == null) {
@@ -208,8 +184,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param va
- * @param slot
*/
public void bindAllocation(Allocation va, int slot) {
mRS.validate();
@@ -223,8 +197,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, float v) {
mRS.nScriptSetVarF(getID(mRS), index, v);
@@ -236,8 +208,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, double v) {
mRS.nScriptSetVarD(getID(mRS), index, v);
@@ -249,8 +219,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, int v) {
mRS.nScriptSetVarI(getID(mRS), index, v);
@@ -263,8 +231,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, long v) {
mRS.nScriptSetVarJ(getID(mRS), index, v);
@@ -277,8 +243,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, boolean v) {
mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0);
@@ -290,8 +254,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param o
*/
public void setVar(int index, BaseObj o) {
mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
@@ -300,8 +262,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void setVar(int index, FieldPacker v) {
mRS.nScriptSetVarV(getID(mRS), index, v.getData());
@@ -310,10 +270,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
- * @param e
- * @param dims
*/
public void setVar(int index, FieldPacker v, Element e, int[] dims) {
mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims);
@@ -322,8 +278,6 @@
/**
* Only intended for use by generated reflected code.
*
- * @param index
- * @param v
*/
public void getVarV(int index, FieldPacker v) {
mRS.nScriptGetVarV(getID(mRS), index, v.getData());
@@ -338,6 +292,10 @@
}
}
+ /**
+ * Only intended for use by generated reflected code.
+ *
+ */
public static class Builder {
RenderScript mRS;
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index 6975534..b0a5759 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -30,7 +30,8 @@
import java.lang.reflect.Modifier;
/**
- *
+ * The superclass for all user-defined scripts. This is only
+ * intended to be used by the generated derived classes.
**/
public class ScriptC extends Script {
private static final String TAG = "ScriptC";
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
index 7afdb397..1416641 100644
--- a/graphics/java/android/renderscript/ScriptGroup.java
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -20,24 +20,26 @@
import java.util.ArrayList;
/**
- * ScriptGroup creates a groups of scripts which are executed
- * together based upon upon one execution call as if they were
- * all part of a single script. The scripts may be connected
- * internally or to an external allocation. For the internal
- * connections the intermediate results are not observable after
- * the execution of the script.
+ * ScriptGroup creates a group of kernels that are executed
+ * together with one execution call as if they were a single kernel.
+ * The kernels may be connected internally or to an external allocation.
+ * The intermediate results for internal connections are not observable
+ * after the execution of the script.
* <p>
- * The external connections are grouped into inputs and outputs.
+ * External connections are grouped into inputs and outputs.
* All outputs are produced by a script kernel and placed into a
- * user supplied allocation. Inputs are similar but supply the
- * input of a kernal. Inputs bounds to a script are set directly
- * upon the script.
+ * user-supplied allocation. Inputs provide the input of a kernel.
+ * Inputs bound to script globals are set directly upon the script.
* <p>
* A ScriptGroup must contain at least one kernel. A ScriptGroup
* must contain only a single directed acyclic graph (DAG) of
* script kernels and connections. Attempting to create a
* ScriptGroup with multiple DAGs or attempting to create
* a cycle within a ScriptGroup will throw an exception.
+ * <p>
+ * Currently, all kernels in a ScriptGroup must be from separate
+ * Script objects. Attempting to use multiple kernels from the same
+ * Script object will result in an {@link android.renderscript.RSInvalidStateException}.
*
**/
public final class ScriptGroup extends BaseObj {
@@ -93,8 +95,8 @@
/**
* Sets an input of the ScriptGroup. This specifies an
- * Allocation to be used for the kernels which require a kernel
- * input and that input is provided external to the group.
+ * Allocation to be used for kernels that require an input
+ * Allocation provided from outside of the ScriptGroup.
*
* @param s The ID of the kernel where the allocation should be
* connected.
@@ -113,8 +115,8 @@
/**
* Sets an output of the ScriptGroup. This specifies an
- * Allocation to be used for the kernels which require a kernel
- * output and that output is provided external to the group.
+ * Allocation to be used for the kernels that require an output
+ * Allocation visible after the ScriptGroup is executed.
*
* @param s The ID of the kernel where the allocation should be
* connected.
@@ -133,8 +135,8 @@
/**
* Execute the ScriptGroup. This will run all the kernels in
- * the script. The state of the connecting lines will not be
- * observable after this operation.
+ * the ScriptGroup. No internal connection results will be visible
+ * after execution of the ScriptGroup.
*/
public void execute() {
mRS.nScriptGroupExecute(getID(mRS));
@@ -142,20 +144,25 @@
/**
- * Create a ScriptGroup. There are two steps to creating a
- * ScriptGoup.
+ * Helper class to build a ScriptGroup. A ScriptGroup is
+ * created in two steps.
* <p>
- * First all the Kernels to be used by the group should be
- * added. Once this is done the kernels should be connected.
- * Kernels cannot be added once a connection has been made.
+ * First, all kernels to be used by the ScriptGroup should be added.
* <p>
- * Second, add connections. There are two forms of connections.
- * Kernel to Kernel and Kernel to Field. Kernel to Kernel is
- * higher performance and should be used where possible. The
- * line of connections cannot form a loop. If a loop is detected
- * an exception is thrown.
+ * Second, add connections between kernels. There are two types
+ * of connections: kernel to kernel and kernel to field.
+ * Kernel to kernel allows a kernel's output to be passed to
+ * another kernel as input. Kernel to field allows the output of
+ * one kernel to be bound as a script global. Kernel to kernel is
+ * higher performance and should be used where possible.
* <p>
- * Once all the connections are made a call to create will
+ * A ScriptGroup must contain a single directed acyclic graph (DAG); it
+ * cannot contain cycles. Currently, all kernels used in a ScriptGroup
+ * must come from different Script objects. Additionally, all kernels
+ * in a ScriptGroup must have at least one input, output, or internal
+ * connection.
+ * <p>
+ * Once all connections are made, a call to {@link #create} will
* return the ScriptGroup object.
*
*/
@@ -166,10 +173,10 @@
private int mKernelCount;
/**
- * Create a builder for generating a ScriptGroup.
+ * Create a Builder for generating a ScriptGroup.
*
*
- * @param rs The Renderscript context.
+ * @param rs The RenderScript context.
*/
public Builder(RenderScript rs) {
mRS = rs;
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java b/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
index 86f37d8..34540a1 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
@@ -40,7 +40,7 @@
*
* The defaults tables are identity.
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for intputs and outputs
*
* @return ScriptIntrinsic3DLUT
@@ -55,6 +55,13 @@
return new ScriptIntrinsic3DLUT(id, rs, e);
}
+ /**
+ * Sets the {@link android.renderscript.Allocation} to be used as the lookup table.
+ *
+ * The lookup table must use the same {@link android.renderscript.Element} as the intrinsic.
+ *
+ */
+
public void setLUT(Allocation lut) {
final Type t = lut.getType();
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
index 65c69c0..0e05bc8 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
@@ -18,8 +18,7 @@
/**
- * Intrinsic kernels for blending two buffers. Each blend function is a separate
- * kernel to make it easy to change between blend modes.
+ * Intrinsic kernels for blending two {@link android.renderscript.Allocation} objects.
**/
public class ScriptIntrinsicBlend extends ScriptIntrinsic {
ScriptIntrinsicBlend(int id, RenderScript rs) {
@@ -27,11 +26,10 @@
}
/**
- * Supported elements types are uchar4
+ * Supported elements types are {@link Element#U8_4}
*
- *
- * @param rs
- * @param e
+ * @param rs The RenderScript context
+ * @param e Element type for inputs and outputs
*
* @return ScriptIntrinsicBlend
*/
@@ -53,7 +51,7 @@
}
/**
- * dst = {0, 0, 0, 0}
+ * Sets dst = {0, 0, 0, 0}
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -73,7 +71,7 @@
/**
- * dst = src
+ * Sets dst = src
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -92,8 +90,9 @@
}
/**
- * dst = dst
- * This is a NOP
+ * Sets dst = dst
+ *
+ * This is a NOP.
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -112,7 +111,7 @@
}
/**
- * dst = src + dst * (1.0 - src.a)
+ * Sets dst = src + dst * (1.0 - src.a)
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -131,7 +130,7 @@
}
/**
- * dst = dst + src * (1.0 - dst.a)
+ * Sets dst = dst + src * (1.0 - dst.a)
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -150,7 +149,7 @@
}
/**
- * dst = src * dst.a
+ * Sets dst = src * dst.a
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -169,7 +168,7 @@
}
/**
- * dst = dst * src.a
+ * Sets dst = dst * src.a
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -188,7 +187,7 @@
}
/**
- * dst = src * (1.0 - dst.a)
+ * Sets dst = src * (1.0 - dst.a)
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -207,7 +206,7 @@
}
/**
- * dst = dst * (1.0 - src.a)
+ * Sets dst = dst * (1.0 - src.a)
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -266,7 +265,7 @@
}
/**
- * dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
+ * Sets dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -295,7 +294,7 @@
}
*/
/**
- * dst = src * dst
+ * Sets dst = src * dst
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -391,7 +390,7 @@
}
*/
/**
- * dst = min(src + dst, 1.0)
+ * Sets dst = min(src + dst, 1.0)
*
* @param ain The source buffer
* @param aout The destination buffer
@@ -410,7 +409,7 @@
}
/**
- * dst = max(dst - src, 0.0)
+ * Sets dst = max(dst - src, 0.0)
*
* @param ain The source buffer
* @param aout The destination buffer
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
index 2848f64..aaf5ffc 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -40,7 +40,7 @@
*
* Supported elements types are {@link Element#U8_4}
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for inputs and outputs
*
* @return ScriptIntrinsicBlur
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
index f7e844e..77b9385 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -41,7 +41,7 @@
*
* Supported elements types are {@link Element#U8_4}
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for intputs and outputs
*
* @return ScriptIntrinsicColorMatrix
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
index d54df96..c9c54b2 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -41,7 +41,7 @@
* <p> [ 0, 0, 0 ]
* </code>
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for intputs and outputs
*
* @return ScriptIntrinsicConvolve3x3
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
index 1f52e3f..c6e1e39 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -42,7 +42,7 @@
* <p> [ 0, 0, 0, 0, 0 ]
* </code>
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for intputs and outputs
*
* @return ScriptIntrinsicConvolve5x5
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
index f5ca261..0f7ab38 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -47,7 +47,7 @@
*
* The defaults tables are identity.
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for intputs and outputs
*
* @return ScriptIntrinsicLUT
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
index dc8a5aa..9b5de9b 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -36,7 +36,7 @@
*
* Supported elements types are {@link Element#U8_4}
*
- * @param rs The Renderscript context
+ * @param rs The RenderScript context
* @param e Element type for output
*
* @return ScriptIntrinsicYuvToRGB
diff --git a/graphics/java/android/renderscript/Short2.java b/graphics/java/android/renderscript/Short2.java
index 617f1f5..7c6027f 100644
--- a/graphics/java/android/renderscript/Short2.java
+++ b/graphics/java/android/renderscript/Short2.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript Short2 type back to the Android system.
+ * Class for exposing the native RenderScript Short2 type back to the Android system.
*
**/
public class Short2 {
diff --git a/graphics/java/android/renderscript/Short3.java b/graphics/java/android/renderscript/Short3.java
index b9ca49b..49de05e 100644
--- a/graphics/java/android/renderscript/Short3.java
+++ b/graphics/java/android/renderscript/Short3.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript short3 type back to the Android system.
+ * Class for exposing the native RenderScript short3 type back to the Android system.
*
**/
public class Short3 {
diff --git a/graphics/java/android/renderscript/Short4.java b/graphics/java/android/renderscript/Short4.java
index d5f2db5..a7807a4 100644
--- a/graphics/java/android/renderscript/Short4.java
+++ b/graphics/java/android/renderscript/Short4.java
@@ -21,7 +21,7 @@
/**
- * Class for exposing the native Renderscript short4 type back to the Android system.
+ * Class for exposing the native RenderScript short4 type back to the Android system.
*
**/
public class Short4 {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index a5e24ce..ef08c29 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -23,24 +23,29 @@
import android.util.Log;
/**
- * <p>Type is an allocation template. It consists of an Element and one or more
- * dimensions. It describes only the layout of memory but does not allocate any
- * storage for the data that is described.</p>
+ * <p>A Type describes the {@link android.renderscript.Element} and dimensions used for an {@link
+ * android.renderscript.Allocation} or a parallel operation. Types are created through {@link
+ * android.renderscript.Type.Builder}.</p>
*
- * <p>A Type consists of several dimensions. Those are X, Y, Z, LOD (level of
- * detail), Faces (faces of a cube map). The X,Y,Z dimensions can be assigned
- * any positive integral value within the constraints of available memory. A
- * single dimension allocation would have an X dimension of greater than zero
- * while the Y and Z dimensions would be zero to indicate not present. In this
- * regard an allocation of x=10, y=1 would be considered 2 dimensionsal while
- * x=10, y=0 would be considered 1 dimensional.</p>
+ * <p>A Type always includes an {@link android.renderscript.Element} and an X
+ * dimension. A Type may be multidimensional, up to three dimensions. A nonzero
+ * value in the Y or Z dimensions indicates that the dimension is present. Note
+ * that a Type with only a given X dimension and a Type with the same X
+ * dimension but Y = 1 are not equivalent.</p>
*
- * <p>The LOD and Faces dimensions are booleans to indicate present or not present.</p>
+ * <p>A Type also supports inclusion of level of detail (LOD) or cube map
+ * faces. LOD and cube map faces are booleans to indicate present or not
+ * present. </p>
+ *
+ * <p>A Type also supports YUV format information to support an {@link
+ * android.renderscript.Allocation} in a YUV format. The YUV formats supported
+ * are {@link android.graphics.ImageFormat#YV12} and {@link
+ * android.graphics.ImageFormat#NV21}.</p>
*
* <div class="special reference">
* <h3>Developer Guides</h3>
- * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
* </div>
**/
public class Type extends BaseObj {
@@ -277,11 +282,9 @@
}
/**
- * Set the YUV layout for a Type. This controls how the memory is
- * interpreted. Generally and application should not need to call this
- * function and it would be set by the Camera.
+ * Set the YUV layout for a Type.
*
- * only NV21, YV12. Enums from ImageFormat
+ * @param yuvFormat {@link android.graphics.ImageFormat#YV12} or {@link android.graphics.ImageFormat#NV21}
*/
public Builder setYuvFormat(int yuvFormat) {
switch (yuvFormat) {
@@ -299,7 +302,7 @@
/**
- * Validate structure and create a new type.
+ * Validate structure and create a new Type.
*
* @return Type
*/
diff --git a/graphics/java/android/renderscript/package.html b/graphics/java/android/renderscript/package.html
index eb178c1..a844956 100644
--- a/graphics/java/android/renderscript/package.html
+++ b/graphics/java/android/renderscript/package.html
@@ -2,6 +2,11 @@
<BODY>
<p>RenderScript provides support for high-performance computation across heterogeneous processors.</p>
+<p>This package is for the latest native version of RenderScript included on
+Android devices. Developers interested in running RenderScript on any Android
+device running {@link android.os.Build.VERSION_CODES#GINGERBREAD} or newer
+should see the {@link android.support.v8.renderscript} package.
+
<p>For more information, see the
<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
{@more}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 771ac45..5a30472 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -41,6 +41,7 @@
SkiaShader.cpp \
Snapshot.cpp \
Stencil.cpp \
+ Texture.cpp \
TextureCache.cpp \
TextDropShadowCache.cpp
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 8511e7c..782c052 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -15,6 +15,7 @@
*/
#include "AssetAtlas.h"
+#include "Caches.h"
#include <GLES2/gl2ext.h>
@@ -33,12 +34,14 @@
mImage = new Image(buffer);
if (mImage->getTexture()) {
- mTexture = new Texture();
+ Caches& caches = Caches::getInstance();
+
+ mTexture = new Texture(caches);
mTexture->id = mImage->getTexture();
mTexture->width = buffer->getWidth();
mTexture->height = buffer->getHeight();
- createEntries(map, count);
+ createEntries(caches, map, count);
} else {
ALOGW("Could not create atlas image");
@@ -82,7 +85,7 @@
* instead of applying the changes to the virtual textures.
*/
struct DelegateTexture: public Texture {
- DelegateTexture(Texture* delegate): Texture(), mDelegate(delegate) { }
+ DelegateTexture(Caches& caches, Texture* delegate): Texture(caches), mDelegate(delegate) { }
virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
@@ -100,7 +103,7 @@
/**
* TODO: This method does not take the rotation flag into account
*/
-void AssetAtlas::createEntries(int* map, int count) {
+void AssetAtlas::createEntries(Caches& caches, int* map, int count) {
const float width = float(mTexture->width);
const float height = float(mTexture->height);
@@ -117,7 +120,7 @@
x / width, (x + bitmap->width()) / width,
y / height, (y + bitmap->height()) / height);
- Texture* texture = new DelegateTexture(mTexture);
+ Texture* texture = new DelegateTexture(caches, mTexture);
Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);
texture->id = mTexture->id;
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 793e300..2624907 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -34,6 +34,8 @@
namespace android {
namespace uirenderer {
+class Caches;
+
/**
* An asset atlas holds a collection of framework bitmaps in a single OpenGL
* texture. Each bitmap is associated with a location, defined in pixels,
@@ -157,7 +159,7 @@
Texture* getEntryTexture(SkBitmap* const bitmap) const;
private:
- void createEntries(int* map, int count);
+ void createEntries(Caches& caches, int* map, int count);
Texture* mTexture;
Image* mImage;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 9d5a854..74aeddb 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -47,7 +47,8 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-Caches::Caches(): Singleton<Caches>(), mExtensions(Extensions::getInstance()), mInitialized(false) {
+Caches::Caches(): Singleton<Caches>(),
+ mExtensions(Extensions::getInstance()), mInitialized(false) {
init();
initFont();
initConstraints();
@@ -100,6 +101,8 @@
mInitialized = true;
+ resetBoundTextures();
+
return true;
}
@@ -491,6 +494,46 @@
}
}
+void Caches::bindTexture(GLuint texture) {
+ if (mBoundTextures[mTextureUnit] != texture) {
+ glBindTexture(GL_TEXTURE_2D, texture);
+ mBoundTextures[mTextureUnit] = texture;
+ }
+}
+
+void Caches::bindTexture(GLenum target, GLuint texture) {
+ if (mBoundTextures[mTextureUnit] != texture) {
+ glBindTexture(target, texture);
+ mBoundTextures[mTextureUnit] = texture;
+ }
+}
+
+void Caches::deleteTexture(GLuint texture) {
+ // When glDeleteTextures() is called on a currently bound texture,
+ // OpenGL ES specifies that the texture is then considered unbound
+ // Consider the following series of calls:
+ //
+ // glGenTextures -> creates texture name 2
+ // glBindTexture(2)
+ // glDeleteTextures(2) -> 2 is now unbound
+ // glGenTextures -> can return 2 again
+ //
+ // If we don't call glBindTexture(2) after the second glGenTextures
+ // call, any texture operation will be performed on the default
+ // texture (name=0)
+
+ for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
+ if (mBoundTextures[i] == texture) {
+ mBoundTextures[i] = 0;
+ }
+ }
+ glDeleteTextures(1, &texture);
+}
+
+void Caches::resetBoundTextures() {
+ memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
+}
+
///////////////////////////////////////////////////////////////////////////////
// Scissor
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 54e4138..bdde8fb 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -55,6 +55,7 @@
// Globals
///////////////////////////////////////////////////////////////////////////////
+// GL ES 2.0 defines that at least 16 texture units must be supported
#define REQUIRED_TEXTURE_UNITS_COUNT 3
#define REGION_MESH_QUAD_COUNT 512
@@ -79,6 +80,7 @@
static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
static const GLsizei gMeshCount = 4;
+// Must define as many texture units as specified by REQUIRED_TEXTURE_UNITS_COUNT
static const GLenum gTextureUnits[] = {
GL_TEXTURE0,
GL_TEXTURE1,
@@ -223,6 +225,33 @@
void activeTexture(GLuint textureUnit);
/**
+ * Binds the specified texture as a GL_TEXTURE_2D texture.
+ * All texture bindings must be performed with this method or
+ * bindTexture(GLenum, GLuint).
+ */
+ void bindTexture(GLuint texture);
+
+ /**
+ * Binds the specified texture with the specified render target.
+ * All texture bindings must be performed with this method or
+ * bindTexture(GLuint).
+ */
+ void bindTexture(GLenum target, GLuint texture);
+
+ /**
+ * Deletes the specified texture and clears it from the cache
+ * of bound textures.
+ * All textures must be deleted using this method.
+ */
+ void deleteTexture(GLuint texture);
+
+ /**
+ * Signals that the cache of bound textures should be cleared.
+ * Other users of the context may have altered which textures are bound.
+ */
+ void resetBoundTextures();
+
+ /**
* Sets the scissor for the current surface.
*/
bool setScissor(GLint x, GLint y, GLint width, GLint height);
@@ -363,6 +392,8 @@
bool mInitialized;
uint32_t mFunctorsCount;
+
+ GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
}; // class Caches
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 06209f1..b2d9915 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -63,6 +63,7 @@
void DisplayList::clearResources() {
mDisplayListData = NULL;
+ mSize = 0; // TODO: shouldn't be needed, WAR possible use after delete
mClipRectOp = NULL;
mSaveLayerOp = NULL;
@@ -479,7 +480,7 @@
*/
template <class T>
void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
- if (mSize == 0 || mAlpha <= 0) {
+ if (mSize == 0 || mAlpha <= 0 || CC_UNLIKELY(!mSaveOp)) { // TODO: shouldn't need mSaveOp check
DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
return;
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 5f84329..97c34dc 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -129,7 +129,12 @@
void setName(const char* name) {
if (name) {
- mName.setTo(name);
+ char* lastPeriod = strrchr(name, '.');
+ if (lastPeriod) {
+ mName.setTo(lastPeriod + 1);
+ } else {
+ mName.setTo(name);
+ }
}
}
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index 19b3849..649a7bc 100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -24,12 +24,15 @@
// Lifecycle
///////////////////////////////////////////////////////////////////////////////
+Dither::Dither(): mCaches(NULL), mInitialized(false), mDitherTexture(0) {
+}
+
void Dither::bindDitherTexture() {
if (!mInitialized) {
bool useFloatTexture = Extensions::getInstance().getMajorGlVersion() >= 3;
glGenTextures(1, &mDitherTexture);
- glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+ mCaches->bindTexture(mDitherTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -68,13 +71,13 @@
mInitialized = true;
} else {
- glBindTexture(GL_TEXTURE_2D, mDitherTexture);
+ mCaches->bindTexture(mDitherTexture);
}
}
void Dither::clear() {
if (mInitialized) {
- glDeleteTextures(1, &mDitherTexture);
+ mCaches->deleteTexture(mDitherTexture);
mInitialized = false;
}
}
@@ -84,8 +87,10 @@
///////////////////////////////////////////////////////////////////////////////
void Dither::setupProgram(Program* program, GLuint* textureUnit) {
+ if (!mCaches) mCaches = &Caches::getInstance();
+
GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+ mCaches->activeTexture(textureSlot);
bindDitherTexture();
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index 4d1f921..546236be 100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
@@ -24,9 +24,7 @@
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
+class Caches;
// Must be a power of two
#define DITHER_KERNEL_SIZE 4
@@ -39,7 +37,7 @@
*/
class Dither {
public:
- Dither(): mInitialized(false), mDitherTexture(0) { }
+ Dither();
void clear();
void setupProgram(Program* program, GLuint* textureUnit);
@@ -47,6 +45,7 @@
private:
void bindDitherTexture();
+ Caches* mCaches;
bool mInitialized;
GLuint mDitherTexture;
};
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index a9bf13e..3e3d882 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -376,7 +376,7 @@
if (cacheTexture->getTextureId() != lastTextureId) {
lastTextureId = cacheTexture->getTextureId();
caches.activeTexture(0);
- glBindTexture(GL_TEXTURE_2D, lastTextureId);
+ caches.bindTexture(lastTextureId);
}
if (cacheTexture->upload()) {
@@ -429,7 +429,7 @@
first = false;
}
- glBindTexture(GL_TEXTURE_2D, texture->getTextureId());
+ caches.bindTexture(texture->getTextureId());
texture->setLinearFiltering(mLinearFiltering, false);
TextureVertex* mesh = texture->mesh();
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 507ed95..1815bff 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -120,7 +120,7 @@
const uint32_t size = texture->width * texture->height * bytesPerPixel();
mSize -= size;
- glDeleteTextures(1, &texture->id);
+ texture->deleteTexture();
delete texture;
}
}
@@ -173,7 +173,7 @@
GradientInfo info;
getGradientInfo(colors, count, info);
- Texture* texture = new Texture;
+ Texture* texture = new Texture();
texture->width = info.width;
texture->height = 2;
texture->blend = info.hasAlpha;
@@ -286,7 +286,7 @@
memcpy(pixels + rowBytes, pixels, rowBytes);
glGenTextures(1, &texture->id);
- glBindTexture(GL_TEXTURE_2D, texture->id);
+ Caches::getInstance().bindTexture(texture->id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (mUseFloatTexture) {
diff --git a/libs/hwui/Image.cpp b/libs/hwui/Image.cpp
index 35ca40d..edf3930 100644
--- a/libs/hwui/Image.cpp
+++ b/libs/hwui/Image.cpp
@@ -18,6 +18,7 @@
#include <utils/Log.h>
+#include "Caches.h"
#include "Image.h"
namespace android {
@@ -38,7 +39,7 @@
} else {
// Create a 2D texture to sample from the EGLImage
glGenTextures(1, &mTexture);
- glBindTexture(GL_TEXTURE_2D, mTexture);
+ Caches::getInstance().bindTexture(mTexture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
GLenum status = GL_NO_ERROR;
@@ -53,7 +54,7 @@
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), mImage);
mImage = EGL_NO_IMAGE_KHR;
- glDeleteTextures(1, &mTexture);
+ Caches::getInstance().deleteTexture(mTexture);
mTexture = 0;
}
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 4adad05..134f452 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -28,7 +28,8 @@
namespace android {
namespace uirenderer {
-Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
+Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight):
+ caches(Caches::getInstance()), texture(caches) {
mesh = NULL;
meshIndices = NULL;
meshElementCount = 0;
@@ -47,11 +48,11 @@
debugDrawUpdate = false;
hasDrawnSinceUpdate = false;
deferredList = NULL;
- Caches::getInstance().resourceCache.incrementRefcount(this);
+ caches.resourceCache.incrementRefcount(this);
}
Layer::~Layer() {
- if (colorFilter) Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+ if (colorFilter) caches.resourceCache.decrementRefcount(colorFilter);
removeFbo();
deleteTexture();
@@ -76,7 +77,7 @@
return true;
}
- const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize;
+ const uint32_t maxTextureSize = caches.maxTextureSize;
if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) {
ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
desiredWidth, desiredHeight, maxTextureSize, maxTextureSize);
@@ -89,7 +90,7 @@
setSize(desiredWidth, desiredHeight);
if (fbo) {
- Caches::getInstance().activeTexture(0);
+ caches.activeTexture(0);
bindTexture();
allocateTexture();
@@ -120,14 +121,14 @@
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
- Caches::getInstance().renderBufferCache.put(stencil);
+ caches.renderBufferCache.put(stencil);
stencil = NULL;
}
if (fbo) {
if (flush) LayerRenderer::flushLayer(this);
// If put fails the cache will delete the FBO
- Caches::getInstance().fboCache.put(fbo);
+ caches.fboCache.put(fbo);
fbo = 0;
}
}
@@ -138,11 +139,51 @@
void Layer::setColorFilter(SkiaColorFilter* filter) {
if (colorFilter) {
- Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+ caches.resourceCache.decrementRefcount(colorFilter);
}
colorFilter = filter;
if (colorFilter) {
- Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
+ caches.resourceCache.incrementRefcount(colorFilter);
+ }
+}
+
+void Layer::bindTexture() const {
+ if (texture.id) {
+ caches.bindTexture(renderTarget, texture.id);
+ }
+}
+
+void Layer::bindStencilRenderBuffer() const {
+ if (stencil) {
+ stencil->bind();
+ }
+}
+
+void Layer::generateTexture() {
+ if (!texture.id) {
+ glGenTextures(1, &texture.id);
+ }
+}
+
+void Layer::deleteTexture() {
+ if (texture.id) {
+ texture.deleteTexture();
+ texture.id = 0;
+ }
+}
+
+void Layer::clearTexture() {
+ texture.id = 0;
+}
+
+void Layer::allocateTexture() {
+#if DEBUG_LAYERS
+ ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight());
+#endif
+ if (texture.id) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 7186603..326b25a 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -40,6 +40,7 @@
///////////////////////////////////////////////////////////////////////////////
// Forward declarations
+class Caches;
class OpenGLRenderer;
class DisplayList;
class DeferredDisplayList;
@@ -221,50 +222,19 @@
ANDROID_API void setColorFilter(SkiaColorFilter* filter);
- inline void bindTexture() const {
- if (texture.id) {
- glBindTexture(renderTarget, texture.id);
- }
- }
+ void bindStencilRenderBuffer() const;
- inline void bindStencilRenderBuffer() const {
- if (stencil) {
- stencil->bind();
- }
- }
-
- inline void generateTexture() {
- if (!texture.id) {
- glGenTextures(1, &texture.id);
- }
- }
-
- inline void deleteTexture() {
- if (texture.id) {
- glDeleteTextures(1, &texture.id);
- texture.id = 0;
- }
- }
+ void bindTexture() const;
+ void generateTexture();
+ void allocateTexture();
+ void deleteTexture();
/**
* When the caller frees the texture itself, the caller
* must call this method to tell this layer that it lost
* the texture.
*/
- void clearTexture() {
- texture.id = 0;
- }
-
- inline void allocateTexture() {
-#if DEBUG_LAYERS
- ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight());
-#endif
- if (texture.id) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- }
+ ANDROID_API void clearTexture();
inline mat4& getTexTransform() {
return texTransform;
@@ -320,6 +290,8 @@
bool hasDrawnSinceUpdate;
private:
+ Caches& caches;
+
/**
* Name of the FBO used to render the layer. If the name is 0
* this layer is not backed by an FBO, but a simple texture.
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 3e55fff..79e0b0c 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -436,7 +436,7 @@
if ((error = glGetError()) != GL_NO_ERROR) goto error;
caches.activeTexture(0);
- glBindTexture(GL_TEXTURE_2D, texture);
+ caches.bindTexture(texture);
glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
@@ -498,7 +498,7 @@
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
layer->setAlpha(alpha, mode);
layer->setFbo(previousLayerFbo);
- glDeleteTextures(1, &texture);
+ caches.deleteTexture(texture);
caches.fboCache.put(fbo);
glViewport(previousViewport[0], previousViewport[1],
previousViewport[2], previousViewport[3]);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index f12119a..f5343b1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -371,6 +371,7 @@
dirtyClip();
mCaches.activeTexture(0);
+ mCaches.resetBoundTextures();
mCaches.blend = true;
glEnable(GL_BLEND);
@@ -3109,7 +3110,7 @@
void OpenGLRenderer::setupShader(SkiaShader* shader) {
mDrawModifiers.mShader = shader;
if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->set(&mCaches.textureCache, &mCaches.gradientCache);
+ mDrawModifiers.mShader->setCaches(mCaches);
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 6286e94..e9ea2f32 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -888,7 +888,7 @@
* prior to calling this method.
*/
inline void bindTexture(GLuint texture) {
- glBindTexture(GL_TEXTURE_2D, texture);
+ mCaches.bindTexture(texture);
}
/**
@@ -896,7 +896,7 @@
* prior to calling this method.
*/
inline void bindExternalTexture(GLuint texture) {
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+ mCaches.bindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
}
/**
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index fdb10e2..3ab40da 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -139,7 +139,7 @@
static PathTexture* createTexture(float left, float top, float offset,
uint32_t width, uint32_t height, uint32_t id) {
- PathTexture* texture = new PathTexture();
+ PathTexture* texture = new PathTexture(Caches::getInstance());
texture->left = left;
texture->top = top;
texture->offset = offset;
@@ -223,7 +223,7 @@
}
if (texture->id) {
- glDeleteTextures(1, &texture->id);
+ Caches::getInstance().deleteTexture(texture->id);
}
delete texture;
}
@@ -300,7 +300,7 @@
glGenTextures(1, &texture->id);
- glBindTexture(GL_TEXTURE_2D, texture->id);
+ Caches::getInstance().bindTexture(texture->id);
// Textures are Alpha8
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index dd1f996..a191f0e 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -58,7 +58,7 @@
* Alpha texture used to represent a path.
*/
struct PathTexture: public Texture {
- PathTexture(): Texture() {
+ PathTexture(Caches& caches): Texture(caches) {
}
~PathTexture() {
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index c38eedb..797ed10 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -69,9 +69,13 @@
mGenerationId = shader.mGenerationId;
}
+SkiaShader::SkiaShader(): mCaches(NULL) {
+}
+
SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
- mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
+ mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
+ mCaches(NULL) {
setMatrix(matrix);
mGenerationId = 0;
}
@@ -87,7 +91,7 @@
}
void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
- glBindTexture(GL_TEXTURE_2D, texture->id);
+ mCaches->bindTexture(texture->id);
texture->setWrapST(wrapS, wrapT);
}
@@ -114,7 +118,7 @@
}
void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
- Texture* texture = mTextureCache->get(mBitmap);
+ Texture* texture = mCaches->textureCache.get(mBitmap);
if (!texture) return;
mTexture = texture;
@@ -229,7 +233,7 @@
GLuint textureSlot = (*textureUnit)++;
Caches::getInstance().activeTexture(textureSlot);
- Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
+ Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
// Uniforms
bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
@@ -349,7 +353,7 @@
GLuint textureSlot = (*textureUnit)++;
Caches::getInstance().activeTexture(textureSlot);
- Texture* texture = mGradientCache->get(mColors, mPositions, mCount);
+ Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
// Uniforms
bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
@@ -359,7 +363,7 @@
bindUniformColor(program->getUniform("endColor"), mColors[1]);
}
- Caches::getInstance().dither.setupProgram(program, textureUnit);
+ mCaches->dither.setupProgram(program, textureUnit);
mat4 screenSpace;
computeScreenSpaceMatrix(screenSpace, modelView);
@@ -394,12 +398,6 @@
return copy;
}
-void SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
- SkiaShader::set(textureCache, gradientCache);
- mFirst->set(textureCache, gradientCache);
- mSecond->set(textureCache, gradientCache);
-}
-
void SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
mFirst->describe(description, extensions);
mSecond->describe(description, extensions);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index bc12b0d..a63431c 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -33,6 +33,8 @@
namespace android {
namespace uirenderer {
+class Caches;
+
///////////////////////////////////////////////////////////////////////////////
// Base shader
///////////////////////////////////////////////////////////////////////////////
@@ -77,9 +79,8 @@
return mType;
}
- virtual void set(TextureCache* textureCache, GradientCache* gradientCache) {
- mTextureCache = textureCache;
- mGradientCache = gradientCache;
+ virtual void setCaches(Caches& caches) {
+ mCaches = &caches;
}
uint32_t getGenerationId() {
@@ -103,8 +104,7 @@
void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
protected:
- SkiaShader() {
- }
+ SkiaShader();
/**
* The appropriate texture unit must have been activated prior to invoking
@@ -118,8 +118,7 @@
SkShader::TileMode mTileY;
bool mBlend;
- TextureCache* mTextureCache;
- GradientCache* mGradientCache;
+ Caches* mCaches;
mat4 mUnitMatrix;
mat4 mShaderMatrix;
@@ -229,7 +228,11 @@
~SkiaComposeShader();
SkiaShader* copy();
- void set(TextureCache* textureCache, GradientCache* gradientCache);
+ void setCaches(Caches& caches) {
+ SkiaShader::setCaches(caches);
+ mFirst->setCaches(caches);
+ mSecond->setCaches(caches);
+ }
void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 6976eaa..0b2c130 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -18,6 +18,7 @@
#include <utils/JenkinsHash.h>
+#include "Caches.h"
#include "Debug.h"
#include "TextDropShadowCache.h"
#include "Properties.h"
@@ -154,7 +155,7 @@
ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize);
}
- glDeleteTextures(1, &texture->id);
+ texture->deleteTexture();
delete texture;
}
}
@@ -182,7 +183,9 @@
return NULL;
}
- texture = new ShadowTexture;
+ Caches& caches = Caches::getInstance();
+
+ texture = new ShadowTexture(caches);
texture->left = shadow.penX;
texture->top = shadow.penY;
texture->width = shadow.width;
@@ -202,7 +205,7 @@
glGenTextures(1, &texture->id);
- glBindTexture(GL_TEXTURE_2D, texture->id);
+ caches.bindTexture(texture->id);
// Textures are Alpha8
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 0bed72b6..04d7357 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -30,6 +30,8 @@
namespace android {
namespace uirenderer {
+class Caches;
+
struct ShadowText {
ShadowText(): len(0), radius(0.0f), textSize(0.0f), typeface(NULL),
flags(0), italicStyle(0.0f), scaleX(0), text(NULL), positions(NULL) {
@@ -114,7 +116,7 @@
* Alpha texture used to represent a shadow.
*/
struct ShadowTexture: public Texture {
- ShadowTexture(): Texture() {
+ ShadowTexture(Caches& caches): Texture(caches) {
}
float left;
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
new file mode 100644
index 0000000..7923ce7
--- /dev/null
+++ b/libs/hwui/Texture.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <utils/Log.h>
+
+#include "Caches.h"
+#include "Texture.h"
+
+namespace android {
+namespace uirenderer {
+
+Texture::Texture(): id(0), generation(0), blend(false), width(0), height(0),
+ cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+ mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
+ mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
+ mFirstFilter(true), mFirstWrap(true), mCaches(Caches::getInstance()) {
+}
+
+Texture::Texture(Caches& caches): id(0), generation(0), blend(false), width(0), height(0),
+ cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+ mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
+ mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
+ mFirstFilter(true), mFirstWrap(true), mCaches(caches) {
+}
+
+void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force,
+ GLenum renderTarget) {
+
+ if (mFirstWrap || force || wrapS != mWrapS || wrapT != mWrapT) {
+ mFirstWrap = false;
+
+ mWrapS = wrapS;
+ mWrapT = wrapT;
+
+ if (bindTexture) {
+ mCaches.bindTexture(renderTarget, id);
+ }
+
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+ }
+}
+
+void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force,
+ GLenum renderTarget) {
+
+ if (mFirstFilter || force || min != mMinFilter || mag != mMagFilter) {
+ mFirstFilter = false;
+
+ mMinFilter = min;
+ mMagFilter = mag;
+
+ if (bindTexture) {
+ mCaches.bindTexture(renderTarget, id);
+ }
+
+ if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
+
+ glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+ glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+ }
+}
+
+void Texture::deleteTexture() const {
+ mCaches.deleteTexture(id);
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index f84cd67..d48ec59 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -22,81 +22,39 @@
namespace android {
namespace uirenderer {
+class Caches;
class UvMapper;
/**
* Represents an OpenGL texture.
*/
-struct Texture {
- Texture() {
- cleanup = false;
- bitmapSize = 0;
-
- wrapS = GL_CLAMP_TO_EDGE;
- wrapT = GL_CLAMP_TO_EDGE;
-
- minFilter = GL_NEAREST;
- magFilter = GL_NEAREST;
-
- mipMap = false;
-
- firstFilter = true;
- firstWrap = true;
-
- id = 0;
-
- uvMapper = NULL;
- }
+class Texture {
+public:
+ Texture();
+ Texture(Caches& caches);
virtual ~Texture() { }
- void setWrap(GLenum wrap, bool bindTexture = false, bool force = false,
+ inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false,
GLenum renderTarget = GL_TEXTURE_2D) {
setWrapST(wrap, wrap, bindTexture, force, renderTarget);
}
virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
- bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
+ bool force = false, GLenum renderTarget = GL_TEXTURE_2D);
- if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) {
- firstWrap = false;
-
- this->wrapS = wrapS;
- this->wrapT = wrapT;
-
- if (bindTexture) {
- glBindTexture(renderTarget, id);
- }
-
- glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
- glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
- }
- }
-
- void setFilter(GLenum filter, bool bindTexture = false, bool force = false,
+ inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false,
GLenum renderTarget = GL_TEXTURE_2D) {
setFilterMinMag(filter, filter, bindTexture, force, renderTarget);
}
virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
- bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
+ bool force = false, GLenum renderTarget = GL_TEXTURE_2D);
- if (firstFilter || force || min != minFilter || mag != magFilter) {
- firstFilter = false;
-
- minFilter = min;
- magFilter = mag;
-
- if (bindTexture) {
- glBindTexture(renderTarget, id);
- }
-
- if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
-
- glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
- glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
- }
- }
+ /**
+ * Convenience method to call glDeleteTextures() on this texture's id.
+ */
+ void deleteTexture() const;
/**
* Name of the texture.
@@ -140,17 +98,19 @@
/**
* Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
*/
- GLenum wrapS;
- GLenum wrapT;
+ GLenum mWrapS;
+ GLenum mWrapT;
/**
* Last filters set on this texture. Defaults to GL_NEAREST.
*/
- GLenum minFilter;
- GLenum magFilter;
+ GLenum mMinFilter;
+ GLenum mMagFilter;
- bool firstFilter;
- bool firstWrap;
+ bool mFirstFilter;
+ bool mFirstWrap;
+
+ Caches& mCaches;
}; // struct Texture
class AutoTexture {
@@ -158,7 +118,7 @@
AutoTexture(const Texture* texture): mTexture(texture) { }
~AutoTexture() {
if (mTexture && mTexture->cleanup) {
- glDeleteTextures(1, &mTexture->id);
+ mTexture->deleteTexture();
delete mTexture;
}
}
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 2378eb5..a63cac6 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -112,7 +112,7 @@
if (mDebugEnabled) {
ALOGD("Texture deleted, size = %d", texture->bitmapSize);
}
- glDeleteTextures(1, &texture->id);
+ texture->deleteTexture();
delete texture;
}
}
@@ -139,7 +139,7 @@
}
}
- texture = new Texture;
+ texture = new Texture();
texture->bitmapSize = size;
generateTexture(bitmap, texture, false);
@@ -162,7 +162,7 @@
}
Texture* TextureCache::getTransient(SkBitmap* bitmap) {
- Texture* texture = new Texture;
+ Texture* texture = new Texture();
texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
texture->cleanup = true;
@@ -235,7 +235,7 @@
texture->width = bitmap->width();
texture->height = bitmap->height();
- glBindTexture(GL_TEXTURE_2D, texture->id);
+ Caches::getInstance().bindTexture(texture->id);
switch (bitmap->getConfig()) {
case SkBitmap::kA8_Config:
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 6c5267d..5f15724 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -17,6 +17,7 @@
#include <SkGlyph.h>
#include "CacheTexture.h"
+#include "../Caches.h"
#include "../Debug.h"
#include "../Extensions.h"
#include "../PixelBuffer.h"
@@ -110,7 +111,8 @@
CacheTexture::CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCount) :
mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
mLinearFiltering(false), mDirty(false), mNumGlyphs(0),
- mMesh(NULL), mCurrentQuad(0), mMaxQuadCount(maxQuadCount) {
+ mMesh(NULL), mCurrentQuad(0), mMaxQuadCount(maxQuadCount),
+ mCaches(Caches::getInstance()) {
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
@@ -154,7 +156,7 @@
mTexture = NULL;
}
if (mTextureId) {
- glDeleteTextures(1, &mTextureId);
+ mCaches.deleteTexture(mTextureId);
mTextureId = 0;
}
mDirty = false;
@@ -166,7 +168,7 @@
mLinearFiltering = linearFiltering;
const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
- if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId());
+ if (bind) mCaches.bindTexture(getTextureId());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
}
@@ -186,7 +188,7 @@
if (!mTextureId) {
glGenTextures(1, &mTextureId);
- glBindTexture(GL_TEXTURE_2D, mTextureId);
+ mCaches.bindTexture(mTextureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Initialize texture dimensions
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mWidth, mHeight, 0,
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index ddcc836..8c3ea0b 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -30,6 +30,7 @@
namespace android {
namespace uirenderer {
+class Caches;
class PixelBuffer;
/**
@@ -178,9 +179,10 @@
TextureVertex* mMesh;
uint32_t mCurrentQuad;
uint32_t mMaxQuadCount;
+ Caches& mCaches;
CacheBlock* mCacheBlocks;
- Rect mDirtyRect;
bool mHasES3;
+ Rect mDirtyRect;
};
}; // namespace uirenderer
diff --git a/media/java/android/media/IRemoteControlDisplay.aidl b/media/java/android/media/IRemoteControlDisplay.aidl
index c70889c..583f436 100644
--- a/media/java/android/media/IRemoteControlDisplay.aidl
+++ b/media/java/android/media/IRemoteControlDisplay.aidl
@@ -40,6 +40,33 @@
void setCurrentClientId(int clientGeneration, in PendingIntent clientMediaIntent,
boolean clearing);
+ /**
+ * Sets the playback information (state, position and speed) of a client.
+ * @param generationId the current generation ID as known by this client
+ * @param state the current playback state, one of the following values:
+ * {@link RemoteControlClient#PLAYSTATE_STOPPED},
+ * {@link RemoteControlClient#PLAYSTATE_PAUSED},
+ * {@link RemoteControlClient#PLAYSTATE_PLAYING},
+ * {@link RemoteControlClient#PLAYSTATE_FAST_FORWARDING},
+ * {@link RemoteControlClient#PLAYSTATE_REWINDING},
+ * {@link RemoteControlClient#PLAYSTATE_SKIPPING_FORWARDS},
+ * {@link RemoteControlClient#PLAYSTATE_SKIPPING_BACKWARDS},
+ * {@link RemoteControlClient#PLAYSTATE_BUFFERING},
+ * {@link RemoteControlClient#PLAYSTATE_ERROR}.
+ * @param stateChangeTimeMs the time at which the client reported the playback information
+ * @param currentPosMs a 0 or positive value for the current media position expressed in ms
+ * Strictly negative values imply that position is not known:
+ * a value of {@link RemoteControlClient#PLAYBACK_POSITION_INVALID} is intended to express
+ * that an application doesn't know the position (e.g. listening to a live stream of a radio)
+ * or that the position information is not applicable (e.g. when state
+ * is {@link RemoteControlClient#PLAYSTATE_BUFFERING} and nothing had played yet);
+ * a value of {@link RemoteControlClient#PLAYBACK_POSITION_ALWAYS_UNKNOWN} implies that the
+ * application uses {@link RemoteControlClient#setPlaybackState(int)} (legacy API) and will
+ * never pass a playback position.
+ * @param speed a value expressed as a ratio of 1x playback: 1.0f is normal playback,
+ * 2.0f is 2x, 0.5f is half-speed, -2.0f is rewind at 2x speed. 0.0f means nothing is
+ * playing (e.g. when state is {@link RemoteControlClient#PLAYSTATE_ERROR}).
+ */
void setPlaybackState(int generationId, int state, long stateChangeTimeMs, long currentPosMs,
float speed);
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
new file mode 100644
index 0000000..eb94346
--- /dev/null
+++ b/media/java/android/media/Image.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.graphics.ImageFormat;
+import java.nio.ByteBuffer;
+import java.lang.AutoCloseable;
+
+/**
+ * <p>A single complete image buffer to use with a media source such as a
+ * {@link MediaCodec} or a
+ * {@link android.hardware.photography.CameraDevice}.</p>
+ *
+ * <p>This class allows for efficient direct application access to the pixel
+ * data of the Image through one or more
+ * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a
+ * {@link Plane} that describes the layout of the pixel data in that plane. Due
+ * to this direct access, and unlike the {@link android.graphics.Bitmap} class,
+ * Images are not directly usable as as UI resources.</p>
+ *
+ * <p>Since Images are often directly produced or consumed by hardware
+ * components, they are a limited resource shared across the system, and should
+ * be closed as soon as they are no longer needed.</p>
+ *
+ * <p>For example, when using the {@link ImageReader} class to read out Images
+ * from various media sources, not closing old Image objects will prevent the
+ * availability of new Images once
+ * {@link ImageReader#getMaxImages the maximum outstanding image count} is
+ * reached.</p>
+ *
+ * @see ImageReader
+ */
+public abstract class Image implements AutoCloseable {
+ /**
+ * Get the format for this image. This format determines the number of
+ * ByteBuffers needed to represent the image, and the general layout of the
+ * pixel data in each in ByteBuffer.
+ *
+ * The format is one of the values from
+ * {@link android.graphics.ImageFormat}. The mapping between the formats and
+ * the planes is as follows:
+ *
+ * <table>
+ * <th>
+ * <td>Format</td>
+ * <td>Plane count</td>
+ * <td>Layout details</td>
+ * </th>
+ * <tr>
+ * <td>{@link android.graphics.ImageFormat#JPEG}</td>
+ * <td>1</td>
+ * <td>Compressed data, so row and pixel strides are 0. To uncompress, use
+ * {@link android.graphics.BitmapFactory#decodeByteArray}.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link android.graphics.ImageFormat#YUV_420_888}</td>
+ * <td>3</td>
+ * <td>A luminance plane followed by the Cb and Cr chroma planes.
+ * The chroma planes have half the width and height of the luminance
+ * plane (4:2:0 subsampling). Each pixel sample in each plane has 8 bits.
+ * Each plane has its own row stride and pixel stride.</td>
+ * </tr>
+ * <tr>
+ * <td>{@link android.graphics.ImageFormat#RAW_SENSOR}</td>
+ * <td>1</td>
+ * <td>A single plane of raw sensor image data, with 16 bits per color
+ * sample. The details of the layout need to be queried from the source of
+ * the raw sensor data, such as
+ * {@link android.hardware.photography.CameraDevice}.
+ * </td>
+ * </tr>
+ * </table>
+ *
+ * @see android.graphics.ImageFormat
+ */
+ public int getFormat() {
+ return ImageFormat.UNKNOWN;
+ }
+
+ /**
+ * The width of the image in pixels. For formats where some color channels
+ * are subsampled, this is the width of the largest-resolution plane.
+ */
+ public int getWidth() {
+ return 0;
+ }
+
+ /**
+ * The height of the image in pixels. For formats where some color channels
+ * are subsampled, this is the height of the largest-resolution plane.
+ */
+ public int getHeight() {
+ return 0;
+ }
+
+ /**
+ * Get the timestamp associated with this frame. The timestamp is measured
+ * in nanoseconds, and is monotonically increasing. However, the zero point
+ * and whether the timestamp can be compared against other sources of time
+ * or images depend on the source of this image.
+ */
+ public long getTimestamp() {
+ return 0;
+ }
+
+ /**
+ * Get the array of pixel planes for this Image. The number of planes is
+ * determined by the format of the Image.
+ */
+ public Plane[] getPlanes() {
+ return null;
+ }
+
+ /**
+ * Free up this frame for reuse. After calling this method, calling any
+ * methods on this Image will result in an IllegalStateException, and
+ * attempting to read from ByteBuffers returned by an earlier
+ * {@code Plane#getBuffer} call will have undefined behavior.
+ */
+ public abstract void close();
+
+ protected final void finalize() {
+ close();
+ }
+
+ /**
+ * <p>A single color plane of image data.</p>
+ *
+ * <p>The number and meaning of the planes in an Image are determined by the
+ * format of the Image.</p>
+ *
+ * <p>Once the Image has been closed, any access to the the plane's
+ * ByteBuffer will fail.</p>
+ *
+ * @see #getFormat
+ */
+ public static final class Plane {
+ /**
+ * <p>The row stride for this color plane, in bytes.
+ *
+ * <p>This is the distance between the start of two consecutive rows of
+ * pixels in the image.</p>
+ */
+ public int getRowStride() {
+ return 0;
+ }
+
+ /**
+ * <p>The distance between adjacent pixel samples, in bytes.</p>
+ *
+ * <p>This is the distance between two consecutive pixel values in a row
+ * of pixels. It may be larger than the size of a single pixel to
+ * account for interleaved image data or padded formats.</p>
+ */
+ public int getPixelStride() {
+ return 0;
+ }
+
+ /**
+ * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
+ * containing the frame data.</p>
+ *
+ * @return the byte buffer containing the image data for this plane.
+ */
+ public ByteBuffer getBuffer() {
+ return null;
+ }
+ }
+
+}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
new file mode 100644
index 0000000..9384c14
--- /dev/null
+++ b/media/java/android/media/ImageReader.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.view.Surface;
+import java.lang.AutoCloseable;
+
+/**
+ * <p>The ImageReader class allows direct application access to image data
+ * rendered into a {@link android.view.Surface}</p>
+ *
+ * <p>Several Android media API classes accept Surface objects as targets to
+ * render to, including {@link MediaPlayer}, {@link MediaCodec},
+ * {@link android.hardware.photography.CameraDevice}, and
+ * {@link android.renderscript.Allocation RenderScript Allocations}. The image
+ * sizes and formats that can be used with each source vary, and should be
+ * checked in the documentation for the specific API.</p>
+ *
+ * <p>The image data is encapsulated in {@link Image} objects, and multiple such
+ * objects can be accessed at the same time, up to the number specified by the
+ * {@code maxImages} constructor parameter. New images sent to an ImageReader
+ * through its Surface are queued until accessed through the
+ * {@link #getNextImage} call. Due to memory limits, an image source will
+ * eventually stall or drop Images in trying to render to the Surface if the
+ * ImageReader does not obtain and release Images at a rate equal to the
+ * production rate.</p>
+ */
+public final class ImageReader {
+
+ /**
+ * <p>Create a new reader for images of the desired size and format.</p>
+ *
+ * <p>The maxImages parameter determines the maximum number of {@link Image}
+ * objects that can be be acquired from the ImageReader
+ * simultaneously. Requesting more buffers will use up more memory, so it is
+ * important to use only the minimum number necessary for the use case.</p>
+ *
+ * <p>The valid sizes and formats depend on the source of the image
+ * data.</p>
+ *
+ * @param width the width in pixels of the Images that this reader will
+ * produce.
+ * @param height the height in pixels of the Images that this reader will
+ * produce.
+ * @param format the format of the Image that this reader will produce. This
+ * must be one of the {@link android.graphics.ImageFormat} constants.
+ * @param maxImages the maximum number of images the user will want to
+ * access simultaneously. This should be as small as possible to limit
+ * memory use. Once maxImages Images are obtained by the user, one of them
+ * has to be released before a new Image will become available for access
+ * through getImage(). Must be greater than 0.
+ *
+ * @see Image
+ */
+ public ImageReader(int width, int height, int format, int maxImages) {
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mMaxImages = maxImages;
+
+ if (width < 1 || height < 1) {
+ throw new IllegalArgumentException(
+ "The image dimensions must be positive");
+ }
+ if (mMaxImages < 1) {
+ throw new IllegalArgumentException(
+ "Maximum outstanding image count must be at least 1");
+ }
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public int getImageFormat() {
+ return mFormat;
+ }
+
+ public int getMaxImages() {
+ return mMaxImages;
+ }
+
+ /**
+ * <p>Get a Surface that can be used to produce Images for this
+ * ImageReader.</p>
+ *
+ * <p>Until valid image data is rendered into this Surface, the
+ * {@link #getNextImage} method will return {@code null}. Only one source
+ * can be producing data into this Surface at the same time, although the
+ * same Surface can be reused with a different API once the first source is
+ * disconnected from the Surface.</p>
+ *
+ * @return A Surface to use for a drawing target for various APIs.
+ */
+ public Surface getSurface() {
+ return null;
+ }
+
+ /**
+ * <p>Get the next Image from the ImageReader's queue. Returns {@code null}
+ * if no new image is available.</p>
+ *
+ * @return a new frame of image data, or {@code null} if no image data is
+ * available.
+ */
+ public Image getNextImage() {
+ return null;
+ }
+
+ /**
+ * <p>Return the frame to the ImageReader for reuse.</p>
+ */
+ public void releaseImage(Image i) {
+ if (! (i instanceof SurfaceImage) ) {
+ throw new IllegalArgumentException(
+ "This image was not produced by an ImageReader");
+ }
+ SurfaceImage si = (SurfaceImage) i;
+ if (si.getReader() != this) {
+ throw new IllegalArgumentException(
+ "This image was not produced by this ImageReader");
+ }
+ }
+
+ public void setOnImageAvailableListener(OnImageAvailableListener l) {
+ mImageListener = l;
+ }
+
+ public interface OnImageAvailableListener {
+ void onImageAvailable(ImageReader reader);
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+ private final int mFormat;
+ private final int mMaxImages;
+
+ private OnImageAvailableListener mImageListener;
+
+ private class SurfaceImage extends android.media.Image {
+ public SurfaceImage() {
+ }
+
+ @Override
+ public void close() {
+ ImageReader.this.releaseImage(this);
+ }
+
+ public ImageReader getReader() {
+ return ImageReader.this;
+ }
+ }
+}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index cf159f0..e558c07 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -199,9 +199,9 @@
public native final int getTrackCount();
/**
- * Get the PSSH info if present. This returns a map of uuid-to-bytes, with the uuid specifying
+ * Get the PSSH info if present.
+ * @return a map of uuid-to-bytes, with the uuid specifying
* the crypto scheme, and the bytes being the data specific to that scheme.
- * {@hide}
*/
public Map<UUID, byte[]> getPsshInfo() {
Map<UUID, byte[]> psshMap = null;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index c6ae9aa..7379438 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -180,6 +180,12 @@
public final static long PLAYBACK_POSITION_INVALID = -1;
/**
* @hide
+ * An invalid playback position value associated with the use of {@link #setPlaybackState(int)}
+ * used to indicate that playback position will remain unknown.
+ */
+ public final static long PLAYBACK_POSITION_ALWAYS_UNKNOWN = 0x8019771980198300L;
+ /**
+ * @hide
* The default playback speed, 1x.
*/
public final static float PLAYBACK_SPEED_1X = 1.0f;
@@ -602,7 +608,8 @@
* {@link #PLAYSTATE_ERROR}.
*/
public void setPlaybackState(int state) {
- setPlaybackState(state, PLAYBACK_POSITION_INVALID, PLAYBACK_SPEED_1X);
+ setPlaybackStateInt(state, PLAYBACK_POSITION_ALWAYS_UNKNOWN, PLAYBACK_SPEED_1X,
+ false /* legacy API, converting to method with position and speed */);
}
/**
@@ -629,12 +636,28 @@
* playing (e.g. when state is {@link #PLAYSTATE_ERROR}).
*/
public void setPlaybackState(int state, long timeInMs, float playbackSpeed) {
+ setPlaybackStateInt(state, timeInMs, playbackSpeed, true);
+ }
+
+ private void setPlaybackStateInt(int state, long timeInMs, float playbackSpeed,
+ boolean hasPosition) {
synchronized(mCacheLock) {
if ((mPlaybackState != state) || (mPlaybackPositionMs != timeInMs)
|| (mPlaybackSpeed != playbackSpeed)) {
// store locally
mPlaybackState = state;
- mPlaybackPositionMs = timeInMs;
+ // distinguish between an application not knowing the current playback position
+ // at the moment and an application using the API where only the playback state
+ // is passed, not the playback position.
+ if (hasPosition) {
+ if (timeInMs < 0) {
+ mPlaybackPositionMs = PLAYBACK_POSITION_INVALID;
+ } else {
+ mPlaybackPositionMs = timeInMs;
+ }
+ } else {
+ mPlaybackPositionMs = PLAYBACK_POSITION_ALWAYS_UNKNOWN;
+ }
mPlaybackSpeed = playbackSpeed;
// keep track of when the state change occurred
mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime();
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index b698705..91ee2c6 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -71,4 +71,9 @@
android:label="Media Power tests InstrumentationRunner">
</instrumentation>
+ <instrumentation android:name=".MediaFrameworkIntegrationTestRunner"
+ android:targetPackage="com.android.mediaframeworktest"
+ android:label="MediaFramework integration tests InstrumentationRunner">
+ </instrumentation>
+
</manifest>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
new file mode 100644
index 0000000..88c5b0c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+import com.android.mediaframeworktest.integration.CameraBinderTest;
+
+import junit.framework.TestSuite;
+
+/**
+ * Instrumentation Test Runner for all media framework integration tests.
+ *
+ * Running all tests:
+ *
+ * adb shell am instrument -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ */
+
+public class MediaFrameworkIntegrationTestRunner extends InstrumentationTestRunner {
+
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(CameraBinderTest.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return MediaFrameworkIntegrationTestRunner.class.getClassLoader();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 92ac9eb..cbb6642 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -50,7 +50,7 @@
* Running all tests:
*
* adb shell am instrument \
- * -w com.android.smstests.MediaPlayerInstrumentationTestRunner
+ * -w com.android.mediaframeworktest/.MediaFrameworkTestRunner
*/
public class MediaFrameworkTestRunner extends InstrumentationTestRunner {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
index 2f864d7..7f23ba5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
@@ -36,7 +36,12 @@
/**
* Junit / Instrumentation test case for the camera api
-
+ *
+ * To run only tests in this class:
+ *
+ * adb shell am instrument \
+ * -e class com.android.mediaframeworktest.functional.CameraTest \
+ * -w com.android.mediaframeworktest/.MediaFrameworkTestRunner
*/
public class CameraTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
private String TAG = "CameraTest";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
new file mode 100644
index 0000000..ba2859b
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.integration;
+
+import android.content.Context;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.hardware.CameraInfo;
+import android.hardware.ICamera;
+import android.hardware.ICameraClient;
+import android.hardware.ICameraService;
+import android.hardware.ICameraServiceListener;
+import android.hardware.IProCameraCallbacks;
+import android.hardware.IProCameraUser;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+/**
+ * Junit / Instrumentation test case for the camera2 api
+ *
+ * To run only tests in
+ * this class:
+ *
+ * adb shell am instrument \
+ * -e class com.android.mediaframeworktest.integration.CameraBinderTest \
+ * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ */
+public class CameraBinderTest extends AndroidTestCase {
+ private static String TAG = "CameraBinderTest";
+
+ private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+ private static final int NO_ERROR = 0;
+ private static final int ALREADY_EXISTS = -17;
+ private static final int BAD_VALUE = -22;
+
+ private static final int USE_CALLING_UID = -1;
+
+ private ICameraService mCameraService;
+ private int mGuessedNumCameras = 0;
+
+ public CameraBinderTest() {
+ }
+
+ private final static boolean isFeatureAvailable(Context context, String feature) {
+ final PackageManager packageManager = context.getPackageManager();
+ final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
+ for (FeatureInfo f : featuresList) {
+ if (f.name != null && f.name.equals(feature)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Guess the lower bound for how many cameras there are
+ private void guessNumCameras() {
+
+ /**
+ * Why do we need this? This way we have no dependency on getNumCameras
+ * actually working. On most systems there are only 0, 1, or 2 cameras,
+ * and this covers that 'usual case'. On other systems there might be 3+
+ * cameras, but this will at least check the first 2.
+ */
+ mGuessedNumCameras = 0;
+
+ // Front facing camera
+ if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_FRONT)) {
+ mGuessedNumCameras++;
+ }
+
+ // Back facing camera
+ if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA)) {
+ mGuessedNumCameras++;
+ }
+
+ // Any facing camera
+ if (mGuessedNumCameras == 0
+ && isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_ANY)) {
+ mGuessedNumCameras++;
+ }
+
+ Log.v(TAG, "Guessing there are at least " + mGuessedNumCameras + " cameras");
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ guessNumCameras();
+
+ IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
+ assertNotNull("Camera service IBinder should not be null", cameraServiceBinder);
+
+ mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
+ assertNotNull("Camera service should not be null", mCameraService);
+ }
+
+ @SmallTest
+ public void testNumberOfCameras() throws Exception {
+ int numCameras = mCameraService.getNumberOfCameras();
+ assertTrue("At least this many cameras: " + mGuessedNumCameras,
+ numCameras >= mGuessedNumCameras);
+ Log.v(TAG, "Number of cameras " + numCameras);
+ }
+
+ @SmallTest
+ public void testCameraInfo() throws Exception {
+ for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+
+ CameraInfo info = new CameraInfo();
+ info.info.facing = -1;
+ info.info.orientation = -1;
+
+ assertTrue("Camera service returned info for camera " + cameraId,
+ mCameraService.getCameraInfo(cameraId, info) == NO_ERROR);
+ assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
+ assertTrue("Orientation was not set for camera " + cameraId,
+ info.info.orientation != -1);
+
+ Log.v(TAG, "Camera " + cameraId + " info: facing " + info.info.facing
+ + ", orientation " + info.info.orientation);
+ }
+ }
+
+ static abstract class DummyBase extends Binder implements android.os.IInterface {
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+ }
+
+ static class DummyCameraClient extends DummyBase implements ICameraClient {
+ }
+
+ @SmallTest
+ public void testConnect() throws Exception {
+ for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+
+ ICameraClient dummyCallbacks = new DummyCameraClient();
+
+ String clientPackageName = getContext().getPackageName();
+
+ ICamera cameraUser = mCameraService.connect(dummyCallbacks, cameraId, clientPackageName,
+ USE_CALLING_UID);
+ assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
+
+ Log.v(TAG, String.format("Camera %s connected", cameraId));
+
+ cameraUser.disconnect();
+ }
+ }
+
+ static class DummyProCameraCallbacks extends DummyBase implements IProCameraCallbacks {
+ }
+
+ @SmallTest
+ public void testConnectPro() throws Exception {
+ for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+
+ IProCameraCallbacks dummyCallbacks = new DummyProCameraCallbacks();
+
+ String clientPackageName = getContext().getPackageName();
+
+ IProCameraUser cameraUser = mCameraService.connectPro(dummyCallbacks, cameraId,
+ clientPackageName, USE_CALLING_UID);
+ assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
+
+ Log.v(TAG, String.format("Camera %s connected", cameraId));
+
+ cameraUser.disconnect();
+ }
+ }
+
+ static class DummyCameraServiceListener extends DummyBase implements ICameraServiceListener {
+ @Override
+ public void onStatusChanged(int status, int cameraId)
+ throws RemoteException {
+ Log.v(TAG, String.format("Camera %d has status changed to 0x%x", cameraId, status));
+ }
+ }
+
+ /**
+ * adb shell am instrument \
+ * -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
+ * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ */
+ @SmallTest
+ public void testAddRemoveListeners() throws Exception {
+ for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+
+ ICameraServiceListener listener = new DummyCameraServiceListener();
+
+ assertTrue("Listener was removed before added",
+ mCameraService.removeListener(listener) == BAD_VALUE);
+
+ assertTrue("Listener was not added", mCameraService.addListener(listener) == NO_ERROR);
+ assertTrue("Listener was wrongly added again",
+ mCameraService.addListener(listener) == ALREADY_EXISTS);
+
+ assertTrue("Listener was not removed",
+ mCameraService.removeListener(listener) == NO_ERROR);
+ assertTrue("Listener was wrongly removed again",
+ mCameraService.removeListener(listener) == BAD_VALUE);
+ }
+ }
+}
diff --git a/packages/SystemUI/assets/fonts/AndroidClock.ttf b/packages/SystemUI/assets/fonts/AndroidClock.ttf
deleted file mode 100644
index 7b550eed..0000000
--- a/packages/SystemUI/assets/fonts/AndroidClock.ttf
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/assets/fonts/AndroidClock2.ttf b/packages/SystemUI/assets/fonts/AndroidClock2.ttf
deleted file mode 100644
index a95d548..0000000
--- a/packages/SystemUI/assets/fonts/AndroidClock2.ttf
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index c886eea..ab45d99 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -1,10 +1,3 @@
--keep class com.android.systemui.statusbar.tablet.TabletStatusBarService {
- public void notificationIconsClicked(android.view.View);
- public void systemInfoClicked(android.view.View);
- public void recentButtonClicked(android.view.View);
- public void toggleLightsOut(android.view.View);
-}
-
-keep class com.android.systemui.statusbar.policy.KeyButtonView {
public float getDrawingAlpha();
public float getGlowAlpha();
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..1a5a8aa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..cceab0a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..e377608
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..d619f6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..515788a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..58327c1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..66dc694
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..8078424
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..50e5011
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..bb1de06
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..6de14dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..17ca21a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..0d344b9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..ac010bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..b704cdf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..3cb8f3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..d819f5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..bb1de06
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..6de14dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..17ca21a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_lte.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_lte.png
new file mode 100644
index 0000000..75c5c72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_full_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_lte.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_lte.png
new file mode 100644
index 0000000..402db43
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_lte.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_lte.png
new file mode 100644
index 0000000..7a59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_lte.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_lte.png
new file mode 100644
index 0000000..84348ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_lte.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/universe.xml b/packages/SystemUI/res/layout/universe.xml
deleted file mode 100644
index 390c467..0000000
--- a/packages/SystemUI/res/layout/universe.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent" android:layout_height="match_parent">
- <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:layout_centerHorizontal="true" android:layout_alignParentTop="true"
- android:src="@drawable/bugdroid" android:scaleType="center" />
-
- <Button android:id="@+id/close"
- android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:layout_alignParentTop="true" android:layout_alignParentEnd="true"
- android:text="@string/close_universe" />
-
- <TextView android:id="@+id/title"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:layout_below="@id/close" android:layout_centerHorizontal="true"
- android:paddingBottom="16dp"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:gravity="center" />
-
- <ImageView android:id="@+id/bottom"
- android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:layout_below="@id/title" android:layout_centerHorizontal="true"
- android:layout_marginTop="16dp" />
-</RelativeLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0ca5f98..3cc52f3 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programinligting"</string>
- <string name="close_universe" msgid="3736513750241754348">"Maak toe"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Kennisgewings af"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om kennisgewings weer aan te skakel."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 4308ec3..326f478 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"የመተግበሪያ መረጃ"</string>
- <string name="close_universe" msgid="3736513750241754348">"ዝጋ"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"ማሳወቂያዎች ጠፍተዋል"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"ማስታወቅያዎችን መልሶ ለማብራት እዚህ ጋር መታ አድርግ።"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1f0c757..6609e37 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"تم تعيين الموقع بواسطة GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"معلومات التطبيق"</string>
- <string name="close_universe" msgid="3736513750241754348">"إغلاق"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"التنبيهات معطّلة"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"انقر هنا لإعادة تشغيل الإشعارات."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"سيتم تدوير الشاشة تلقائيًا."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index b45ddb6..5367d03 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Месца задана праз GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інфармацыя пра прыкладанне"</string>
- <string name="close_universe" msgid="3736513750241754348">"Закрыць"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Паведамленні адключаны"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Націсніце тут, каб зноў уключыць апавяшчэнні."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран паварочваецца аўтаматычна."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index c161fbd..06321af 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информация за приложението"</string>
- <string name="close_universe" msgid="3736513750241754348">"Затваряне"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Известията са изключени"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Докоснете тук, за да включите отново известията."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5cf131d..0801f69 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informació de l\'aplicació"</string>
- <string name="close_universe" msgid="3736513750241754348">"Tanca"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificacions desactivades"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Pica aquí per tornar a activar les notificacions."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 0f03db1..ca7cac0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informace o aplikaci"</string>
- <string name="close_universe" msgid="3736513750241754348">"Zavřít"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Oznámení jsou vypnuta"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Chcete-li oznámení znovu zapnout, klepněte sem."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otočí."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b6a92a6..a37a8f6 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
- <string name="close_universe" msgid="3736513750241754348">"Luk"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Underretninger slået fra"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tryk her for at slå underretninger til igen."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3a3c451..a6104ba 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-Details"</string>
- <string name="close_universe" msgid="3736513750241754348">"Schließen"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Benachrichtigungen aus"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tippen Sie hier, um die Benachrichtigungen wieder zu aktivieren."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index befd927..9c6a513 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Πληροφορίες εφαρμογής"</string>
- <string name="close_universe" msgid="3736513750241754348">"Κλείσιμο"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Ειδοποιήσεις ανενεργές"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Πατήστε εδώ για να ενεργοποιήσετε ξανά τις ειδοποιήσεις."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 1427c87..6ef894d 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App info"</string>
- <string name="close_universe" msgid="3736513750241754348">"Close"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notifications off"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tap here to turn notifications back on."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 21c6e750..c94a237 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
- <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
@@ -207,5 +206,5 @@
<string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
<string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Desliza el dedo hacia arriba desde la parte inferior de la pantalla para mostrar la barra del sistema."</string>
<string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Desliza el dedo desde la parte inferior de la pantalla para mostrar la barra."</string>
- <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza el dedo desde la parte derecha de la pantalla para mostrar la barra del sistema."</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza el dedo desde la derecha de la pantalla para mostrar la barra del sistema."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b2cb952..acef755 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
- <string name="close_universe" msgid="3736513750241754348">"Cerrar"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificaciones desactivadas"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Toca aquí para volver a activar las notificaciones."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index e2324b5..f091640 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Rakenduse teave"</string>
- <string name="close_universe" msgid="3736513750241754348">"Sule"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Teatised väljas"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Teatiste uuesti sisselülitamiseks puudutage siin."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index a3eb06b..5abcc05 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"مکان تنظیم شده توسط GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلانها"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"اطلاعات برنامه"</string>
- <string name="close_universe" msgid="3736513750241754348">"بستن"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"اعلانها خاموش"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"برای روشن کردن مجدد اعلانها، اینجا را ضربه بزنید."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"صفحه به صورت خودکار میچرخد."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c975970..26a355e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Sovelluksen tiedot"</string>
- <string name="close_universe" msgid="3736513750241754348">"Sulje"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Ilmoitukset pois käytöstä"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 3b7f798..4fd43d6 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
- <string name="close_universe" msgid="3736513750241754348">"Fermer"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notifications désactivées"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Appuyez ici pour réactiver les notifications."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 05fffc36..ed9654f1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्थान"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"एप्लिकेशन जानकारी"</string>
- <string name="close_universe" msgid="3736513750241754348">"बंद करें"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"सूचनाएं बंद"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"सूचनाओं को पुन: चालू करने के लिए यहां टैप करें."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वचालित रूप से घूमेगी."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 0f7f92f..777c048 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informacije o aplikaciji"</string>
- <string name="close_universe" msgid="3736513750241754348">"Zatvori"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Obavijesti isključene"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 82b3ddd..b354024 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Alkalmazásinformáció"</string>
- <string name="close_universe" msgid="3736513750241754348">"Bezárás"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Értesítések kikapcsolva"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Itt érintse meg az értesítések bekapcsolásához."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d9597da..68d3796 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info aplikasi"</string>
- <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan mati"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Ketuk di sini untuk menyalakan pemberitahuan lagi."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6ef9a8e..398650e9 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informazioni applicazione"</string>
- <string name="close_universe" msgid="3736513750241754348">"Chiudi"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notifiche disattivate"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tocca qui per riattivare le notifiche."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8a3f1550..96f8a4a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"פרטי יישום"</string>
- <string name="close_universe" msgid="3736513750241754348">"סגור"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"מצב התראות כבוי"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"הקש כאן כדי להפעיל מחדש את ההתראות."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 95f24fd..eff450d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"アプリ情報"</string>
- <string name="close_universe" msgid="3736513750241754348">"閉じる"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"通知OFF"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"通知を再度ONにするにはここをタップします。"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index dc82a01..0bcc626 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"앱 정보"</string>
- <string name="close_universe" msgid="3736513750241754348">"닫기"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"알림 사용 안함"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"알림을 다시 사용하려면 여기를 터치하세요."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index b2c5d2c..03de3c5 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programos informacija"</string>
- <string name="close_universe" msgid="3736513750241754348">"Uždaryti"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Pranešimai išjungti"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Jei norite vėl įjungti pranešimus, palieskite čia."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 41d1158..2f4e9c2 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informācija par lietotni"</string>
- <string name="close_universe" msgid="3736513750241754348">"Aizvērt"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Paziņojumi ir izslēgti"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Pieskarieties šeit, lai atkal ieslēgtu paziņojumus."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index cabd7b5..cb9d961 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Maklumat apl"</string>
- <string name="close_universe" msgid="3736513750241754348">"Tutup"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Pemberitahuan dimatikan"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
@@ -203,7 +202,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
- <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Leret ke atas dari bahagian bawah skrin untuk mendedahkan bar sistem"</string>
- <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Leret ke bahagian bawah skrin untuk mendedahkan bar"</string>
- <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Leret dari kanan skrin untuk mendedahkan bar sistem"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Leret ke atas dari bahagian bawah skrin untuk menampakkan bar sistem"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Leret ke bahagian bawah skrin untuk menampakkan bar"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Leret dari kanan skrin untuk menampakkan bar sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 31953c3..e0df440 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om app"</string>
- <string name="close_universe" msgid="3736513750241754348">"Lukk"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Varsler er deaktivert"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Trykk her for å aktivere varsler på nytt."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6661bfa..9457da2 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-info"</string>
- <string name="close_universe" msgid="3736513750241754348">"Sluiten"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Meldingen uit"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tik hier om meldingen weer in te schakelen."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c97372d..947bd4e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
- <string name="close_universe" msgid="3736513750241754348">"Zamknij"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Powiadomienia wyłączone"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Kliknij tutaj, by przywrócić powiadomienia."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index eba6c18..f54034d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações da aplicação"</string>
- <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para voltar a ativar as notificações."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 93b0e2d..4ee6554 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações do aplicativo"</string>
- <string name="close_universe" msgid="3736513750241754348">"Fechar"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificações desativadas"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Toque aqui para ativar as notificações novamente."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 948b959..1265b64 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -304,8 +304,6 @@
<skip />
<!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
<skip />
- <!-- no translation found for close_universe (3736513750241754348) -->
- <skip />
<!-- no translation found for notifications_off_title (8936620513608443224) -->
<skip />
<!-- no translation found for notifications_off_text (2529001315769385273) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7faa2e4..97d81e8 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeţi toate notificările."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informaţii despre aplicaţie"</string>
- <string name="close_universe" msgid="3736513750241754348">"Închideţi"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Notificările sunt dezactivate"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Apăsaţi aici pentru a reactiva notificările."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 2ca195a..b26ef9d 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"О приложении"</string>
- <string name="close_universe" msgid="3736513750241754348">"Закрыть"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Уведомления отключены"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Нажмите здесь, чтобы снова включить уведомления."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index e5e1d58..92ff8c9 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informácie o aplikácii"</string>
- <string name="close_universe" msgid="3736513750241754348">"Zavrieť"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Upozornenia sú vypnuté"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Klepnutím sem upozornenia znova povolíte."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5a0f46af..4c36308 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Podatki o aplikaciji"</string>
- <string name="close_universe" msgid="3736513750241754348">"Zapri"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Obvestila so izklopljena"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Dotaknite se tukaj, da ponovno vklopite obvestila."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 6a209d0..00a92a9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информације о апликацији"</string>
- <string name="close_universe" msgid="3736513750241754348">"Затвори"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Обавештења су искључена"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Додирните овде да бисте поново укључили обавештења."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран ће се аутоматски ротирати."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index b1c1cf6..38689e4 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om appen"</string>
- <string name="close_universe" msgid="3736513750241754348">"Stäng"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Meddelanden inaktiverade"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Knacka lätt här om du vill aktivera meddelanden igen."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 2c8100d..1fa3b4d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -165,7 +165,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Taarifa ya programu"</string>
- <string name="close_universe" msgid="3736513750241754348">"Funga"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Arifa zimelemazwa"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Gonga hapa ili kuwezesha tena arifa."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
@@ -200,8 +199,8 @@
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ung\'avu"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
- <string name="status_bar_help_text" msgid="7874607155052076323">"Wafikie wakati wowote kwa kupapasa chini."\n"Papasa chini tena kupata vidhibiti vya mfumo."</string>
- <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Papasa kwenda juu kutoka chini ya skrini ili kuonyesha upau wa mfumo"</string>
- <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Papasa chini ya skrini ili kuonyesha upau"</string>
- <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Papasa kutoka kulia kwa skrini ili kuonyesha upau wa mfumo"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Zifikie wakati wowote kwa kutelezesha chini."\n"Telezesha chini tena kupata vidhibiti vya mfumo."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Telezesha kwenda juu kutoka chini ya skrini ili kuonyesha upau wa mfumo"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Telezesha sehemu ya chini ya skrini ili kuonyesha upau"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Telezesha kutoka kulia mwa skrini ili kuonyesha upau wa mfumo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f36e07f..e7f93ed 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ข้อมูลแอป"</string>
- <string name="close_universe" msgid="3736513750241754348">"ปิด"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"การแจ้งเตือนปิดอยู่"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"หน้าจอจะหมุนโดยอัตโนมัติ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 68b7896..4579b43 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Impormasyon ng app"</string>
- <string name="close_universe" msgid="3736513750241754348">"Isara"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Naka-off ang mga notification"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Tumapik dito upang muling i-on ang mga notification."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0017a9e..9bccbb9 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Uygulama bilgileri"</string>
- <string name="close_universe" msgid="3736513750241754348">"Kapat"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Bildirimler kapalı"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a9b0fe7..1df9c28 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інформація про програму"</string>
- <string name="close_universe" msgid="3736513750241754348">"Закрити"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Сповіщення вимкнено"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Торкніться тут, щоб знову ввімкнути сповіщення."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 38f6036..f37fa47 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Thông tin về ứng dụng"</string>
- <string name="close_universe" msgid="3736513750241754348">"Đóng"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Tắt thông báo"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Chạm vào đây để bật lại thông báo."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 18814c7..57c93cc 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"应用信息"</string>
- <string name="close_universe" msgid="3736513750241754348">"关闭"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"通知功能已停用"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"点按此处可重新启用通知功能。"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index af3e469..d57e82e 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -169,7 +169,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"應用程式資訊"</string>
- <string name="close_universe" msgid="3736513750241754348">"關閉"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"關閉通知"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"輕按這裡即可重新開啟通知。"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index af790a3..710225d 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -167,7 +167,6 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Ulwazi lohlelo lokusebenza"</string>
- <string name="close_universe" msgid="3736513750241754348">"Vala"</string>
<string name="notifications_off_title" msgid="8936620513608443224">"Izaziso zivaliwe"</string>
<string name="notifications_off_text" msgid="2529001315769385273">"Thepha lapha ukuvula futhi izaziso."</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index a27630d..4c81c88 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -102,5 +102,8 @@
<!-- Enable the "flip settings" panel -->
<bool name="config_hasFlipSettingsPanel">true</bool>
+
+ <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
+ <bool name="config_show4GForLTE">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d003a09..9498fe4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -320,6 +320,9 @@
<!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_4g">4G</string>
+ <!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_connection_lte">LTE</string>
+
<!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_cdma">CDMA</string>
@@ -433,9 +436,6 @@
application -->
<string name="status_bar_notification_inspect_item_title">App info</string>
- <!-- [CHAR LIMIT=NONE] -->
- <string name="close_universe">Close</string>
-
<!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
mode) -->
<string name="notifications_off_title">Notifications off</string>
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
index d3ce30d..8e24eeb 100644
--- a/packages/SystemUI/src/com/android/systemui/BootReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
@@ -21,7 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
/**
* Performs a number of miscellaneous, non-system-critical actions
@@ -40,7 +40,7 @@
context.startService(loadavg);
}
} catch (Exception e) {
- Slog.e(TAG, "Can't start load average service", e);
+ Log.e(TAG, "Can't start load average service", e);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index edfaf49..0019c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -23,7 +23,7 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Vibrator;
-import android.util.Slog;
+import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
@@ -113,7 +113,7 @@
= new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
- if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
+ if (DEBUG_SCALE) Log.v(TAG, "onscalebegin()");
float focusX = detector.getFocusX();
float focusY = detector.getFocusY();
@@ -126,7 +126,7 @@
@Override
public boolean onScale(ScaleGestureDetector detector) {
- if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
+ if (DEBUG_SCALE) Log.v(TAG, "onscale() on " + mCurrView);
return true;
}
@@ -143,7 +143,7 @@
mView = v;
}
public void setHeight(float h) {
- if (DEBUG_SCALE) Slog.v(TAG, "SetHeight: setting to " + h);
+ if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
ViewGroup.LayoutParams lp = mView.getLayoutParams();
lp.height = (int)h;
mView.setLayoutParams(lp);
@@ -158,7 +158,7 @@
}
public int getNaturalHeight(int maximum) {
ViewGroup.LayoutParams lp = mView.getLayoutParams();
- if (DEBUG_SCALE) Slog.v(TAG, "Inspecting a child of type: " +
+ if (DEBUG_SCALE) Log.v(TAG, "Inspecting a child of type: " +
mView.getClass().getName());
int oldHeight = lp.height;
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -230,7 +230,7 @@
}
private void updateExpansion() {
- if (DEBUG_SCALE) Slog.v(TAG, "updateExpansion()");
+ if (DEBUG_SCALE) Log.v(TAG, "updateExpansion()");
// are we scaling or dragging?
float span = mSGD.getCurrentSpan() - mInitialTouchSpan;
span *= USE_SPAN ? 1f : 0f;
@@ -270,10 +270,10 @@
}
private boolean isInside(View v, float x, float y) {
- if (DEBUG) Slog.d(TAG, "isinside (" + x + ", " + y + ")");
+ if (DEBUG) Log.d(TAG, "isinside (" + x + ", " + y + ")");
if (v == null) {
- if (DEBUG) Slog.d(TAG, "isinside null subject");
+ if (DEBUG) Log.d(TAG, "isinside null subject");
return false;
}
if (mEventSource != null) {
@@ -281,14 +281,14 @@
mEventSource.getLocationOnScreen(location);
x += location[0];
y += location[1];
- if (DEBUG) Slog.d(TAG, " to global (" + x + ", " + y + ")");
+ if (DEBUG) Log.d(TAG, " to global (" + x + ", " + y + ")");
}
int[] location = new int[2];
v.getLocationOnScreen(location);
x -= location[0];
y -= location[1];
- if (DEBUG) Slog.d(TAG, " to local (" + x + ", " + y + ")");
- if (DEBUG) Slog.d(TAG, " inside (" + v.getWidth() + ", " + v.getHeight() + ")");
+ if (DEBUG) Log.d(TAG, " to local (" + x + ", " + y + ")");
+ if (DEBUG) Log.d(TAG, " inside (" + v.getWidth() + ", " + v.getHeight() + ")");
boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
return inside;
}
@@ -307,10 +307,10 @@
private float calculateGlow(float target, float actual) {
// glow if overscale
- if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
+ if (DEBUG_GLOW) Log.d(TAG, "target: " + target + " actual: " + actual);
float stretch = Math.abs((target - actual) / mMaximumStretch);
float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
- if (DEBUG_GLOW) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
+ if (DEBUG_GLOW) Log.d(TAG, "stretch: " + stretch + " strength: " + strength);
return (GLOW_BASE + strength * (1f - GLOW_BASE));
}
@@ -348,7 +348,7 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
- if (DEBUG_SCALE) Slog.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
+ if (DEBUG_SCALE) Log.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
" expanding=" + mExpanding +
(0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
(0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
@@ -362,7 +362,7 @@
mInitialTouchSpan = mSGD.getCurrentSpan();
mLastFocusY = mInitialTouchFocusY;
mLastSpanY = mInitialTouchSpan;
- if (DEBUG_SCALE) Slog.d(TAG, "set initial span: " + mInitialTouchSpan);
+ if (DEBUG_SCALE) Log.d(TAG, "set initial span: " + mInitialTouchSpan);
if (mExpanding) {
return true;
@@ -376,7 +376,7 @@
xspan > mPullGestureMinXSpan &&
xspan > mSGD.getCurrentSpanY())) {
// detect a vertical pulling gesture with fingers somewhat separated
- if (DEBUG_SCALE) Slog.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
+ if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
final View underFocus = findView(x, y);
if (underFocus != null) {
@@ -393,7 +393,7 @@
if (mWatchingForPull) {
final int yDiff = y - mLastMotionY;
if (yDiff > mTouchSlop) {
- if (DEBUG) Slog.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
+ if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
mLastMotionY = y;
final View underFocus = findView(x, y);
if (underFocus != null) {
@@ -413,7 +413,7 @@
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- if (DEBUG) Slog.d(TAG, "up/cancel");
+ if (DEBUG) Log.d(TAG, "up/cancel");
finishExpanding(false);
clearView();
break;
@@ -425,7 +425,7 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
- if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
+ if (DEBUG_SCALE) Log.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
" expanding=" + mExpanding +
(0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
(0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
@@ -484,14 +484,14 @@
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
- if (DEBUG) Slog.d(TAG, "pointer change");
+ if (DEBUG) Log.d(TAG, "pointer change");
mInitialTouchY += mSGD.getFocusY() - mLastFocusY;
mInitialTouchSpan += mSGD.getCurrentSpan() - mLastSpanY;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (DEBUG) Slog.d(TAG, "up/cancel");
+ if (DEBUG) Log.d(TAG, "up/cancel");
finishExpanding(false);
clearView();
break;
@@ -505,20 +505,20 @@
return;
}
mExpanding = true;
- if (DEBUG) Slog.d(TAG, "scale type " + expandType + " beginning on view: " + v);
+ if (DEBUG) Log.d(TAG, "scale type " + expandType + " beginning on view: " + v);
mCallback.setUserLockedChild(v, true);
setView(v);
setGlow(GLOW_BASE);
mScaler.setView(v);
mOldHeight = mScaler.getHeight();
if (mCallback.canChildBeExpanded(v)) {
- if (DEBUG) Slog.d(TAG, "working on an expandable child");
+ if (DEBUG) Log.d(TAG, "working on an expandable child");
mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
} else {
- if (DEBUG) Slog.d(TAG, "working on a non-expandable child");
+ if (DEBUG) Log.d(TAG, "working on a non-expandable child");
mNaturalHeight = mOldHeight;
}
- if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
+ if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
" mNaturalHeight: " + mNaturalHeight);
v.getParent().requestDisallowInterceptTouchEvent(true);
}
@@ -526,7 +526,7 @@
private void finishExpanding(boolean force) {
if (!mExpanding) return;
- if (DEBUG) Slog.d(TAG, "scale in finishing on view: " + mCurrView);
+ if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mCurrView);
float currentHeight = mScaler.getHeight();
float targetHeight = mSmallSize;
@@ -552,11 +552,11 @@
mExpanding = false;
mExpansionStyle = NONE;
- if (DEBUG) Slog.d(TAG, "wasClosed is: " + wasClosed);
- if (DEBUG) Slog.d(TAG, "currentHeight is: " + currentHeight);
- if (DEBUG) Slog.d(TAG, "mSmallSize is: " + mSmallSize);
- if (DEBUG) Slog.d(TAG, "targetHeight is: " + targetHeight);
- if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
+ if (DEBUG) Log.d(TAG, "wasClosed is: " + wasClosed);
+ if (DEBUG) Log.d(TAG, "currentHeight is: " + currentHeight);
+ if (DEBUG) Log.d(TAG, "mSmallSize is: " + mSmallSize);
+ if (DEBUG) Log.d(TAG, "targetHeight is: " + targetHeight);
+ if (DEBUG) Log.d(TAG, "scale was finished on view: " + mCurrView);
}
private void clearView() {
@@ -575,7 +575,7 @@
String debugLog = "Looking for glows: " +
(mCurrViewTopGlow != null ? "found top " : "didn't find top") +
(mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
- Slog.v(TAG, debugLog);
+ Log.v(TAG, debugLog);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 1f29990..ab11748 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -32,7 +32,7 @@
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.EventLog;
-import android.util.Slog;
+import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.View;
@@ -120,7 +120,7 @@
mContext.startActivityAsUser(intent, opts.toBundle(),
new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
- Slog.w(TAG, "Activity not found for " + intent.getAction());
+ Log.w(TAG, "Activity not found for " + intent.getAction());
onAnimationStarted();
}
}
@@ -186,7 +186,7 @@
if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
ASSIST_ICON_METADATA_NAME,
com.android.internal.R.drawable.ic_action_assist_generic)) {
- if (DEBUG) Slog.v(TAG, "Couldn't grab icon for component " + component);
+ if (DEBUG) Log.v(TAG, "Couldn't grab icon for component " + component);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index e1aed82..ebd7fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,7 +24,7 @@
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.Slog;
+import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
@@ -70,14 +70,14 @@
? R.string.config_systemBarComponent
: R.string.config_statusBarComponent;
} catch (RemoteException e) {
- Slog.w(TAG, "Failing checking whether status bar can hide", e);
+ Log.w(TAG, "Failing checking whether status bar can hide", e);
}
final int N = SERVICES.length;
mServices = new SystemUI[N];
for (int i=0; i<N; i++) {
Class cl = chooseClass(SERVICES[i]);
- Slog.d(TAG, "loading: " + cl);
+ Log.d(TAG, "loading: " + cl);
try {
mServices[i] = (SystemUI)cl.newInstance();
} catch (IllegalAccessException ex) {
@@ -86,7 +86,7 @@
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
- Slog.d(TAG, "running: " + mServices[i]);
+ Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
deleted file mode 100644
index f859880..0000000
--- a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Matrix;
-import android.graphics.PixelFormat;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.Slog;
-import android.view.Choreographer;
-import android.view.Display;
-import android.view.IWindowSession;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewRootImpl;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.view.animation.Transformation;
-import android.widget.FrameLayout;
-
-public class UniverseBackground extends FrameLayout {
- static final String TAG = "UniverseBackground";
- static final boolean SPEW = false;
- static final boolean CHATTY = false;
-
- final IWindowSession mSession;
- final View mContent;
- final View mBottomAnchor;
-
- final Runnable mAnimationCallback = new Runnable() {
- @Override
- public void run() {
- doAnimation(mChoreographer.getFrameTimeNanos());
- }
- };
-
- // fling gesture tuning parameters, scaled to display density
- private float mSelfExpandVelocityPx; // classic value: 2000px/s
- private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
- private float mFlingExpandMinVelocityPx; // classic value: 200px/s
- private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
- private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
- private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
- private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
-
- private float mExpandAccelPx; // classic value: 2000px/s/s
- private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
-
- static final int STATE_CLOSED = 0;
- static final int STATE_OPENING = 1;
- static final int STATE_OPEN = 2;
- private int mState = STATE_CLOSED;
-
- private float mDragStartX, mDragStartY;
- private float mAverageX, mAverageY;
-
- // position
- private int[] mPositionTmp = new int[2];
- private boolean mExpanded;
- private boolean mExpandedVisible;
-
- private boolean mTracking;
- private VelocityTracker mVelocityTracker;
-
- private Choreographer mChoreographer;
- private boolean mAnimating;
- private boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
- private float mAnimY;
- private float mAnimVel;
- private float mAnimAccel;
- private long mAnimLastTimeNanos;
- private boolean mAnimatingReveal = false;
-
- private int mYDelta = 0;
- private Transformation mUniverseTransform = new Transformation();
- private final float[] mTmpFloats = new float[9];
-
- public UniverseBackground(Context context) {
- super(context);
- setBackgroundColor(0xff000000);
- mSession = WindowManagerGlobal.getWindowSession();
- mContent = View.inflate(context, R.layout.universe, null);
- addView(mContent);
- mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
- @Override public void onClick(View v) {
- animateCollapse();
- }
- });
- mBottomAnchor = mContent.findViewById(R.id.bottom);
- mChoreographer = Choreographer.getInstance();
- loadDimens();
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- loadDimens();
- }
-
- private void loadDimens() {
- final Resources res = getContext().getResources();
- mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
- mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
- mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
- mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
-
- mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
- mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
-
- mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
- mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
-
- mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
- }
-
- private void computeAveragePos(MotionEvent event) {
- final int num = event.getPointerCount();
- float x = 0, y = 0;
- for (int i=0; i<num; i++) {
- x += event.getX(i);
- y += event.getY(i);
- }
- mAverageX = x / num;
- mAverageY = y / num;
- }
-
- private void sendUniverseTransform() {
- if (getWindowToken() != null) {
- mUniverseTransform.getMatrix().getValues(mTmpFloats);
- try {
- mSession.setUniverseTransform(getWindowToken(), mUniverseTransform.getAlpha(),
- mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y],
- mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
- mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
- } catch (RemoteException e) {
- }
- }
- }
-
- public WindowManager.LayoutParams getLayoutParams() {
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
- 0
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.OPAQUE);
- // this will allow the window to run in an overlay on devices that support this
- if (ActivityManager.isHighEndGfx()) {
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
- lp.setTitle("UniverseBackground");
- lp.windowAnimations = 0;
- return lp;
- }
-
- private int getExpandedViewMaxHeight() {
- return mBottomAnchor.getTop();
- }
-
- public void animateCollapse() {
- animateCollapse(1.0f);
- }
-
- public void animateCollapse(float velocityMultiplier) {
- if (SPEW) {
- Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
- + " mExpandedVisible=" + mExpandedVisible
- + " mExpanded=" + mExpanded
- + " mAnimating=" + mAnimating
- + " mAnimY=" + mAnimY
- + " mAnimVel=" + mAnimVel);
- }
-
- mState = STATE_CLOSED;
- if (!mExpandedVisible) {
- return;
- }
-
- int y;
- if (mAnimating) {
- y = (int)mAnimY;
- } else {
- y = getExpandedViewMaxHeight()-1;
- }
- // Let the fling think that we're open so it goes in the right direction
- // and doesn't try to re-open the windowshade.
- mExpanded = true;
- prepareTracking(y, false);
- performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
- }
-
- private void updateUniverseScale() {
- if (mYDelta > 0) {
- int w = getWidth();
- int h = getHeight();
- float scale = (h-mYDelta+.5f) / (float)h;
- mUniverseTransform.getMatrix().setScale(scale, scale, w/2, h);
- if (CHATTY) Log.i(TAG, "w=" + w + " h=" + h + " scale=" + scale
- + ": " + mUniverseTransform);
- sendUniverseTransform();
- if (getVisibility() != VISIBLE) {
- setVisibility(VISIBLE);
- }
- } else {
- if (CHATTY) Log.i(TAG, "mYDelta=" + mYDelta);
- mUniverseTransform.clear();
- sendUniverseTransform();
- if (getVisibility() == VISIBLE) {
- setVisibility(GONE);
- }
- }
- }
-
- void resetLastAnimTime() {
- mAnimLastTimeNanos = System.nanoTime();
- if (SPEW) {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
- }
- }
-
- void doAnimation(long frameTimeNanos) {
- if (mAnimating) {
- if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
- if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
- incrementAnim(frameTimeNanos);
- if (SPEW) {
- Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
- }
-
- if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
- if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
- mAnimating = false;
- mYDelta = getExpandedViewMaxHeight();
- updateUniverseScale();
- mExpanded = true;
- mState = STATE_OPEN;
- return;
- }
-
- if (mAnimY <= 0 && mClosing) {
- if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
- mAnimating = false;
- mYDelta = 0;
- updateUniverseScale();
- mExpanded = false;
- mState = STATE_CLOSED;
- return;
- }
-
- mYDelta = (int)mAnimY;
- updateUniverseScale();
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- }
- }
-
- void stopTracking() {
- mTracking = false;
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
-
- void incrementAnim(long frameTimeNanos) {
- final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
- final float t = deltaNanos * 0.000000001f; // ns -> s
- final float y = mAnimY;
- final float v = mAnimVel; // px/s
- final float a = mAnimAccel; // px/s/s
- mAnimY = y + (v*t) + (0.5f*a*t*t); // px
- mAnimVel = v + (a*t); // px/s
- mAnimLastTimeNanos = frameTimeNanos; // ns
- //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
- // + " mAnimAccel=" + mAnimAccel);
- }
-
- void prepareTracking(int y, boolean opening) {
- if (CHATTY) {
- Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
- }
-
- mTracking = true;
- mVelocityTracker = VelocityTracker.obtain();
- if (opening) {
- mAnimAccel = mExpandAccelPx;
- mAnimVel = mFlingExpandMinVelocityPx;
- mAnimY = y;
- mAnimating = true;
- mAnimatingReveal = true;
- resetLastAnimTime();
- mExpandedVisible = true;
- }
- if (mAnimating) {
- mAnimating = false;
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- }
- }
-
- void performFling(int y, float vel, boolean always) {
- if (CHATTY) {
- Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
- }
-
- mAnimatingReveal = false;
-
- mAnimY = y;
- mAnimVel = vel;
-
- //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
-
- if (mExpanded) {
- if (!always && (
- vel > mFlingCollapseMinVelocityPx
- || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
- vel > -mFlingExpandMinVelocityPx))) {
- // We are expanded, but they didn't move sufficiently to cause
- // us to retract. Animate back to the expanded position.
- mAnimAccel = mExpandAccelPx;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are expanded and are now going to animate away.
- mAnimAccel = -mCollapseAccelPx;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- } else {
- if (always || (
- vel > mFlingExpandMinVelocityPx
- || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
- vel > -mFlingCollapseMinVelocityPx))) {
- // We are collapsed, and they moved enough to allow us to
- // expand. Animate in the notifications.
- mAnimAccel = mExpandAccelPx;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are collapsed, but they didn't move sufficiently to cause
- // us to retract. Animate back to the collapsed position.
- mAnimAccel = -mCollapseAccelPx;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- }
- //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
- // + " mAnimAccel=" + mAnimAccel);
-
- resetLastAnimTime();
- mAnimating = true;
- mClosing = mAnimAccel < 0;
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
-
- stopTracking();
- }
-
- private void trackMovement(MotionEvent event) {
- mVelocityTracker.addMovement(event);
- }
-
- public boolean consumeEvent(MotionEvent event) {
- if (mState == STATE_CLOSED) {
- if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
- // Second finger down, time to start opening!
- computeAveragePos(event);
- mDragStartX = mAverageX;
- mDragStartY = mAverageY;
- mYDelta = 0;
- mUniverseTransform.clear();
- sendUniverseTransform();
- setVisibility(VISIBLE);
- mState = STATE_OPENING;
- prepareTracking((int)mDragStartY, true);
- mVelocityTracker.clear();
- trackMovement(event);
- return true;
- }
- return false;
- }
-
- if (mState == STATE_OPENING) {
- if (event.getActionMasked() == MotionEvent.ACTION_UP
- || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
- mVelocityTracker.computeCurrentVelocity(1000);
- computeAveragePos(event);
-
- float yVel = mVelocityTracker.getYVelocity();
- boolean negative = yVel < 0;
-
- float xVel = mVelocityTracker.getXVelocity();
- if (xVel < 0) {
- xVel = -xVel;
- }
- if (xVel > mFlingGestureMaxXVelocityPx) {
- xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
- }
-
- float vel = (float)Math.hypot(yVel, xVel);
- if (negative) {
- vel = -vel;
- }
-
- if (CHATTY) {
- Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
- mVelocityTracker.getXVelocity(),
- mVelocityTracker.getYVelocity(),
- xVel, yVel,
- vel));
- }
-
- performFling((int)mAverageY, vel, false);
- mState = STATE_OPEN;
- return true;
- }
-
- computeAveragePos(event);
- mYDelta = (int)(mAverageY - mDragStartY);
- if (mYDelta > getExpandedViewMaxHeight()) {
- mYDelta = getExpandedViewMaxHeight();
- }
- updateUniverseScale();
- return true;
- }
-
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 0c6e59c..5b4bb2c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -28,10 +28,9 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.util.Slog;
+import android.util.Log;
import com.android.systemui.SystemUI;
-import com.google.android.collect.Maps;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -50,7 +49,7 @@
private IAudioService mAudioService;
private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
- private final HashMap<IBinder, Client> mClients = Maps.newHashMap();
+ private final HashMap<IBinder, Client> mClients = new HashMap<IBinder, Client>();
@Override
public void start() {
@@ -61,7 +60,7 @@
try {
mAudioService.setRingtonePlayer(mCallback);
} catch (RemoteException e) {
- Slog.e(TAG, "Problem registering RingtonePlayer: " + e);
+ Log.e(TAG, "Problem registering RingtonePlayer: " + e);
}
}
@@ -82,7 +81,7 @@
@Override
public void binderDied() {
- if (LOGD) Slog.d(TAG, "binderDied() token=" + mToken);
+ if (LOGD) Log.d(TAG, "binderDied() token=" + mToken);
synchronized (mClients) {
mClients.remove(mToken);
}
@@ -94,7 +93,7 @@
@Override
public void play(IBinder token, Uri uri, int streamType) throws RemoteException {
if (LOGD) {
- Slog.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
+ Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
+ Binder.getCallingUid() + ")");
}
Client client;
@@ -112,7 +111,7 @@
@Override
public void stop(IBinder token) {
- if (LOGD) Slog.d(TAG, "stop(token=" + token + ")");
+ if (LOGD) Log.d(TAG, "stop(token=" + token + ")");
Client client;
synchronized (mClients) {
client = mClients.remove(token);
@@ -125,7 +124,7 @@
@Override
public boolean isPlaying(IBinder token) {
- if (LOGD) Slog.d(TAG, "isPlaying(token=" + token + ")");
+ if (LOGD) Log.d(TAG, "isPlaying(token=" + token + ")");
Client client;
synchronized (mClients) {
client = mClients.get(token);
@@ -139,7 +138,7 @@
@Override
public void playAsync(Uri uri, UserHandle user, boolean looping, int streamType) {
- if (LOGD) Slog.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
+ if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
@@ -149,7 +148,7 @@
@Override
public void stopAsync() {
- if (LOGD) Slog.d(TAG, "stopAsync()");
+ if (LOGD) Log.d(TAG, "stopAsync()");
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
index 888b76e..1ac8295 100644
--- a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
@@ -32,7 +32,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.Slog;
+import android.util.Log;
import android.view.WindowManager;
import com.android.systemui.R;
@@ -79,7 +79,7 @@
try {
policyService.snoozeLimit(template);
} catch (RemoteException e) {
- Slog.w(TAG, "problem snoozing network policy", e);
+ Log.w(TAG, "problem snoozing network policy", e);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index ccb711a..0d26c57 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -35,7 +35,7 @@
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
@@ -126,19 +126,19 @@
int bucket = findBatteryLevelBucket(mBatteryLevel);
if (DEBUG) {
- Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ Log.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
- Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
- Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
- Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
- Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
- Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
- Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
+ Log.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
+ Log.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
+ Log.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
+ Log.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
+ Log.d(TAG, "bucket " + oldBucket + " --> " + bucket);
+ Log.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
}
if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
- Slog.d(TAG, "showing invalid charger warning");
+ Log.d(TAG, "showing invalid charger warning");
showInvalidChargerDialog();
return;
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
@@ -164,20 +164,20 @@
showLowBatteryWarning();
}
} else {
- Slog.w(TAG, "unknown intent: " + intent);
+ Log.w(TAG, "unknown intent: " + intent);
}
}
};
void dismissLowBatteryWarning() {
if (mLowBatteryDialog != null) {
- Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
+ Log.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
mLowBatteryDialog.dismiss();
}
}
void showLowBatteryWarning() {
- Slog.i(TAG,
+ Log.i(TAG,
((mBatteryLevelTextView == null) ? "showing" : "updating")
+ " low battery warning: level=" + mBatteryLevel
+ " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
@@ -234,7 +234,7 @@
void playLowBatterySound() {
if (DEBUG) {
- Slog.i(TAG, "playing low battery sound. WOMP-WOMP!");
+ Log.i(TAG, "playing low battery sound. WOMP-WOMP!");
}
final ContentResolver cr = mContext.getContentResolver();
@@ -261,7 +261,7 @@
}
void showInvalidChargerDialog() {
- Slog.d(TAG, "showing invalid charger dialog");
+ Log.d(TAG, "showing invalid charger dialog");
dismissLowBatteryWarning();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index fdeead1..f5471e5 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -30,7 +30,6 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
-import android.util.Slog;
import android.view.IWindowManager;
import android.widget.CompoundButton;
import android.widget.ImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
index 122f81e..036bd4f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.UserHandle;
public abstract class CurrentUserTracker extends BroadcastReceiver {
@@ -54,4 +55,8 @@
}
public abstract void onUserSwitched(int newUserId);
+
+ public boolean isCurrentUserOwner() {
+ return mCurrentUserId == UserHandle.USER_OWNER;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java b/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
index 1075a73..3ab2d9b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
@@ -26,7 +26,7 @@
import android.content.IntentFilter;
import android.os.Handler;
import android.os.UserHandle;
-import android.util.Slog;
+import android.util.Log;
import com.android.systemui.SystemUI;
@@ -42,7 +42,7 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)) {
- if (DEBUG) Slog.d(TAG, "showing brightness dialog");
+ if (DEBUG) Log.d(TAG, "showing brightness dialog");
if (mBrightnessDialog == null) {
mBrightnessDialog = new BrightnessDialog(mContext);
@@ -59,7 +59,7 @@
}
} else {
- Slog.w(TAG, "unknown intent: " + intent);
+ Log.w(TAG, "unknown intent: " + intent);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index c7c361c..e0aefca 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -21,7 +21,6 @@
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
index 78226c5..9839fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
@@ -20,7 +20,6 @@
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews.RemoteView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index af72936..c96d9c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -62,7 +62,6 @@
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.Slog;
import android.view.Display;
import android.view.IWindowManager;
import android.view.LayoutInflater;
@@ -168,7 +167,7 @@
@Override
public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) {
if (DEBUG) {
- Slog.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
+ Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
}
final boolean isActivity = pendingIntent.isActivity();
if (isActivity) {
@@ -259,7 +258,7 @@
}
if (DEBUG) {
- Slog.d(TAG, String.format(
+ Log.d(TAG, String.format(
"init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
iconList.size(),
switches[0],
@@ -279,7 +278,7 @@
String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (true) Slog.v(TAG, "userId " + mCurrentUserId + " is in the house");
+ if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
userSwitched(mCurrentUserId);
}
}}, filter);
@@ -295,7 +294,7 @@
final int thisUserId = mCurrentUserId;
final int notificationUserId = n.getUserId();
if (DEBUG && MULTIUSER_DEBUG) {
- Slog.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
+ Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
n, thisUserId, notificationUserId));
}
return notificationUserId == UserHandle.USER_ALL
@@ -348,7 +347,7 @@
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
version = info.targetSdkVersion;
} catch (NameNotFoundException ex) {
- Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+ Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
}
if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
@@ -643,7 +642,7 @@
};
protected void preloadRecentTasksList() {
- if (DEBUG) Slog.d(TAG, "preloading recents");
+ if (DEBUG) Log.d(TAG, "preloading recents");
Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
"com.android.systemui.recent.RecentsPreloadReceiver");
@@ -653,7 +652,7 @@
}
protected void cancelPreloadingRecentTasksList() {
- if (DEBUG) Slog.d(TAG, "cancel preloading recents");
+ if (DEBUG) Log.d(TAG, "cancel preloading recents");
Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
"com.android.systemui.recent.RecentsPreloadReceiver");
@@ -667,11 +666,11 @@
Intent intent;
switch (m.what) {
case MSG_TOGGLE_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "toggle recents panel");
+ if (DEBUG) Log.d(TAG, "toggle recents panel");
toggleRecentsActivity();
break;
case MSG_CLOSE_RECENTS_PANEL:
- if (DEBUG) Slog.d(TAG, "closing recents panel");
+ if (DEBUG) Log.d(TAG, "closing recents panel");
intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
intent.setPackage("com.android.systemui");
mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
@@ -683,13 +682,13 @@
cancelPreloadingRecentTasksList();
break;
case MSG_OPEN_SEARCH_PANEL:
- if (DEBUG) Slog.d(TAG, "opening search panel");
+ if (DEBUG) Log.d(TAG, "opening search panel");
if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
mSearchPanelView.show(true, true);
}
break;
case MSG_CLOSE_SEARCH_PANEL:
- if (DEBUG) Slog.d(TAG, "closing search panel");
+ if (DEBUG) Log.d(TAG, "closing search panel");
if (mSearchPanelView != null && mSearchPanelView.isShowing()) {
mSearchPanelView.show(false, true);
}
@@ -776,7 +775,7 @@
}
catch (RuntimeException e) {
final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
- Slog.e(TAG, "couldn't inflate view for notification " + ident, e);
+ Log.e(TAG, "couldn't inflate view for notification " + ident, e);
return false;
}
@@ -855,7 +854,7 @@
mIntent.send(mContext, 0, overlay);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. Just log the exception message.
- Slog.w(TAG, "Sending contentIntent failed: " + e);
+ Log.w(TAG, "Sending contentIntent failed: " + e);
}
KeyguardManager kgm =
@@ -913,7 +912,7 @@
protected StatusBarNotification removeNotificationViews(IBinder key) {
NotificationData.Entry entry = mNotificationData.remove(key);
if (entry == null) {
- Slog.w(TAG, "removeNotification for unknown key: " + key);
+ Log.w(TAG, "removeNotification for unknown key: " + key);
return null;
}
// Remove the expanded view.
@@ -928,7 +927,7 @@
protected StatusBarIconView addNotificationViews(IBinder key,
StatusBarNotification notification) {
if (DEBUG) {
- Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
+ Log.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
}
// Construct the icon.
final StatusBarIconView iconView = new StatusBarIconView(mContext,
@@ -957,7 +956,7 @@
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
- Slog.d(TAG, "addNotificationViews: added at " + pos);
+ Log.d(TAG, "addNotificationViews: added at " + pos);
}
updateExpansionStates();
updateNotificationIcons();
@@ -970,10 +969,10 @@
mContext.getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
ViewGroup.LayoutParams lp = entry.row.getLayoutParams();
if (entry.expandable() && expand) {
- if (DEBUG) Slog.d(TAG, "setting expanded row height to WRAP_CONTENT");
+ if (DEBUG) Log.d(TAG, "setting expanded row height to WRAP_CONTENT");
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
- if (DEBUG) Slog.d(TAG, "setting collapsed row height to " + rowHeight);
+ if (DEBUG) Log.d(TAG, "setting collapsed row height to " + rowHeight);
lp.height = rowHeight;
}
entry.row.setLayoutParams(lp);
@@ -986,18 +985,18 @@
NotificationData.Entry entry = mNotificationData.get(i);
if (!entry.userLocked()) {
if (i == (N-1)) {
- if (DEBUG) Slog.d(TAG, "expanding top notification at " + i);
+ if (DEBUG) Log.d(TAG, "expanding top notification at " + i);
expandView(entry, true);
} else {
if (!entry.userExpanded()) {
- if (DEBUG) Slog.d(TAG, "collapsing notification at " + i);
+ if (DEBUG) Log.d(TAG, "collapsing notification at " + i);
expandView(entry, false);
} else {
- if (DEBUG) Slog.d(TAG, "ignoring user-modified notification at " + i);
+ if (DEBUG) Log.d(TAG, "ignoring user-modified notification at " + i);
}
}
} else {
- if (DEBUG) Slog.d(TAG, "ignoring notification being held by user at " + i);
+ if (DEBUG) Log.d(TAG, "ignoring notification being held by user at " + i);
}
}
}
@@ -1015,11 +1014,11 @@
}
public void updateNotification(IBinder key, StatusBarNotification notification) {
- if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
+ if (DEBUG) Log.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
if (oldEntry == null) {
- Slog.w(TAG, "updateNotification for unknown key: " + key);
+ Log.w(TAG, "updateNotification for unknown key: " + key);
return;
}
@@ -1032,13 +1031,13 @@
final RemoteViews bigContentView = notification.getNotification().bigContentView;
if (DEBUG) {
- Slog.d(TAG, "old notification: when=" + oldNotification.getNotification().when
+ Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
+ " ongoing=" + oldNotification.isOngoing()
+ " expanded=" + oldEntry.expanded
+ " contentView=" + oldContentView
+ " bigContentView=" + oldBigContentView
+ " rowParent=" + oldEntry.row.getParent());
- Slog.d(TAG, "new notification: when=" + notification.getNotification().when
+ Log.d(TAG, "new notification: when=" + notification.getNotification().when
+ " ongoing=" + oldNotification.isOngoing()
+ " contentView=" + contentView
+ " bigContentView=" + bigContentView);
@@ -1071,7 +1070,7 @@
oldEntry.notification.getNotification().tickerText);
boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
if (contentsUnchanged && bigContentsUnchanged && (orderUnchanged || isTopAnyway)) {
- if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
+ if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
@@ -1102,15 +1101,15 @@
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
- Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
+ Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
} else {
- if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
- if (DEBUG) Slog.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
- if (DEBUG) Slog.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
- if (DEBUG) Slog.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
+ if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
+ if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
+ if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
+ if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
final boolean wasExpanded = oldEntry.userExpanded();
removeNotificationViews(key);
addNotificationViews(key, notification);
@@ -1127,7 +1126,7 @@
// Is this for you?
boolean isForCurrentUser = notificationIsForCurrentUser(notification);
- if (DEBUG) Slog.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+ if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
// Restart the ticker if it's still running
if (updateTicker && isForCurrentUser) {
@@ -1141,11 +1140,11 @@
// See if we need to update the intruder.
if (ENABLE_INTRUDERS && oldNotification == mCurrentlyIntrudingNotification) {
- if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification);
+ if (DEBUG) Log.d(TAG, "updating the current intruder:" + notification);
// XXX: this is a hack for Alarms. The real implementation will need to *update*
// the intruder.
if (notification.getNotification().fullScreenIntent == null) { // TODO(dsandler): consistent logic with add()
- if (DEBUG) Slog.d(TAG, "no longer intrudes!");
+ if (DEBUG) Log.d(TAG, "no longer intrudes!");
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java b/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
index 9e44e71..ce67abe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
@@ -22,7 +22,6 @@
import android.content.SharedPreferences;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.Slog;
import com.android.systemui.statusbar.policy.Prefs;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
index 0f894a1..378061f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -27,7 +27,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
-import android.util.Slog;
+import android.util.Log;
import android.view.MotionEvent;
/**
@@ -46,7 +46,7 @@
public MotionEvent event;
public MotionEventRecord(long when, MotionEvent event) {
this.time = when;
- this.event = event.copy();
+ this.event = MotionEvent.obtain(event);
}
String actionName(int action) {
switch (action) {
@@ -101,7 +101,7 @@
mDownTime = ev.getDownTime();
} else {
if (mDownTime != ev.getDownTime()) {
- Slog.w(TAG, "Assertion failure in GestureRecorder: event downTime ("
+ Log.w(TAG, "Assertion failure in GestureRecorder: event downTime ("
+ev.getDownTime()+") does not match gesture downTime ("+mDownTime+")");
}
}
@@ -237,10 +237,10 @@
mGestures.add(mCurrentGesture);
}
if (DEBUG) {
- Slog.v(TAG, String.format("Wrote %d complete gestures to %s", mLastSaveLen, mLogfile));
+ Log.v(TAG, String.format("Wrote %d complete gestures to %s", mLastSaveLen, mLogfile));
}
} catch (IOException e) {
- Slog.e(TAG, String.format("Couldn't write gestures to %s", mLogfile), e);
+ Log.e(TAG, String.format("Couldn't write gestures to %s", mLogfile), e);
mLastSaveLen = -1;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 46916f7..de7f189 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -18,7 +18,7 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
@@ -64,7 +64,7 @@
}
public void setNetworkController(NetworkController nc) {
- if (DEBUG) Slog.d(TAG, "NetworkController=" + nc);
+ if (DEBUG) Log.d(TAG, "NetworkController=" + nc);
mNC = nc;
}
@@ -185,7 +185,7 @@
mWifiGroup.setVisibility(View.GONE);
}
- if (DEBUG) Slog.d(TAG,
+ if (DEBUG) Log.d(TAG,
String.format("wifi: %s sig=%d act=%d",
(mWifiVisible ? "VISIBLE" : "GONE"),
mWifiStrengthId, mWifiActivityId));
@@ -214,7 +214,7 @@
mSpacer.setVisibility(View.GONE);
}
- if (DEBUG) Slog.d(TAG,
+ if (DEBUG) Log.d(TAG,
String.format("mobile: %s sig=%d act=%d typ=%d",
(mMobileVisible ? "VISIBLE" : "GONE"),
mMobileStrengthId, mMobileActivityId, mMobileTypeId));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 39d56a4..54c5e2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -27,7 +27,6 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Slog;
import android.util.Log;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
@@ -151,7 +150,7 @@
private boolean updateDrawable(boolean withClear) {
Drawable drawable = getIcon(mIcon);
if (drawable == null) {
- Slog.w(TAG, "No icon for slot " + mSlot);
+ Log.w(TAG, "No icon for slot " + mSlot);
return false;
}
if (withClear) {
@@ -185,7 +184,7 @@
r = context.getPackageManager()
.getResourcesForApplicationAsUser(icon.iconPackage, userId);
} catch (PackageManager.NameNotFoundException ex) {
- Slog.e(TAG, "Icon package not found: " + icon.iconPackage);
+ Log.e(TAG, "Icon package not found: " + icon.iconPackage);
return null;
}
} else {
@@ -199,7 +198,7 @@
try {
return r.getDrawable(icon.iconId);
} catch (RuntimeException e) {
- Slog.w(TAG, "Icon not found in "
+ Log.w(TAG, "Icon not found in "
+ (icon.iconPackage != null ? icon.iconId : "<system>")
+ ": " + Integer.toHexString(icon.iconId));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
index 66494e4..5fa8126 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
@@ -22,7 +22,7 @@
import android.content.IntentFilter;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.widget.TextView;
@@ -90,7 +90,7 @@
void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
if (false) {
- Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ " showPlmn=" + showPlmn + " plmn=" + plmn);
}
final String str;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index 0640282..eae4b7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index fd36da6a..f5867ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -29,7 +29,7 @@
import android.os.Message;
import android.os.ServiceManager;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.animation.AccelerateInterpolator;
import android.view.Display;
import android.view.MotionEvent;
@@ -95,7 +95,7 @@
final int vh = mCurrentView.getHeight();
if (h != vh || w != vw) {
- Slog.w(TAG, String.format(
+ Log.w(TAG, String.format(
"*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
how, w, h, vw, vh));
if (WORKAROUND_INVALID_LAYOUT) {
@@ -318,7 +318,7 @@
mLowProfile = lightsOut;
- if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
+ if (DEBUG) Log.d(TAG, "setting lights " + (lightsOut?"out":"on"));
final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
final View lowLights = mCurrentView.findViewById(R.id.lights_out);
@@ -361,7 +361,7 @@
if (hide == mHidden) return;
mHidden = hide;
- Slog.d(TAG,
+ Log.d(TAG,
(hide ? "HIDING" : "SHOWING") + " navigation bar");
// bring up the lights no matter what
@@ -402,7 +402,7 @@
setMenuVisibility(mShowMenu, true /* force */);
if (DEBUG) {
- Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
+ Log.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
}
setNavigationIconHints(mNavigationIconHints, true);
@@ -416,13 +416,13 @@
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (DEBUG) Slog.d(TAG, String.format(
+ if (DEBUG) Log.d(TAG, String.format(
"onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
final boolean newVertical = w > 0 && h > w;
if (newVertical != mVertical) {
mVertical = newVertical;
- //Slog.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
+ //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
reorient();
}
@@ -433,7 +433,7 @@
/*
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
- if (DEBUG) Slog.d(TAG, String.format(
+ if (DEBUG) Log.d(TAG, String.format(
"onLayout: %s (%d,%d,%d,%d)",
changed?"changed":"notchanged", left, top, right, bottom));
super.onLayout(changed, left, top, right, bottom);
@@ -443,7 +443,7 @@
// fails, any touch on the display will fix the layout.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (DEBUG) Slog.d(TAG, "onInterceptTouchEvent: " + ev.toString());
+ if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
postCheckForInvalidLayout("touch");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f33dc20..6be6d4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,7 +22,6 @@
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.EventLog;
-import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 565a3f2..91e1aa0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -20,7 +20,7 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -30,7 +30,7 @@
public static final String TAG = PanelBar.class.getSimpleName();
public static final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
- Slog.v(TAG, String.format(fmt, args));
+ Log.v(TAG, String.format(fmt, args));
}
public static final int STATE_CLOSED = 0;
@@ -66,7 +66,7 @@
public void setPanelHolder(PanelHolder ph) {
if (ph == null) {
- Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
+ Log.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
return;
}
ph.setBar(this);
@@ -98,7 +98,7 @@
// Allow subclasses to implement enable/disable semantics
if (!panelsEnabled()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- Slog.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
+ Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
}
return false;
@@ -109,7 +109,7 @@
final PanelView panel = selectPanelForTouch(event);
if (panel == null) {
// panel is not there, so we'll eat the gesture
- Slog.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
+ Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
mTouchingPanel = null;
return true;
@@ -119,7 +119,7 @@
(enabled ? "" : " (disabled)"));
if (!enabled) {
// panel is disabled, so we'll eat the gesture
- Slog.v(TAG, String.format(
+ Log.v(TAG, String.format(
"onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
panel, (int) event.getX(), (int) event.getY()));
mTouchingPanel = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e351429..70cb94a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -27,7 +27,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -42,7 +42,7 @@
public final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
- Slog.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
+ Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
}
public static final boolean BRAKES = false;
@@ -112,7 +112,7 @@
}
public void computeCurrentVelocity(long timebase) {
if (FlingTracker.DEBUG) {
- Slog.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
+ Log.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
}
mVX = mVY = 0;
MotionEventCopy last = null;
@@ -127,7 +127,7 @@
final float dx = (event.x - last.x);
final float dy = (event.y - last.y);
if (FlingTracker.DEBUG) {
- Slog.v("FlingTracker", String.format(" [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
+ Log.v("FlingTracker", String.format(" [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
i,
dx, dy, dt,
(dx/dt),
@@ -147,7 +147,7 @@
mVY /= totalweight;
} else {
if (DEBUG_NAN) {
- Slog.v("FlingTracker", "computeCurrentVelocity warning: totalweight=0",
+ Log.v("FlingTracker", "computeCurrentVelocity warning: totalweight=0",
new Throwable());
}
// so as not to contaminate the velocities with NaN
@@ -155,13 +155,13 @@
}
if (FlingTracker.DEBUG) {
- Slog.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
+ Log.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
}
}
public float getXVelocity() {
if (Float.isNaN(mVX)) {
if (DEBUG_NAN) {
- Slog.v("FlingTracker", "warning: vx=NaN");
+ Log.v("FlingTracker", "warning: vx=NaN");
}
mVX = 0;
}
@@ -170,7 +170,7 @@
public float getYVelocity() {
if (Float.isNaN(mVY)) {
if (DEBUG_NAN) {
- Slog.v("FlingTracker", "warning: vx=NaN");
+ Log.v("FlingTracker", "warning: vx=NaN");
}
mVY = 0;
}
@@ -307,7 +307,7 @@
post(mStopAnimator);
}
} else {
- Slog.v(TAG, "animationTick called with dtms=" + dtms + "; nothing to do (h="
+ Log.v(TAG, "animationTick called with dtms=" + dtms + "; nothing to do (h="
+ mExpandedHeight + " v=" + mVel + ")");
}
}
@@ -547,7 +547,7 @@
if (Float.isNaN(h)) {
// If a NaN gets in here, it will freeze the Animators.
if (DEBUG_NAN) {
- Slog.v(TAG, "setExpandedHeightInternal: warning: h=NaN, using 0 instead",
+ Log.v(TAG, "setExpandedHeightInternal: warning: h=NaN, using 0 instead",
new Throwable());
}
h = 0;
@@ -586,7 +586,7 @@
if (Float.isNaN(frac)) {
// If a NaN gets in here, it will freeze the Animators.
if (DEBUG_NAN) {
- Slog.v(TAG, "setExpandedFraction: frac=NaN, using 0 instead",
+ Log.v(TAG, "setExpandedFraction: frac=NaN, using 0 instead",
new Throwable());
}
frac = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 978b36b..97c7b98a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -55,7 +55,6 @@
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
-import android.util.Slog;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -280,7 +279,7 @@
public void onAnimationEnd(Animator animation) {
// double-check to avoid races
if (mStatusBarContents.getAlpha() == 0) {
- if (DEBUG) Slog.d(TAG, "makeIconsInvisible");
+ if (DEBUG) Log.d(TAG, "makeIconsInvisible");
mStatusBarContents.setVisibility(View.INVISIBLE);
}
}
@@ -296,7 +295,7 @@
Settings.Secure.USER_SETUP_COMPLETE,
0 /*default */,
mCurrentUserId);
- if (MULTIUSER_DEBUG) Slog.d(TAG, String.format("User setup changed: " +
+ if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " +
"selfChange=%s userSetup=%s mUserSetup=%s",
selfChange, userSetup, mUserSetup));
if (mSettingsButton != null && mHasFlipSettings) {
@@ -439,7 +438,7 @@
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
- if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
+ if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
mNavigationBarView =
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
@@ -566,7 +565,7 @@
mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
mShowCarrierInPanel = (mCarrierLabel != null);
- if (DEBUG) Slog.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
+ if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
if (mShowCarrierInPanel) {
mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
@@ -818,7 +817,7 @@
// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
- if (DEBUG) Slog.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
+ if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
if (mNavigationBarView == null) return;
prepareNavigationBarView();
@@ -897,7 +896,7 @@
}
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " icon=" + icon);
StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
view.set(icon);
@@ -906,19 +905,19 @@
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ if (SPEW) Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " old=" + old + " icon=" + icon);
StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
view.set(icon);
}
public void removeIcon(String slot, int index, int viewIndex) {
- if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
+ if (SPEW) Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
mStatusIcons.removeViewAt(viewIndex);
}
public void addNotification(IBinder key, StatusBarNotification notification) {
- if (DEBUG) Slog.d(TAG, "addNotification score=" + notification.getScore());
+ if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
StatusBarIconView iconView = addNotificationViews(key, notification);
if (iconView == null) return;
@@ -926,7 +925,7 @@
try {
immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
if (DEBUG) {
- Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
+ Log.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
}
} catch (RemoteException ex) {
}
@@ -936,12 +935,12 @@
if (ENABLE_INTRUDERS && (
// TODO(dsandler): Only if the screen is on
notification.notification.intruderView != null)) {
- Slog.d(TAG, "Presenting high-priority notification");
+ Log.d(TAG, "Presenting high-priority notification");
// special new transient ticker mode
// 1. Populate mIntruderAlertView
if (notification.notification.intruderView == null) {
- Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null");
+ Log.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null");
return;
}
@@ -973,7 +972,7 @@
awakenDreams();
// not immersive & a full-screen alert should be shown
- if (DEBUG) Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+ if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
try {
notification.getNotification().fullScreenIntent.send();
} catch (PendingIntent.CanceledException e) {
@@ -994,7 +993,7 @@
public void removeNotification(IBinder key) {
StatusBarNotification old = removeNotificationViews(key);
- if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old);
+ if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
if (old != null) {
// Cancel the ticker if it's still running
@@ -1099,7 +1098,7 @@
int N = mNotificationData.size();
if (DEBUG) {
- Slog.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + mNotificationIcons);
+ Log.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + mNotificationIcons);
}
ArrayList<View> toShow = new ArrayList<View>();
@@ -1139,7 +1138,7 @@
// The idea here is to only show the carrier label when there is enough room to see it,
// i.e. when there aren't enough notifications to fill the panel.
if (DEBUG) {
- Slog.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
+ Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
mPile.getHeight(), mScrollView.getHeight(), mCarrierLabelHeight));
}
@@ -1152,7 +1151,7 @@
if (force || mCarrierLabelVisible != makeVisible) {
mCarrierLabelVisible = makeVisible;
if (DEBUG) {
- Slog.d(TAG, "making carrier label " + (makeVisible?"visible":"invisible"));
+ Log.d(TAG, "making carrier label " + (makeVisible?"visible":"invisible"));
}
mCarrierLabel.animate().cancel();
if (makeVisible) {
@@ -1183,7 +1182,7 @@
final boolean clearable = any && mNotificationData.hasClearableItems();
if (DEBUG) {
- Slog.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size()
+ Log.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size()
+ " any=" + any + " clearable=" + clearable);
}
@@ -1260,7 +1259,7 @@
mDisabled = state;
if (DEBUG) {
- Slog.d(TAG, String.format("disable: 0x%08x -> 0x%08x (diff: 0x%08x)",
+ Log.d(TAG, String.format("disable: 0x%08x -> 0x%08x (diff: 0x%08x)",
old, state, diff));
}
@@ -1287,7 +1286,7 @@
flagdbg.append(((state & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search");
flagdbg.append(((diff & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " ");
flagdbg.append(">");
- Slog.d(TAG, flagdbg.toString());
+ Log.d(TAG, flagdbg.toString());
if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
mSystemIconArea.animate().cancel();
@@ -1410,7 +1409,7 @@
};
void makeExpandedVisible(boolean revealAfterDraw) {
- if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
+ if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
if (mExpandedVisible) {
return;
}
@@ -1449,7 +1448,7 @@
public void animateCollapsePanels(int flags) {
if (SPEW) {
- Slog.d(TAG, "animateCollapse():"
+ Log.d(TAG, "animateCollapse():"
+ " mExpandedVisible=" + mExpandedVisible
+ " flags=" + flags);
}
@@ -1517,7 +1516,7 @@
@Override
public void animateExpandNotificationsPanel() {
- if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
+ if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return ;
}
@@ -1572,7 +1571,7 @@
@Override
public void animateExpandSettingsPanel() {
- if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
+ if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return;
}
@@ -1671,7 +1670,7 @@
}
void makeExpandedInvisible() {
- if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+ if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+ " mExpandedVisible=" + mExpandedVisible);
if (!mExpandedVisible) {
@@ -1842,11 +1841,11 @@
}
if (SPEW) {
- Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
+ Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
+ mDisabled + " mTracking=" + mTracking);
} else if (CHATTY) {
if (event.getAction() != MotionEvent.ACTION_MOVE) {
- Slog.d(TAG, String.format(
+ Log.d(TAG, String.format(
"panel: %s at (%f, %f) mDisabled=0x%08x",
MotionEvent.actionToString(event.getAction()),
event.getRawX(), event.getRawY(), mDisabled));
@@ -1896,7 +1895,7 @@
final int oldVal = mSystemUiVisibility;
final int newVal = (oldVal&~mask) | (vis&mask);
final int diff = newVal ^ oldVal;
- if (DEBUG) Slog.d(TAG, String.format(
+ if (DEBUG) Log.d(TAG, String.format(
"setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s",
Integer.toHexString(vis), Integer.toHexString(mask),
Integer.toHexString(oldVal), Integer.toHexString(newVal),
@@ -1959,7 +1958,7 @@
}
private void setHideybarConfirmationVisible(boolean visible) {
- if (DEBUG) Slog.d(TAG, "setHideybarConfirmationVisible " + visible);
+ if (DEBUG) Log.d(TAG, "setHideybarConfirmationVisible " + visible);
if (visible && mHideybarConfirmation == null && !mHideybarConfirmationDismissed) {
// create the confirmation toast bar with the correct message for this config
float widthDp = mCurrentDisplaySize.x /
@@ -2016,7 +2015,7 @@
private void setTransparent(View view, boolean transparent) {
float alpha = transparent ? TRANSPARENT_ALPHA : 1;
- if (DEBUG) Slog.d(TAG, "Setting " + (view == mStatusBarView ? "status bar" :
+ if (DEBUG) Log.d(TAG, "Setting " + (view == mStatusBarView ? "status bar" :
view == mNavigationBarView ? "navigation bar" : "view") + " alpha to " + alpha);
view.setAlpha(alpha);
}
@@ -2084,7 +2083,7 @@
public void topAppWindowChanged(boolean showMenu) {
if (DEBUG) {
- Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
+ Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
}
if (mNavigationBarView != null) {
mNavigationBarView.setMenuVisibility(showMenu);
@@ -2247,7 +2246,7 @@
mHandler.post(new Runnable() {
public void run() {
mStatusBarView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
+ Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
+ ") " + mStatusBarView.getWidth() + "x"
+ getStatusBarHeight());
mStatusBarView.debug();
@@ -2319,7 +2318,7 @@
@Override
public void updateExpandedViewPos(int thingy) {
- if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
+ if (DEBUG) Log.v(TAG, "updateExpandedViewPos");
// on larger devices, the notification panel is propped open a bit
mNotificationPanel.setMinimumHeight(
@@ -2387,7 +2386,7 @@
@Override
public void run() {
if (DEBUG) {
- Slog.v(TAG, "running post-collapse cleanup");
+ Log.v(TAG, "running post-collapse cleanup");
}
try {
mPile.setViewRemoval(true);
@@ -2465,7 +2464,7 @@
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
- if (DEBUG) Slog.v(TAG, "onReceive: " + intent);
+ if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
@@ -2484,7 +2483,7 @@
}
else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
if (DEBUG) {
- Slog.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
+ Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
}
mDisplay.getSize(mCurrentDisplaySize);
@@ -2521,7 +2520,7 @@
private void setIntruderAlertVisibility(boolean vis) {
if (!ENABLE_INTRUDERS) return;
if (DEBUG) {
- Slog.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window");
+ Log.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window");
}
mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
}
@@ -2572,7 +2571,7 @@
R.dimen.status_bar_icon_padding);
if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
-// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
+// Log.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
mIconHPadding = newIconHPadding;
mIconSize = newIconSize;
//reloadAllNotificationIcons(); // reload the tray
@@ -2617,7 +2616,7 @@
mNotificationPanelMinHeightFrac = 0f;
}
- if (false) Slog.v(TAG, "updateResources");
+ if (false) Log.v(TAG, "updateResources");
}
//
@@ -2638,7 +2637,7 @@
public void run() {
vibrate();
SystemClock.sleep(250);
- Slog.d(TAG, "startTracing");
+ Log.d(TAG, "startTracing");
android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
mHandler.postDelayed(mStopTracing, 10000);
}
@@ -2647,7 +2646,7 @@
Runnable mStopTracing = new Runnable() {
public void run() {
android.os.Debug.stopMethodTracing();
- Slog.d(TAG, "stopTracing");
+ Log.d(TAG, "stopTracing");
vibrate();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 9b8bd22..80734ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -36,7 +36,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
-import android.util.Slog;
+import android.util.Log;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCardConstants;
@@ -284,17 +284,17 @@
final String action = intent.getAction();
final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
- if (false) Slog.v(TAG, "updateTTY: enabled: " + enabled);
+ if (false) Log.v(TAG, "updateTTY: enabled: " + enabled);
if (enabled) {
// TTY is on
- if (false) Slog.v(TAG, "updateTTY: set TTY on");
+ if (false) Log.v(TAG, "updateTTY: set TTY on");
mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0,
mContext.getString(R.string.accessibility_tty_enabled));
mService.setIconVisibility("tty", true);
} else {
// TTY is off
- if (false) Slog.v(TAG, "updateTTY: set TTY off");
+ if (false) Log.v(TAG, "updateTTY: set TTY off");
mService.setIconVisibility("tty", false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index de9f750..2a65381 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -23,7 +23,7 @@
import android.content.res.Resources.NotFoundException;
import android.util.AttributeSet;
import android.util.EventLog;
-import android.util.Slog;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -128,7 +128,7 @@
float region = (w * mSettingsPanelDragzoneFrac);
if (DEBUG) {
- Slog.v(TAG, String.format(
+ Log.v(TAG, String.format(
"w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
}
@@ -152,7 +152,7 @@
// which is kind of tricky to determine
mShouldFade = (mFadingPanel == null || mFadingPanel.isFullyExpanded());
if (DEBUG) {
- Slog.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
+ Log.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
}
mFadingPanel = panel;
}
@@ -202,7 +202,7 @@
super.panelExpansionChanged(panel, frac);
if (DEBUG) {
- Slog.v(TAG, "panelExpansionChanged: f=" + frac);
+ Log.v(TAG, "panelExpansionChanged: f=" + frac);
}
if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index cdfd52e..b0aca16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -580,7 +580,7 @@
} catch (SettingNotFoundException e) {
}
- mBugreportState.enabled = enabled;
+ mBugreportState.enabled = enabled && mUserTracker.isCurrentUserOwner();
mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index f3f6a80..b1ccd00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -33,7 +33,6 @@
import java.util.ArrayList;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.util.CharSequences;
import com.android.systemui.R;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -192,7 +191,7 @@
if (n.getPackageName().equals(seg.notification.getPackageName())
&& n.getNotification().icon == seg.notification.getNotification().icon
&& n.getNotification().iconLevel == seg.notification.getNotification().iconLevel
- && CharSequences.equals(seg.notification.getNotification().tickerText,
+ && charSequencesEqual(seg.notification.getNotification().tickerText,
n.getNotification().tickerText)) {
return;
}
@@ -232,6 +231,20 @@
}
}
+ private static boolean charSequencesEqual(CharSequence a, CharSequence b) {
+ if (a.length() != b.length()) {
+ return false;
+ }
+
+ int length = a.length();
+ for (int i = 0; i < length; i++) {
+ if (a.charAt(i) != b.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public void removeEntry(StatusBarNotification n) {
for (int i=mSegments.size()-1; i>=0; i--) {
Segment seg = mSegments.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
index d2ed5ff..f3cf65c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index 3c8276d..71a7aa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -26,7 +26,6 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
-import android.util.Slog;
import android.widget.CompoundButton;
public class AirplaneModeController extends BroadcastReceiver
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 716341f..0f56ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -24,7 +24,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
-import android.util.Slog;
import android.widget.ImageView;
import android.widget.TextView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index bff6cda..91a1a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -34,7 +34,6 @@
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.widget.TextView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
index 2d951c2..3083e8b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
@@ -21,7 +21,7 @@
import android.content.res.TypedArray;
import android.os.RemoteException;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -55,7 +55,7 @@
}
final boolean vis = (mode != ActivityManager.COMPAT_MODE_NEVER
&& mode != ActivityManager.COMPAT_MODE_ALWAYS);
- if (DEBUG) Slog.d(TAG, "compat mode is " + mode + "; icon will " + (vis ? "show" : "hide"));
+ if (DEBUG) Log.d(TAG, "compat mode is " + mode + "; icon will " + (vis ? "show" : "hide"));
setVisibility(vis ? View.VISIBLE : View.GONE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 6eb88be..dca5e41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -22,7 +22,7 @@
import android.graphics.Canvas;
import android.os.SystemClock;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -75,7 +75,7 @@
mVertical = (index == VERTICAL);
if (DEBUG)
- Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ Log.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ (mVertical ? " vertical" : " horizontal"));
setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
@@ -106,7 +106,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
if (DEBUG) {
- Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
+ Log.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
}
final int action = event.getAction();
@@ -114,12 +114,12 @@
poke(event);
} else if (action == MotionEvent.ACTION_DOWN) {
if (DEBUG) {
- Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
+ Log.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
}
int size = (int) getSize(event.getEventTime());
if ((mVertical && event.getX() < size) || event.getY() < size) {
if (CHATTY) {
- Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
+ Log.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
}
if (mShouldFlash) {
post(mDebugFlash);
@@ -134,7 +134,7 @@
public void poke(MotionEvent event) {
mLastPokeTime = event.getEventTime();
if (DEBUG)
- Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
+ Log.v(TAG, "poked! size=" + getSize(mLastPokeTime));
if (mShouldFlash) postInvalidate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
index 94c8aa5..d45a94f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
@@ -22,7 +22,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
import android.view.IWindowManager;
import android.widget.CompoundButton;
@@ -52,7 +52,7 @@
// The checkbox is ON for notifications coming in and OFF for Do not disturb, so we
// don't have a double negative.
public void onCheckedChanged(CompoundButton view, boolean checked) {
- //Slog.d(TAG, "onCheckedChanged checked=" + checked + " mDoNotDisturb=" + mDoNotDisturb);
+ //Log.d(TAG, "onCheckedChanged checked=" + checked + " mDoNotDisturb=" + mDoNotDisturb);
final boolean value = !checked;
if (value != mDoNotDisturb) {
SharedPreferences.Editor editor = Prefs.edit(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
index 47e758c..4de4241 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
@@ -25,7 +25,6 @@
import android.os.SystemClock;
import android.os.ServiceManager;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.HapticFeedbackConstants;
import android.view.IWindowManager;
import android.view.InputDevice;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
index 0e8095c..3751399 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
@@ -20,7 +20,6 @@
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Rect;
-import android.util.Slog;
public class FixedSizeDrawable extends Drawable {
Drawable mDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
index ee5c863..9b96384 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
@@ -28,7 +28,6 @@
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@@ -102,7 +101,7 @@
}
public void onChildDismissed(View v) {
- Slog.v(TAG, "User swiped intruder to dismiss");
+ Log.v(TAG, "User swiped intruder to dismiss");
mBar.dismissIntruder();
}
@@ -134,7 +133,7 @@
public void onDraw(android.graphics.Canvas c) {
super.onDraw(c);
if (DEBUG) {
- //Slog.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
+ //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
// + getMeasuredHeight() + "px");
c.save();
c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
@@ -146,7 +145,7 @@
public void applyIntruderContent(RemoteViews intruderView, OnClickListener listener) {
if (DEBUG) {
- Slog.v(TAG, "applyIntruderContent: view=" + intruderView + " listener=" + listener);
+ Log.v(TAG, "applyIntruderContent: view=" + intruderView + " listener=" + listener);
}
mIntruderRemoteViews = intruderView;
mOnClickListener = listener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 82d6a99..db0e4c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -61,7 +61,7 @@
Runnable mCheckLongPress = new Runnable() {
public void run() {
if (isPressed()) {
- // Slog.d("KeyButtonView", "longpressed: " + this);
+ // Log.d("KeyButtonView", "longpressed: " + this);
if (mCode != 0) {
sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
@@ -213,7 +213,7 @@
switch (action) {
case MotionEvent.ACTION_DOWN:
- //Slog.d("KeyButtonView", "press");
+ //Log.d("KeyButtonView", "press");
mDownTime = SystemClock.uptimeMillis();
setPressed(true);
if (mCode != 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 3619587..a19b52a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -37,7 +37,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
@@ -90,6 +90,7 @@
boolean mShowPhoneRSSIForData = false;
boolean mShowAtLeastThreeGees = false;
boolean mAlwaysShowCdmaRssi = false;
+ boolean mShow4GforLTE = false;
String mContentDescriptionPhoneSignal;
String mContentDescriptionWifi;
@@ -199,6 +200,7 @@
mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
+ mShow4GforLTE = res.getBoolean(R.bool.config_show4GForLTE);
mAlwaysShowCdmaRssi = res.getBoolean(
com.android.internal.R.bool.config_alwaysUseCdmaRssi);
@@ -429,7 +431,7 @@
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
if (DEBUG) {
- Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
+ Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
}
mSignalStrength = signalStrength;
@@ -440,7 +442,7 @@
@Override
public void onServiceStateChanged(ServiceState state) {
if (DEBUG) {
- Slog.d(TAG, "onServiceStateChanged state=" + state.getState());
+ Log.d(TAG, "onServiceStateChanged state=" + state.getState());
}
mServiceState = state;
updateTelephonySignalStrength();
@@ -452,7 +454,7 @@
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if (DEBUG) {
- Slog.d(TAG, "onCallStateChanged state=" + state);
+ Log.d(TAG, "onCallStateChanged state=" + state);
}
// In cdma, if a voice call is made, RSSI should switch to 1x.
if (isCdma()) {
@@ -464,7 +466,7 @@
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
if (DEBUG) {
- Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
+ Log.d(TAG, "onDataConnectionStateChanged: state=" + state
+ " type=" + networkType);
}
mDataState = state;
@@ -477,7 +479,7 @@
@Override
public void onDataActivity(int direction) {
if (DEBUG) {
- Slog.d(TAG, "onDataActivity: direction=" + direction);
+ Log.d(TAG, "onDataActivity: direction=" + direction);
}
mDataActivity = direction;
updateDataIcon();
@@ -539,13 +541,13 @@
private final void updateTelephonySignalStrength() {
if (!hasService()) {
- if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: !hasService()");
+ if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: !hasService()");
mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
mDataSignalIconId = R.drawable.stat_sys_signal_null;
} else {
if (mSignalStrength == null) {
- if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
+ if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
mDataSignalIconId = R.drawable.stat_sys_signal_null;
@@ -556,7 +558,7 @@
int[] iconList;
if (isCdma() && mAlwaysShowCdmaRssi) {
mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel();
- if(DEBUG) Slog.d(TAG, "mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
+ if(DEBUG) Log.d(TAG, "mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
+ " set to cdmaLevel=" + mSignalStrength.getCdmaLevel()
+ " instead of level=" + mSignalStrength.getLevel());
} else {
@@ -678,11 +680,19 @@
R.string.accessibility_data_connection_3g);
break;
case TelephonyManager.NETWORK_TYPE_LTE:
- mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
- mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
- mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_4g);
+ if (mShow4GforLTE) {
+ mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+ mDataTypeIconId = R.drawable.stat_sys_data_connected_4g;
+ mQSDataTypeIconId = R.drawable.ic_qs_signal_4g;
+ mContentDescriptionDataType = mContext.getString(
+ R.string.accessibility_data_connection_4g);
+ } else {
+ mDataIconList = TelephonyIcons.DATA_LTE[mInetCondition];
+ mDataTypeIconId = R.drawable.stat_sys_data_connected_lte;
+ mQSDataTypeIconId = R.drawable.ic_qs_signal_lte;
+ mContentDescriptionDataType = mContext.getString(
+ R.string.accessibility_data_connection_lte);
+ }
break;
default:
if (!mShowAtLeastThreeGees) {
@@ -798,7 +808,7 @@
void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
if (false) {
- Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ " showPlmn=" + showPlmn + " plmn=" + plmn);
}
StringBuilder str = new StringBuilder();
@@ -832,7 +842,7 @@
mWifiChannel.sendMessage(Message.obtain(this,
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
} else {
- Slog.e(TAG, "Failed to connect to wifi");
+ Log.e(TAG, "Failed to connect to wifi");
}
break;
case WifiManager.DATA_ACTIVITY_NOTIFICATION:
@@ -964,7 +974,7 @@
private void updateConnectivity(Intent intent) {
if (CHATTY) {
- Slog.d(TAG, "updateConnectivity: intent=" + intent);
+ Log.d(TAG, "updateConnectivity: intent=" + intent);
}
final ConnectivityManager connManager = (ConnectivityManager) mContext
@@ -984,8 +994,8 @@
int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
if (CHATTY) {
- Slog.d(TAG, "updateConnectivity: networkInfo=" + info);
- Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
+ Log.d(TAG, "updateConnectivity: networkInfo=" + info);
+ Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
}
mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
@@ -1173,7 +1183,7 @@
}
if (DEBUG) {
- Slog.d(TAG, "refreshViews connected={"
+ Log.d(TAG, "refreshViews connected={"
+ (mWifiConnected?" wifi":"")
+ (mDataConnected?" data":"")
+ " } level="
@@ -1312,7 +1322,7 @@
// the data direction overlay
if (mLastDataDirectionOverlayIconId != combinedActivityIconId) {
if (DEBUG) {
- Slog.d(TAG, "changing data overlay icon id to " + combinedActivityIconId);
+ Log.d(TAG, "changing data overlay icon id to " + combinedActivityIconId);
}
mLastDataDirectionOverlayIconId = combinedActivityIconId;
N = mDataDirectionOverlayIconViews.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 89eed1b..9bf1c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -27,7 +27,6 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -87,11 +86,11 @@
setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
- Slog.d(TAG, "view added: " + child + "; new count: " + getChildCount());
+ Log.d(TAG, "view added: " + child + "; new count: " + getChildCount());
}
@Override
public void onChildViewRemoved(View parent, View child) {
- Slog.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
+ Log.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
}
});
@@ -167,7 +166,7 @@
}
public void onChildDismissed(View v) {
- if (DEBUG) Slog.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
+ if (DEBUG) Log.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
final View veto = v.findViewById(R.id.veto);
if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
veto.performClick();
@@ -231,7 +230,7 @@
* get removed properly.
*/
public void setViewRemoval(boolean removeViews) {
- if (DEBUG) Slog.v(TAG, "setViewRemoval: " + removeViews);
+ if (DEBUG) Log.v(TAG, "setViewRemoval: " + removeViews);
mRemoveViews = removeViews;
}
@@ -266,7 +265,7 @@
super.onDraw(c);
if (DEBUG) logLayoutTransition();
if (DEBUG) {
- //Slog.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
+ //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
// + getMeasuredHeight() + "px");
c.save();
c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 3b953a0..4b2c65e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -136,6 +136,17 @@
R.drawable.stat_sys_data_fully_connected_4g }
};
+ // LTE branded "LTE"
+ static final int[][] DATA_LTE = {
+ { R.drawable.stat_sys_data_connected_lte,
+ R.drawable.stat_sys_data_connected_lte,
+ R.drawable.stat_sys_data_connected_lte,
+ R.drawable.stat_sys_data_connected_lte },
+ { R.drawable.stat_sys_data_fully_connected_lte,
+ R.drawable.stat_sys_data_fully_connected_lte,
+ R.drawable.stat_sys_data_fully_connected_lte,
+ R.drawable.stat_sys_data_fully_connected_lte }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
index 70f9ac8..3e138d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
@@ -23,7 +23,6 @@
import android.os.Vibrator;
import android.media.AudioManager;
import android.provider.Settings;
-import android.util.Slog;
import android.view.IWindowManager;
import android.widget.CompoundButton;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
index 8c4ae19..080cbd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
@@ -21,7 +21,6 @@
import android.content.res.TypedArray;
import android.os.RemoteException;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
index 3d6c1a2..4f3c4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
@@ -20,7 +20,6 @@
import android.content.res.Resources;
import android.os.Handler;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
index 9ecb2e4..51980dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
@@ -26,7 +26,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 87fc6fc..585c067 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -23,7 +23,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -224,7 +224,7 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
- if (DEBUG) Slog.d(TAG, String.format("PANEL: onLayout: (%d, %d, %d, %d)", l, t, r, b));
+ if (DEBUG) Log.d(TAG, String.format("PANEL: onLayout: (%d, %d, %d, %d)", l, t, r, b));
}
@Override
@@ -232,7 +232,7 @@
super.onSizeChanged(w, h, oldw, oldh);
if (DEBUG) {
- Slog.d(TAG, String.format("PANEL: onSizeChanged: (%d -> %d, %d -> %d)",
+ Log.d(TAG, String.format("PANEL: onSizeChanged: (%d -> %d, %d -> %d)",
oldw, w, oldh, h));
}
}
@@ -390,7 +390,7 @@
}
void startAnimation(boolean appearing) {
- if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+ if (DEBUG) Log.d(TAG, "startAnimation(appearing=" + appearing + ")");
createAnimation(appearing);
mContentAnim.start();
@@ -402,11 +402,11 @@
}
public void onAnimationCancel(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationCancel");
+ if (DEBUG) Log.d(TAG, "onAnimationCancel");
}
public void onAnimationEnd(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+ if (DEBUG) Log.d(TAG, "onAnimationEnd");
if (! mVisible) {
setVisibility(View.GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 2924cc9..48486b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -28,7 +28,7 @@
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.DragEvent;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -96,21 +96,21 @@
@Override
public boolean onDragEvent(DragEvent event) {
- if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
+ if (DEBUG) Log.d(TAG, "onDragEvent: " + event);
switch (event.getAction()) {
// We want to appear whenever a potential drag takes off from anywhere in the UI.
case DragEvent.ACTION_DRAG_STARTED:
show(true);
break;
case DragEvent.ACTION_DRAG_ENTERED:
- if (DEBUG) Slog.d(TAG, "entered!");
+ if (DEBUG) Log.d(TAG, "entered!");
// XXX: TODO
break;
case DragEvent.ACTION_DRAG_EXITED:
- if (DEBUG) Slog.d(TAG, "exited!");
+ if (DEBUG) Log.d(TAG, "exited!");
break;
case DragEvent.ACTION_DROP:
- if (DEBUG) Slog.d(TAG, "dropped!");
+ if (DEBUG) Log.d(TAG, "dropped!");
mPocket.stash(event.getClipData());
break;
case DragEvent.ACTION_DRAG_ENDED:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index bfa1b63..c2054d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -40,7 +40,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.text.TextUtils;
-import android.util.Slog;
+import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
@@ -427,7 +427,7 @@
}
if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
-// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
+// Log.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
mIconHPadding = newIconHPadding;
mIconSize = newIconSize;
reloadAllNotificationIcons(); // reload the tray
@@ -436,7 +436,7 @@
final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
if (numIcons != mMaxNotificationIcons) {
mMaxNotificationIcons = numIcons;
- if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
+ if (DEBUG) Log.d(TAG, "max notification icons: " + mMaxNotificationIcons);
reloadAllNotificationIcons();
}
}
@@ -461,7 +461,7 @@
// Sanity-check that someone hasn't set up the config wrong and asked for a navigation
// bar on a tablet that has only the system bar
if (mWindowManagerService.hasNavigationBar()) {
- Slog.e(TAG, "Tablet device cannot show navigation bar and system bar");
+ Log.e(TAG, "Tablet device cannot show navigation bar and system bar");
}
} catch (RemoteException ex) {
}
@@ -711,7 +711,7 @@
super.handleMessage(m);
switch (m.what) {
case MSG_OPEN_NOTIFICATION_PEEK:
- if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
+ if (DEBUG) Log.d(TAG, "opening notification peek window; arg=" + m.arg1);
if (m.arg1 >= 0) {
final int N = mNotificationData.size();
@@ -727,7 +727,7 @@
final int peekIndex = m.arg1;
if (peekIndex < N) {
- //Slog.d(TAG, "loading peek: " + peekIndex);
+ //Log.d(TAG, "loading peek: " + peekIndex);
NotificationData.Entry entry =
mNotificationDNDMode
? mNotificationDNDDummyEntry
@@ -769,7 +769,7 @@
}
break;
case MSG_CLOSE_NOTIFICATION_PEEK:
- if (DEBUG) Slog.d(TAG, "closing notification peek window");
+ if (DEBUG) Log.d(TAG, "closing notification peek window");
mNotificationPeekWindow.setVisibility(View.GONE);
mNotificationPeekRow.removeAllViews();
@@ -786,7 +786,7 @@
mNotificationPeekKey = null;
break;
case MSG_OPEN_NOTIFICATION_PANEL:
- if (DEBUG) Slog.d(TAG, "opening notifications panel");
+ if (DEBUG) Log.d(TAG, "opening notifications panel");
if (!mNotificationPanel.isShowing()) {
mNotificationPanel.show(true, true);
mNotificationArea.setVisibility(View.INVISIBLE);
@@ -794,37 +794,37 @@
}
break;
case MSG_CLOSE_NOTIFICATION_PANEL:
- if (DEBUG) Slog.d(TAG, "closing notifications panel");
+ if (DEBUG) Log.d(TAG, "closing notifications panel");
if (mNotificationPanel.isShowing()) {
mNotificationPanel.show(false, true);
mNotificationArea.setVisibility(View.VISIBLE);
}
break;
case MSG_OPEN_INPUT_METHODS_PANEL:
- if (DEBUG) Slog.d(TAG, "opening input methods panel");
+ if (DEBUG) Log.d(TAG, "opening input methods panel");
if (mInputMethodsPanel != null) mInputMethodsPanel.openPanel();
break;
case MSG_CLOSE_INPUT_METHODS_PANEL:
- if (DEBUG) Slog.d(TAG, "closing input methods panel");
+ if (DEBUG) Log.d(TAG, "closing input methods panel");
if (mInputMethodsPanel != null) mInputMethodsPanel.closePanel(false);
break;
case MSG_OPEN_COMPAT_MODE_PANEL:
- if (DEBUG) Slog.d(TAG, "opening compat panel");
+ if (DEBUG) Log.d(TAG, "opening compat panel");
if (mCompatModePanel != null) mCompatModePanel.openPanel();
break;
case MSG_CLOSE_COMPAT_MODE_PANEL:
- if (DEBUG) Slog.d(TAG, "closing compat panel");
+ if (DEBUG) Log.d(TAG, "closing compat panel");
if (mCompatModePanel != null) mCompatModePanel.closePanel();
break;
case MSG_SHOW_CHROME:
- if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
+ if (DEBUG) Log.d(TAG, "hiding shadows (lights on)");
mBarContents.setVisibility(View.VISIBLE);
mShadow.setVisibility(View.GONE);
mSystemUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
notifyUiVisibilityChanged();
break;
case MSG_HIDE_CHROME:
- if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
+ if (DEBUG) Log.d(TAG, "showing shadows (lights out)");
animateCollapsePanels();
visibilityChanged(false);
mBarContents.setVisibility(View.GONE);
@@ -840,20 +840,20 @@
}
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
- if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
+ if (DEBUG) Log.d(TAG, "addIcon(" + slot + ") -> " + icon);
}
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon) {
- if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
+ if (DEBUG) Log.d(TAG, "updateIcon(" + slot + ") -> " + icon);
}
public void removeIcon(String slot, int index, int viewIndex) {
- if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
+ if (DEBUG) Log.d(TAG, "removeIcon(" + slot + ")");
}
public void addNotification(IBinder key, StatusBarNotification notification) {
- if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
+ if (DEBUG) Log.d(TAG, "addNotification(" + key + " -> " + notification + ")");
addNotificationViews(key, notification);
final boolean immersive = isImmersive();
@@ -861,7 +861,7 @@
// TODO: immersive mode popups for tablet
} else if (notification.getNotification().fullScreenIntent != null) {
// not immersive & a full-screen alert should be shown
- Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+ Log.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+ " sending fullScreenIntent");
try {
notification.getNotification().fullScreenIntent.send();
@@ -875,7 +875,7 @@
}
public void removeNotification(IBinder key) {
- if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ")");
+ if (DEBUG) Log.d(TAG, "removeNotification(" + key + ")");
removeNotificationViews(key);
mTicker.remove(key);
setAreThereNotifications();
@@ -900,17 +900,17 @@
// act accordingly
if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
- Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
+ Log.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
showClock(show);
}
if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
- Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
+ Log.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
}
if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
- Slog.i(TAG, "DISABLE_EXPAND: yes");
+ Log.i(TAG, "DISABLE_EXPAND: yes");
animateCollapsePanels();
visibilityChanged(false);
}
@@ -920,10 +920,10 @@
.getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
+ Log.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
mTicker.halt();
} else {
- Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
+ Log.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
}
// refresh icons to show either notifications or the DND message
@@ -1089,7 +1089,7 @@
on = true;
}
- Slog.v(TAG, "setLightsOn(" + on + ")");
+ Log.v(TAG, "setLightsOn(" + on + ")");
if (on) {
setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
} else {
@@ -1099,7 +1099,7 @@
public void topAppWindowChanged(boolean showMenu) {
if (DEBUG) {
- Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
+ Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
}
mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
@@ -1182,7 +1182,7 @@
@Override
public void setHardKeyboardStatus(boolean available, boolean enabled) {
if (DEBUG) {
- Slog.d(TAG, "Set hard keyboard status: available=" + available
+ Log.d(TAG, "Set hard keyboard status: available=" + available
+ ", enabled=" + enabled);
}
mInputMethodSwitchButton.setHardKeyboardStatus(available);
@@ -1201,7 +1201,7 @@
private boolean isImmersive() {
try {
return ActivityManagerNative.getDefault().isTopActivityImmersive();
- //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
+ //Log.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
} catch (RemoteException ex) {
// the end is nigh
return false;
@@ -1228,14 +1228,14 @@
};
public void onClickRecentButton() {
- if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
+ if (DEBUG) Log.d(TAG, "clicked recent apps; disabled=" + mDisabled);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
toggleRecentApps();
}
}
public void onClickInputMethodSwitchButton() {
- if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
+ if (DEBUG) Log.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
mHandler.removeMessages(msg);
@@ -1272,7 +1272,7 @@
}
public boolean onTouch(View v, MotionEvent event) {
-// Slog.d(TAG, String.format("touch: (%.1f, %.1f) initial: (%.1f, %.1f)",
+// Log.d(TAG, String.format("touch: (%.1f, %.1f) initial: (%.1f, %.1f)",
// event.getX(),
// event.getY(),
// mInitialTouchX,
@@ -1333,7 +1333,7 @@
public void resetNotificationPeekFadeTimer() {
if (DEBUG) {
- Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
+ Log.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
+ "ms from now");
}
mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
@@ -1393,7 +1393,7 @@
int N = mNotificationData.size();
if (DEBUG) {
- Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
+ Log.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
}
ArrayList<View> toShow = new ArrayList<View>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 30d49ca..cd1c942 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -23,7 +23,7 @@
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
-import android.util.Slog;
+import android.util.Log;
import android.view.View;
import android.view.MotionEvent;
import android.widget.FrameLayout;
@@ -80,7 +80,7 @@
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (TabletStatusBar.DEBUG) {
- Slog.d(TabletStatusBar.TAG, "TabletStatusBarView intercepting touch event: " + ev);
+ Log.d(TabletStatusBar.TAG, "TabletStatusBarView intercepting touch event: " + ev);
}
// do not close the recents panel here- the intended behavior is that recents is dismissed
// on touch up when clicking on status bar buttons
@@ -96,7 +96,7 @@
if (mPanels[i] != null && mPanels[i].getVisibility() == View.VISIBLE) {
if (eventInside(mIgnoreChildren[i], ev)) {
if (TabletStatusBar.DEBUG) {
- Slog.d(TabletStatusBar.TAG,
+ Log.d(TabletStatusBar.TAG,
"TabletStatusBarView eating event for view: "
+ mIgnoreChildren[i]);
}
@@ -106,7 +106,7 @@
}
}
if (TabletStatusBar.DEBUG) {
- Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
+ Log.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
}
if (mDelegateHelper != null && mDelegateHelper.onInterceptTouchEvent(ev)) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 095c441..04e0e56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -29,7 +29,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
-import android.util.Slog;
+import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -89,7 +89,7 @@
public void add(IBinder key, StatusBarNotification notification) {
if (false) {
- Slog.d(TAG, "add 1 mCurrentNotification=" + mCurrentNotification
+ Log.d(TAG, "add 1 mCurrentNotification=" + mCurrentNotification
+ " mQueuePos=" + mQueuePos + " mQueue=" + Arrays.toString(mQueue));
}
@@ -195,7 +195,7 @@
mCurrentKey = mKeys[0];
mCurrentNotification = mQueue[0];
if (false) {
- Slog.d(TAG, "dequeue mQueuePos=" + mQueuePos + " mQueue=" + Arrays.toString(mQueue));
+ Log.d(TAG, "dequeue mQueuePos=" + mQueuePos + " mQueue=" + Arrays.toString(mQueue));
}
final int N = mQueuePos;
for (int i=0; i<N; i++) {
@@ -276,7 +276,7 @@
if (expanded == null) {
final String ident = notification.getPackageName()
+ "/0x" + Integer.toHexString(notification.getId());
- Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
+ Log.e(TAG, "couldn't inflate view for notification " + ident, exception);
return null;
}
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 06696fe..a3eeb47 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -29,7 +29,7 @@
import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
public class StorageNotification extends StorageEventListener {
private static final String TAG = "StorageNotification";
@@ -71,7 +71,7 @@
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
final boolean connected = mStorageManager.isUsbMassStorageConnected();
- if (DEBUG) Slog.d(TAG, String.format( "Startup with UMS connection %s (media state %s)",
+ if (DEBUG) Log.d(TAG, String.format( "Startup with UMS connection %s (media state %s)",
mUmsAvailable, Environment.getExternalStorageState()));
HandlerThread thr = new HandlerThread("SystemUI StorageNotification");
@@ -102,7 +102,7 @@
*/
String st = Environment.getExternalStorageState();
- if (DEBUG) Slog.i(TAG, String.format("UMS connection changed to %s (media state %s)",
+ if (DEBUG) Log.i(TAG, String.format("UMS connection changed to %s (media state %s)",
connected, st));
if (connected && (st.equals(
@@ -129,7 +129,7 @@
}
private void onStorageStateChangedAsync(String path, String oldState, String newState) {
- if (DEBUG) Slog.i(TAG, String.format(
+ if (DEBUG) Log.i(TAG, String.format(
"Media {%s} state changed from {%s} -> {%s}", path, oldState, newState));
if (newState.equals(Environment.MEDIA_SHARED)) {
/*
@@ -250,7 +250,7 @@
true, true, null);
updateUsbMassStorageNotification(false);
} else {
- Slog.w(TAG, String.format("Ignoring unknown state {%s}", newState));
+ Log.w(TAG, String.format("Ignoring unknown state {%s}", newState));
}
}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index a2ac8fe..884f57e 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -265,7 +265,7 @@
// next: bug report, if enabled
if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0) {
+ Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
mItems.add(
new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
R.string.global_action_bug_report) {
@@ -349,16 +349,24 @@
return dialog;
}
+ private UserInfo getCurrentUser() {
+ try {
+ return ActivityManagerNative.getDefault().getCurrentUser();
+ } catch (RemoteException re) {
+ return null;
+ }
+ }
+
+ private boolean isCurrentUserOwner() {
+ UserInfo currentUser = getCurrentUser();
+ return currentUser == null || currentUser.isPrimary();
+ }
+
private void addUsersToMenu(ArrayList<Action> items) {
List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
.getUsers();
if (users.size() > 1) {
- UserInfo currentUser;
- try {
- currentUser = ActivityManagerNative.getDefault().getCurrentUser();
- } catch (RemoteException re) {
- currentUser = null;
- }
+ UserInfo currentUser = getCurrentUser();
for (final UserInfo user : users) {
boolean isCurrentUser = currentUser == null
? user.id == 0 : (currentUser.id == user.id);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b8a9797..0da3b56 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -538,7 +538,7 @@
Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
- "fancy_rotation_anim"), false, this,
+ OverlayTesting.ENABLED_SETTING), false, this,
UserHandle.USER_ALL);
updateSettings();
}
@@ -898,20 +898,7 @@
com.android.internal.R.integer.config_lidNavigationAccessibility);
mLidControlsSleep = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_lidControlsSleep);
-
- mLongPressOnHomeBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnHomeBehavior);
- if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
- mLongPressOnHomeBehavior > LONG_PRESS_HOME_ASSIST) {
- mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
- }
-
- mDoubleTapOnHomeBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
- if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
- mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
- mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
- }
+ readConfigurationDependentBehaviors();
// register for dock events
IntentFilter filter = new IntentFilter();
@@ -962,7 +949,7 @@
}
@Override
public void onDebug() {
- if (OverlayTesting.ENABLED) {
+ if (OverlayTesting.enabled) {
OverlayTesting.toggleForceOverlay(mFocusedWindow, mContext);
}
}
@@ -996,6 +983,27 @@
}
}
+ /**
+ * Read values from config.xml that may be overridden depending on
+ * the configuration of the device.
+ * eg. Disable long press on home goes to recents on sw600dp.
+ */
+ private void readConfigurationDependentBehaviors() {
+ mLongPressOnHomeBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnHomeBehavior);
+ if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
+ mLongPressOnHomeBehavior > LONG_PRESS_HOME_ASSIST) {
+ mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
+ }
+
+ mDoubleTapOnHomeBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
+ if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
+ mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
+ mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
+ }
+ }
+
@Override
public void setInitialDisplaySize(Display display, int width, int height, int density) {
if (display.getDisplayId() != Display.DEFAULT_DISPLAY) {
@@ -1171,6 +1179,8 @@
mHasSoftInput = hasSoftInput;
updateRotation = true;
}
+ OverlayTesting.enabled = Settings.System.getIntForUser(resolver,
+ OverlayTesting.ENABLED_SETTING, 0, UserHandle.USER_CURRENT) != 0;
}
if (updateRotation) {
updateRotation(true);
@@ -1374,6 +1384,7 @@
int navigationPresence) {
mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
+ readConfigurationDependentBehaviors();
readLidState();
applyLidSwitchState();
@@ -3461,7 +3472,7 @@
}
}});
} else {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Policy preventing status bar from hiding");
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
}
} else {
if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
@@ -5079,7 +5090,7 @@
}
private int updateHideybarsLw(int tmpVisibility) {
- if (OverlayTesting.ENABLED) {
+ if (OverlayTesting.enabled) {
tmpVisibility = OverlayTesting.applyForced(mFocusedWindow, tmpVisibility);
}
boolean statusBarHasFocus =
@@ -5146,7 +5157,8 @@
// TODO temporary helper that allows testing overlay bars on existing apps
private static final class OverlayTesting {
- static final boolean ENABLED = true;
+ static String ENABLED_SETTING = "overlay_testing_enabled";
+ static boolean enabled = false;
private static final HashSet<String> sForced = new HashSet<String>();
private static String parseActivity(WindowState win) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 0bf3a11..231cfe1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -682,19 +682,21 @@
@Override
public void locationCallbackFinished(ILocationListener listener) {
- //Do not use getReceiver here as that will add the ILocationListener to
+ //Do not use getReceiverLocked here as that will add the ILocationListener to
//the receiver list if it is not found. If it is not found then the
//LocationListener was removed when it had a pending broadcast and should
//not be added back.
- IBinder binder = listener.asBinder();
- Receiver receiver = mReceivers.get(binder);
- if (receiver != null) {
- synchronized (receiver) {
- // so wakelock calls will succeed
- long identity = Binder.clearCallingIdentity();
- receiver.decrementPendingBroadcastsLocked();
- Binder.restoreCallingIdentity(identity);
- }
+ synchronized (mLock) {
+ IBinder binder = listener.asBinder();
+ Receiver receiver = mReceivers.get(binder);
+ if (receiver != null) {
+ synchronized (receiver) {
+ // so wakelock calls will succeed
+ long identity = Binder.clearCallingIdentity();
+ receiver.decrementPendingBroadcastsLocked();
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
}
}
@@ -1176,7 +1178,8 @@
}
}
- private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) {
+ private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
+ String packageName) {
IBinder binder = listener.asBinder();
Receiver receiver = mReceivers.get(binder);
if (receiver == null) {
@@ -1193,7 +1196,7 @@
return receiver;
}
- private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) {
+ private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName) {
Receiver receiver = mReceivers.get(intent);
if (receiver == null) {
receiver = new Receiver(null, intent, pid, uid, packageName);
@@ -1257,7 +1260,7 @@
}
}
- private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
+ private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
int pid, int uid, String packageName) {
if (intent == null && listener == null) {
throw new IllegalArgumentException("need either listener or intent");
@@ -1265,9 +1268,9 @@
throw new IllegalArgumentException("cannot register both listener and intent");
} else if (intent != null) {
checkPendingIntent(intent);
- return getReceiver(intent, pid, uid, packageName);
+ return getReceiverLocked(intent, pid, uid, packageName);
} else {
- return getReceiver(listener, pid, uid, packageName);
+ return getReceiverLocked(listener, pid, uid, packageName);
}
}
@@ -1289,9 +1292,10 @@
// We don't check for MODE_IGNORED here; we will do that when we go to deliver
// a location.
checkLocationAccess(uid, packageName, allowedResolutionLevel);
- Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
synchronized (mLock) {
+ Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
+ packageName);
requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
}
} finally {
@@ -1338,16 +1342,17 @@
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
- // providers may use public location API's, need to clear identity
- long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
+ synchronized (mLock) {
+ Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid, packageName);
+
+ // providers may use public location API's, need to clear identity
+ long identity = Binder.clearCallingIdentity();
+ try {
removeUpdatesLocked(receiver);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index ad23b66..83739f5 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -64,6 +64,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.am.ActivityManagerService;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
@@ -1641,8 +1642,8 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid,
- external ? "1" : "0");
+ mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key),
+ ownerUid, external ? "1" : "0");
} catch (NativeDaemonConnectorException e) {
rc = StorageResultCode.OperationFailedInternalError;
}
@@ -1742,7 +1743,7 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "mount", id, key, ownerUid);
+ mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
@@ -2018,7 +2019,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "checkpw", password);
+ event = mConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
final int code = Integer.parseInt(event.getMessage());
if (code == 0) {
@@ -2057,7 +2058,7 @@
}
try {
- mConnector.execute("cryptfs", "enablecrypto", "inplace", password);
+ mConnector.execute("cryptfs", "enablecrypto", "inplace", new SensitiveArg(password));
} catch (NativeDaemonConnectorException e) {
// Encryption failed
return e.getCode();
@@ -2082,7 +2083,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "changepw", password);
+ event = mConnector.execute("cryptfs", "changepw", new SensitiveArg(password));
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
// Encryption failed
@@ -2115,7 +2116,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "verifypw", password);
+ event = mConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
@@ -2481,8 +2482,8 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute(
- "obb", "mount", mObbState.voldPath, hashedKey, mObbState.ownerGid);
+ mConnector.execute("obb", "mount", mObbState.voldPath, new SensitiveArg(hashedKey),
+ mObbState.ownerGid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index abcd8ee..8a8e38d 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -201,9 +201,28 @@
}
/**
+ * Wrapper around argument that indicates it's sensitive and shouldn't be
+ * logged.
+ */
+ public static class SensitiveArg {
+ private final Object mArg;
+
+ public SensitiveArg(Object arg) {
+ mArg = arg;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mArg);
+ }
+ }
+
+ /**
* Make command for daemon, escaping arguments as needed.
*/
- private void makeCommand(StringBuilder builder, String cmd, Object... args) {
+ @VisibleForTesting
+ static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
+ String cmd, Object... args) {
if (cmd.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected command: " + cmd);
}
@@ -211,16 +230,26 @@
throw new IllegalArgumentException("Arguments must be separate from command");
}
- builder.append(cmd);
+ rawBuilder.append(sequenceNumber).append(' ').append(cmd);
+ logBuilder.append(sequenceNumber).append(' ').append(cmd);
for (Object arg : args) {
final String argString = String.valueOf(arg);
if (argString.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected argument: " + arg);
}
- builder.append(' ');
- appendEscaped(builder, argString);
+ rawBuilder.append(' ');
+ logBuilder.append(' ');
+
+ appendEscaped(rawBuilder, argString);
+ if (arg instanceof SensitiveArg) {
+ logBuilder.append("[scrubbed]");
+ } else {
+ appendEscaped(logBuilder, argString);
+ }
}
+
+ rawBuilder.append('\0');
}
/**
@@ -300,27 +329,27 @@
*/
public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
- final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
-
- final int sequenceNumber = mSequenceNumber.incrementAndGet();
- final StringBuilder cmdBuilder =
- new StringBuilder(Integer.toString(sequenceNumber)).append(' ');
final long startTime = SystemClock.elapsedRealtime();
- makeCommand(cmdBuilder, cmd, args);
+ final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
- final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
+ final int sequenceNumber = mSequenceNumber.incrementAndGet();
+
+ makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
+
+ final String rawCmd = rawBuilder.toString();
+ final String logCmd = logBuilder.toString();
+
log("SND -> {" + logCmd + "}");
- cmdBuilder.append('\0');
- final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */
-
synchronized (mDaemonLock) {
if (mOutputStream == null) {
throw new NativeDaemonConnectorException("missing output stream");
} else {
try {
- mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));
+ mOutputStream.write(rawCmd.getBytes(Charsets.UTF_8));
} catch (IOException e) {
throw new NativeDaemonConnectorException("problem sending command", e);
}
@@ -329,7 +358,7 @@
NativeDaemonEvent event = null;
do {
- event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);
+ event = mResponseQueue.remove(sequenceNumber, timeout, logCmd);
if (event == null) {
loge("timed-out waiting for response to " + logCmd);
throw new NativeDaemonFailureException(logCmd, event);
@@ -444,10 +473,11 @@
private static class ResponseQueue {
private static class PendingCmd {
- public int cmdNum;
+ public final int cmdNum;
+ public final String logCmd;
+
public BlockingQueue<NativeDaemonEvent> responses =
new ArrayBlockingQueue<NativeDaemonEvent>(10);
- public String request;
// The availableResponseCount member is used to track when we can remove this
// instance from the ResponseQueue.
@@ -465,7 +495,11 @@
// hold references to this instance already so it can be removed from
// mPendingCmds queue.
public int availableResponseCount;
- public PendingCmd(int c, String r) {cmdNum = c; request = r;}
+
+ public PendingCmd(int cmdNum, String logCmd) {
+ this.cmdNum = cmdNum;
+ this.logCmd = logCmd;
+ }
}
private final LinkedList<PendingCmd> mPendingCmds;
@@ -494,7 +528,7 @@
// let any waiter timeout waiting for this
PendingCmd pendingCmd = mPendingCmds.remove();
Slog.e("NativeDaemonConnector.ResponseQueue",
- "Removing request: " + pendingCmd.request + " (" +
+ "Removing request: " + pendingCmd.logCmd + " (" +
pendingCmd.cmdNum + ")");
}
found = new PendingCmd(cmdNum, null);
@@ -512,7 +546,7 @@
// note that the timeout does not count time in deep sleep. If you don't want
// the device to sleep, hold a wakelock
- public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
+ public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String logCmd) {
PendingCmd found = null;
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
@@ -522,7 +556,7 @@
}
}
if (found == null) {
- found = new PendingCmd(cmdNum, origCmd);
+ found = new PendingCmd(cmdNum, logCmd);
mPendingCmds.add(found);
}
found.availableResponseCount--;
@@ -544,7 +578,7 @@
pw.println("Pending requests:");
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
- pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.request);
+ pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
}
}
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 0d266c2..769b97f 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -34,7 +34,6 @@
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.Context;
import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
@@ -50,15 +49,18 @@
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import com.android.internal.app.IBatteryStats;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Maps;
@@ -343,6 +345,14 @@
SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
+ if (mBandwidthControlEnabled) {
+ try {
+ IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"))
+ .noteNetworkStatsEnabled();
+ } catch (RemoteException e) {
+ }
+ }
+
// push any existing quota or UID rules
synchronized (mQuotaLock) {
int size = mActiveQuotas.size();
@@ -990,8 +1000,8 @@
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- "broadcast", getSecurityType(wifiConfig),
- wifiConfig.preSharedKey);
+ "broadcast", "6", getSecurityType(wifiConfig),
+ new SensitiveArg(wifiConfig.preSharedKey));
}
mConnector.execute("softap", "startap");
} catch (NativeDaemonConnectorException e) {
@@ -1040,8 +1050,8 @@
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- "broadcast", getSecurityType(wifiConfig),
- wifiConfig.preSharedKey);
+ "broadcast", "6", getSecurityType(wifiConfig),
+ new SensitiveArg(wifiConfig.preSharedKey));
}
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index f4065ed..6ddf3a1 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1390,7 +1390,7 @@
return ;
}
- final boolean isSystemToast = ("android".equals(pkg));
+ final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
if (!isSystemToast) {
@@ -1608,7 +1608,7 @@
Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
}
checkCallerIsSystemOrSameApp(pkg);
- final boolean isSystemNotification = ("android".equals(pkg));
+ final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg));
userId = ActivityManager.handleIncomingUser(callingPid,
callingUid, userId, true, false, "enqueueNotification", pkg);
@@ -2084,19 +2084,26 @@
cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
}
+ // Return true if the caller is a system or phone UID and therefore should not have
+ // any notifications or toasts blocked.
+ boolean isCallerSystem() {
+ final int uid = Binder.getCallingUid();
+ final int appid = UserHandle.getAppId(uid);
+ return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
+ }
+
void checkCallerIsSystem() {
- int uid = Binder.getCallingUid();
- if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+ if (isCallerSystem()) {
return;
}
- throw new SecurityException("Disallowed call for uid " + uid);
+ throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
}
void checkCallerIsSystemOrSameApp(String pkg) {
- int uid = Binder.getCallingUid();
- if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+ if (isCallerSystem()) {
return;
}
+ final int uid = Binder.getCallingUid();
try {
ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
pkg, 0, UserHandle.getCallingUserId());
diff --git a/services/java/com/android/server/ProcessMap.java b/services/java/com/android/server/ProcessMap.java
index 6b26403..20c97ba 100644
--- a/services/java/com/android/server/ProcessMap.java
+++ b/services/java/com/android/server/ProcessMap.java
@@ -16,13 +16,12 @@
package com.android.server;
+import android.util.ArrayMap;
import android.util.SparseArray;
-import java.util.HashMap;
-
public class ProcessMap<E> {
- final HashMap<String, SparseArray<E>> mMap
- = new HashMap<String, SparseArray<E>>();
+ final ArrayMap<String, SparseArray<E>> mMap
+ = new ArrayMap<String, SparseArray<E>>();
public E get(String name, int uid) {
SparseArray<E> uids = mMap.get(name);
@@ -50,7 +49,7 @@
}
}
- public HashMap<String, SparseArray<E>> getMap() {
+ public ArrayMap<String, SparseArray<E>> getMap() {
return mMap;
}
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 84e44bd..98c4352 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -57,7 +57,7 @@
import android.util.SparseArray;
import android.util.TimeUtils;
-public class ActiveServices {
+public final class ActiveServices {
static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
@@ -1840,10 +1840,10 @@
/**
* Prints a list of ServiceRecords (dumpsys activity services)
*/
- boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
boolean needSep = false;
- boolean needSepResult = false;
+ boolean printedAnything = false;
ItemMatcher matcher = new ItemMatcher();
matcher.build(args, opti);
@@ -1866,7 +1866,7 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
- needSepResult = true;
+ printedAnything = true;
if (!printed) {
if (user != 0) {
pw.println();
@@ -1893,7 +1893,7 @@
pw.println(r.connections.size());
if (r.connections.size() > 0) {
pw.println(" Connections:");
- for (int conni=0; conni<=r.connections.size(); conni++) {
+ for (int conni=0; conni<r.connections.size(); conni++) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord conn = clist.get(i);
@@ -1930,11 +1930,11 @@
needSep = true;
}
}
- needSep = printed;
+ needSep |= printed;
}
}
} catch (Exception e) {
- Log.w(TAG, "Exception in dumpServicesLocked: " + e);
+ Log.w(TAG, "Exception in dumpServicesLocked", e);
}
if (mPendingServices.size() > 0) {
@@ -1947,9 +1947,9 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
- needSepResult = true;
+ printedAnything = true;
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Pending services:");
printed = true;
@@ -1970,9 +1970,9 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
- needSepResult = true;
+ printedAnything = true;
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Restarting services:");
printed = true;
@@ -1993,9 +1993,9 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
- needSepResult = true;
+ printedAnything = true;
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Stopping services:");
printed = true;
@@ -2022,9 +2022,9 @@
|| !dumpPackage.equals(cr.binding.client.info.packageName))) {
continue;
}
- needSepResult = true;
+ printedAnything = true;
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Connection bindings to services:");
printed = true;
@@ -2036,7 +2036,9 @@
}
}
- return needSepResult;
+ if (!printedAnything) {
+ pw.println(" (nothing)");
+ }
}
/**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8d71cf9..f06b9a6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -26,6 +26,7 @@
import android.app.AppOpsManager;
import android.appwidget.AppWidgetManager;
+import android.util.ArrayMap;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
@@ -401,6 +402,12 @@
final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
/**
+ * Tracking long-term execution of processes to look for abuse and other
+ * bad app behavior.
+ */
+ final ProcessTracker mProcessTracker = new ProcessTracker();
+
+ /**
* The currently running isolated processes.
*/
final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<ProcessRecord>();
@@ -614,8 +621,8 @@
* by the user ID the sticky is for, and can include UserHandle.USER_ALL
* for stickies that are sent to all users.
*/
- final SparseArray<HashMap<String, ArrayList<Intent>>> mStickyBroadcasts =
- new SparseArray<HashMap<String, ArrayList<Intent>>>();
+ final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts =
+ new SparseArray<ArrayMap<String, ArrayList<Intent>>>();
final ActiveServices mServices;
@@ -803,16 +810,16 @@
int mLruSeq = 0;
/**
- * Keep track of the non-hidden/empty process we last found, to help
- * determine how to distribute hidden/empty processes next time.
+ * Keep track of the non-cached/empty process we last found, to help
+ * determine how to distribute cached/empty processes next time.
*/
- int mNumNonHiddenProcs = 0;
+ int mNumNonCachedProcs = 0;
/**
- * Keep track of the number of hidden procs, to balance oom adj
+ * Keep track of the number of cached procs, to balance oom adj
* distribution between those and empty procs.
*/
- int mNumHiddenProcs = 0;
+ int mNumCachedProcs = 0;
/**
* Keep track of the number of service processes we last found, to
@@ -895,7 +902,7 @@
*/
boolean mBooted = false;
- int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
+ int mProcessLimit = ProcessList.MAX_CACHED_APPS;
int mProcessLimitOverride = -1;
WindowManagerService mWindowManager;
@@ -1476,6 +1483,7 @@
ServiceManager.addService("meminfo", new MemBinder(m));
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
ServiceManager.addService("dbinfo", new DbBinder(m));
+ ServiceManager.addService("procstats", new ProcBinder(m));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(m));
}
@@ -1692,6 +1700,26 @@
}
}
+ static class ProcBinder extends Binder {
+ ActivityManagerService mActivityManagerService;
+ ProcBinder(ActivityManagerService activityManagerService) {
+ mActivityManagerService = activityManagerService;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump procstats from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
+ return;
+ }
+
+ mActivityManagerService.dumpProcessTracker(fd, pw, args);
+ }
+ }
+
private ActivityManagerService() {
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
@@ -1780,7 +1808,9 @@
// We need to tell all apps about the system property change.
ArrayList<IBinder> procs = new ArrayList<IBinder>();
synchronized(this) {
- for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip=0; ip<NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
@@ -2000,22 +2030,22 @@
// If this process contains content providers, we want to keep
// it a little more strongly.
app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
- // Also don't let it kick out the first few "real" hidden processes.
- skipTop = ProcessList.MIN_HIDDEN_APPS;
+ // Also don't let it kick out the first few "real" cached processes.
+ skipTop = ProcessList.MIN_CACHED_APPS;
} else {
// If this process doesn't have activities, we less strongly
// want to keep it around, and generally want to avoid getting
// in front of any very recently used activities.
app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
- // Also don't let it kick out the first few "real" hidden processes.
- skipTop = ProcessList.MIN_HIDDEN_APPS;
+ // Also don't let it kick out the first few "real" cached processes.
+ skipTop = ProcessList.MIN_CACHED_APPS;
}
while (i >= 0) {
ProcessRecord p = mLruProcesses.get(i);
// If this app shouldn't be in front of the first N background
- // apps, then skip over that many that are currently hidden.
- if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ // apps, then skip over that many that are currently cached.
+ if (skipTop > 0 && p.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
skipTop--;
}
if (p.lruWeight <= app.lruWeight || i < bestPos) {
@@ -3179,7 +3209,7 @@
boolean haveBg = false;
for (int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord rec = mLruProcesses.get(i);
- if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (rec.thread != null && rec.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
haveBg = true;
break;
}
@@ -3703,7 +3733,9 @@
try {
synchronized(this) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
- for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip=0; ip<NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
@@ -3713,7 +3745,7 @@
}
if (app.removed) {
procs.add(app);
- } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ } else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
app.removed = true;
procs.add(app);
}
@@ -3940,7 +3972,9 @@
// same UID (except for the system or root user), and all whose name
// matches the package name.
final String procNamePrefix = packageName != null ? (packageName + ":") : null;
- for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip=0; ip<NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
@@ -4026,9 +4060,9 @@
Slog.i(TAG, "Force stopping u" + userId + ": " + reason);
}
- Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
- while (badApps.hasNext()) {
- SparseArray<Long> ba = badApps.next();
+ final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
+ for (int ip=pmap.size()-1; ip>=0; ip--) {
+ SparseArray<Long> ba = pmap.valueAt(ip);
for (i=ba.size()-1; i>=0; i--) {
boolean remove = false;
final int entUid = ba.keyAt(i);
@@ -4050,7 +4084,7 @@
}
}
if (ba.size() == 0) {
- badApps.remove();
+ pmap.removeAt(ip);
}
}
}
@@ -4974,7 +5008,7 @@
enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
"setProcessLimit()");
synchronized (this) {
- mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
+ mProcessLimit = max < 0 ? ProcessList.MAX_CACHED_APPS : max;
mProcessLimitOverride = max;
}
trimApplications();
@@ -5945,12 +5979,12 @@
@Override
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
- final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
+ final long cachedAppMem = mProcessList.getMemLevel(ProcessList.CACHED_APP_MIN_ADJ);
outInfo.availMem = Process.getFreeMemory();
outInfo.totalMem = Process.getTotalMemory();
outInfo.threshold = homeAppMem;
- outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
- outInfo.hiddenAppThreshold = hiddenAppMem;
+ outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
+ outInfo.hiddenAppThreshold = cachedAppMem;
outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
ProcessList.SERVICE_ADJ);
outInfo.visibleAppThreshold = mProcessList.getMemLevel(
@@ -6177,10 +6211,11 @@
// Find any running processes associated with this app.
final String pkg = component.getPackageName();
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
- HashMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
- for (SparseArray<ProcessRecord> uids : pmap.values()) {
- for (int i=0; i<uids.size(); i++) {
- ProcessRecord proc = uids.valueAt(i);
+ ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+ for (int i=0; i<pmap.size(); i++) {
+ SparseArray<ProcessRecord> uids = pmap.valueAt(i);
+ for (int j=0; j<uids.size(); j++) {
+ ProcessRecord proc = uids.valueAt(j);
if (proc.userId != tr.userId) {
continue;
}
@@ -7279,7 +7314,8 @@
synchronized (stats) {
ps = stats.getProcessStatsLocked(info.uid, proc);
}
- return new ProcessRecord(ps, thread, info, proc, uid);
+ return new ProcessRecord(ps, thread, info, proc, uid,
+ mProcessTracker.getStateLocked(info.processName, info.uid));
}
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
@@ -7908,11 +7944,11 @@
}
}
- // If the worst oom_adj is somewhere in the hidden proc LRU range,
- // then constrain it so we will kill all hidden procs.
- if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
- && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
- worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
+ // If the worst oom_adj is somewhere in the cached proc LRU range,
+ // then constrain it so we will kill all cached procs.
+ if (worstType < ProcessList.CACHED_APP_MAX_ADJ
+ && worstType > ProcessList.CACHED_APP_MIN_ADJ) {
+ worstType = ProcessList.CACHED_APP_MIN_ADJ;
}
// If this is not a secure call, don't let it kill processes that
@@ -8815,7 +8851,9 @@
}
synchronized (this) {
- for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip=0; ip<NP; ip++) {
+ SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord p = apps.valueAt(ia);
@@ -9174,9 +9212,9 @@
}
static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
- if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
if (currApp != null) {
- currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
+ currApp.lru = adj - ProcessList.CACHED_APP_MIN_ADJ + 1;
}
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
} else if (adj >= ProcessList.SERVICE_B_ADJ) {
@@ -9489,39 +9527,28 @@
// No piece of data specified, dump everything.
synchronized (this) {
- boolean needSep;
- needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
- if (needSep) {
- pw.println(" ");
- }
+ dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
- if (needSep) {
- pw.println(" ");
- }
+ dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
- if (needSep) {
- pw.println(" ");
- }
+ dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = mServices.dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
- if (needSep) {
- pw.println(" ");
- }
+ mServices.dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
- if (needSep) {
- pw.println(" ");
- }
+ dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
@@ -9530,21 +9557,32 @@
Binder.restoreCallingIdentity(origId);
}
- boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
- mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
+ boolean printedAnything = mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient,
+ dumpPackage);
+ boolean needSep = printedAnything;
- pw.println(" ");
- pw.println(" mFocusedActivity: " + mFocusedActivity);
- pw.println(" ");
+ boolean printed = ActivityStackSupervisor.printThisActivity(pw, mFocusedActivity,
+ dumpPackage, needSep, " mFocusedActivity: ");
+ if (printed) {
+ printedAnything = true;
+ needSep = false;
+ }
- mStackSupervisor.dump(pw, " ");
+ if (dumpPackage == null) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ printedAnything = true;
+ mStackSupervisor.dump(pw, " ");
+ }
if (mRecentTasks.size() > 0) {
- pw.println();
- pw.println(" Recent tasks:");
+ boolean printedHeader = false;
final int N = mRecentTasks.size();
for (int i=0; i<N; i++) {
@@ -9555,6 +9593,14 @@
continue;
}
}
+ if (!printedHeader) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Recent tasks:");
+ printedHeader = true;
+ printedAnything = true;
+ }
pw.print(" * Recent #"); pw.print(i); pw.print(": ");
pw.println(tr);
if (dumpAll) {
@@ -9563,27 +9609,33 @@
}
}
- return true;
+ if (!printedAnything) {
+ pw.println(" (nothing)");
+ }
}
- boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
+ boolean printedAnything = false;
int numPers = 0;
pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
if (dumpAll) {
- for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip=0; ip<NP; ip++) {
+ SparseArray<ProcessRecord> procs = mProcessNames.getMap().valueAt(ip);
final int NA = procs.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord r = procs.valueAt(ia);
- if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
continue;
}
if (!needSep) {
pw.println(" All known processes:");
needSep = true;
+ printedAnything = true;
}
pw.print(r.persistent ? " *PERS*" : " *APP*");
pw.print(" UID "); pw.print(procs.keyAt(ia));
@@ -9597,41 +9649,50 @@
}
if (mIsolatedProcesses.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Isolated process list (sorted by uid):");
+ boolean printed = false;
for (int i=0; i<mIsolatedProcesses.size(); i++) {
ProcessRecord r = mIsolatedProcesses.valueAt(i);
- if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
continue;
}
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Isolated process list (sorted by uid):");
+ printedAnything = true;
+ printed = true;
+ needSep = true;
+ }
pw.println(String.format("%sIsolated #%2d: %s",
" ", i, r.toString()));
}
}
if (mLruProcesses.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Process LRU list (sorted by oom_adj):");
- dumpProcessOomList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", false, dumpPackage);
- needSep = true;
+ boolean printed = dumpProcessOomList(pw, this, mLruProcesses, " ",
+ "Proc", "PERS", false, dumpPackage, needSep,
+ " Process LRU list (sorted by oom_adj):");
+ if (printed) {
+ needSep = true;
+ printedAnything = true;
+ }
}
- if (dumpAll) {
+ if (dumpAll || dumpPackage != null) {
synchronized (mPidsSelfLocked) {
boolean printed = false;
for (int i=0; i<mPidsSelfLocked.size(); i++) {
ProcessRecord r = mPidsSelfLocked.valueAt(i);
- if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" PID mappings:");
printed = true;
+ printedAnything = true;
}
pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
@@ -9646,14 +9707,15 @@
ProcessRecord r = mPidsSelfLocked.get(
mForegroundProcesses.valueAt(i).pid);
if (dumpPackage != null && (r == null
- || !dumpPackage.equals(r.info.packageName))) {
+ || !r.pkgList.contains(dumpPackage))) {
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Foreground Processes:");
printed = true;
+ printedAnything = true;
}
pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
@@ -9662,24 +9724,27 @@
}
if (mPersistentStartingProcesses.size() > 0) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
+ printedAnything = true;
pw.println(" Persisent processes that are starting:");
dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
"Starting Norm", "Restarting PERS", dumpPackage);
}
if (mRemovedProcesses.size() > 0) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
+ printedAnything = true;
pw.println(" Processes that are being removed:");
dumpProcessList(pw, this, mRemovedProcesses, " ",
"Removed Norm", "Removed PERS", dumpPackage);
}
if (mProcessesOnHold.size() > 0) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
+ printedAnything = true;
pw.println(" Processes that are on old until the system is ready:");
dumpProcessList(pw, this, mProcessesOnHold, " ",
"OnHold Norm", "OnHold PERS", dumpPackage);
@@ -9690,23 +9755,25 @@
if (mProcessCrashTimes.getMap().size() > 0) {
boolean printed = false;
long now = SystemClock.uptimeMillis();
- for (Map.Entry<String, SparseArray<Long>> procs
- : mProcessCrashTimes.getMap().entrySet()) {
- String pname = procs.getKey();
- SparseArray<Long> uids = procs.getValue();
+ final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
+ final int NP = pmap.size();
+ for (int ip=0; ip<NP; ip++) {
+ String pname = pmap.keyAt(ip);
+ SparseArray<Long> uids = pmap.valueAt(ip);
final int N = uids.size();
for (int i=0; i<N; i++) {
int puid = uids.keyAt(i);
ProcessRecord r = mProcessNames.get(pname, puid);
if (dumpPackage != null && (r == null
- || !dumpPackage.equals(r.info.packageName))) {
+ || !r.pkgList.contains(dumpPackage))) {
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Time since processes crashed:");
printed = true;
+ printedAnything = true;
}
pw.print(" Process "); pw.print(pname);
pw.print(" uid "); pw.print(puid);
@@ -9719,22 +9786,24 @@
if (mBadProcesses.getMap().size() > 0) {
boolean printed = false;
- for (Map.Entry<String, SparseArray<Long>> procs
- : mBadProcesses.getMap().entrySet()) {
- String pname = procs.getKey();
- SparseArray<Long> uids = procs.getValue();
+ final ArrayMap<String, SparseArray<Long>> pmap = mBadProcesses.getMap();
+ final int NP = pmap.size();
+ for (int ip=0; ip<NP; ip++) {
+ String pname = pmap.keyAt(ip);
+ SparseArray<Long> uids = pmap.valueAt(ip);
final int N = uids.size();
for (int i=0; i<N; i++) {
int puid = uids.keyAt(i);
ProcessRecord r = mProcessNames.get(pname, puid);
if (dumpPackage != null && (r == null
- || !dumpPackage.equals(r.info.packageName))) {
+ || !r.pkgList.contains(dumpPackage))) {
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Bad processes:");
+ printedAnything = true;
}
pw.print(" Bad process "); pw.print(pname);
pw.print(" uid "); pw.print(puid);
@@ -9744,40 +9813,64 @@
}
}
- pw.println();
- pw.println(" mStartedUsers:");
- for (int i=0; i<mStartedUsers.size(); i++) {
- UserStartedState uss = mStartedUsers.valueAt(i);
- pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
- pw.print(": "); uss.dump("", pw);
+ if (dumpPackage == null) {
+ pw.println();
+ needSep = false;
+ pw.println(" mStartedUsers:");
+ for (int i=0; i<mStartedUsers.size(); i++) {
+ UserStartedState uss = mStartedUsers.valueAt(i);
+ pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
+ pw.print(": "); uss.dump("", pw);
+ }
+ pw.print(" mStartedUserArray: [");
+ for (int i=0; i<mStartedUserArray.length; i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mStartedUserArray[i]);
+ }
+ pw.println("]");
+ pw.print(" mUserLru: [");
+ for (int i=0; i<mUserLru.size(); i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mUserLru.get(i));
+ }
+ pw.println("]");
+ if (dumpAll) {
+ pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
+ }
}
- pw.print(" mStartedUserArray: [");
- for (int i=0; i<mStartedUserArray.length; i++) {
- if (i > 0) pw.print(", ");
- pw.print(mStartedUserArray[i]);
+ if (mHomeProcess != null && (dumpPackage == null
+ || mHomeProcess.pkgList.contains(dumpPackage))) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mHomeProcess: " + mHomeProcess);
}
- pw.println("]");
- pw.print(" mUserLru: [");
- for (int i=0; i<mUserLru.size(); i++) {
- if (i > 0) pw.print(", ");
- pw.print(mUserLru.get(i));
+ if (mPreviousProcess != null && (dumpPackage == null
+ || mPreviousProcess.pkgList.contains(dumpPackage))) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mPreviousProcess: " + mPreviousProcess);
}
- pw.println("]");
- if (dumpAll) {
- pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
- }
- pw.println(" mHomeProcess: " + mHomeProcess);
- pw.println(" mPreviousProcess: " + mPreviousProcess);
if (dumpAll) {
StringBuilder sb = new StringBuilder(128);
sb.append(" mPreviousProcessVisibleTime: ");
TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
pw.println(sb);
}
- if (mHeavyWeightProcess != null) {
+ if (mHeavyWeightProcess != null && (dumpPackage == null
+ || mHeavyWeightProcess.pkgList.contains(dumpPackage))) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
}
- pw.println(" mConfiguration: " + mConfiguration);
+ if (dumpPackage == null) {
+ pw.println(" mConfiguration: " + mConfiguration);
+ }
if (dumpAll) {
pw.println(" mConfigWillChange: " + getFocusedStack().mConfigWillChange);
if (mCompatModePackages.getPackages().size() > 0) {
@@ -9798,57 +9891,82 @@
}
}
}
- if (mSleeping || mWentToSleep || mLockScreenShown) {
- pw.println(" mSleeping=" + mSleeping + " mWentToSleep=" + mWentToSleep
- + " mLockScreenShown " + mLockScreenShown);
- }
- if (mShuttingDown) {
- pw.println(" mShuttingDown=" + mShuttingDown);
+ if (dumpPackage == null) {
+ if (mSleeping || mWentToSleep || mLockScreenShown) {
+ pw.println(" mSleeping=" + mSleeping + " mWentToSleep=" + mWentToSleep
+ + " mLockScreenShown " + mLockScreenShown);
+ }
+ if (mShuttingDown) {
+ pw.println(" mShuttingDown=" + mShuttingDown);
+ }
}
if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
|| mOrigWaitForDebugger) {
- pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
- + " mDebugTransient=" + mDebugTransient
- + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
+ if (dumpPackage == null || dumpPackage.equals(mDebugApp)
+ || dumpPackage.equals(mOrigDebugApp)) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
+ + " mDebugTransient=" + mDebugTransient
+ + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
+ }
}
if (mOpenGlTraceApp != null) {
- pw.println(" mOpenGlTraceApp=" + mOpenGlTraceApp);
+ if (dumpPackage == null || dumpPackage.equals(mOpenGlTraceApp)) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mOpenGlTraceApp=" + mOpenGlTraceApp);
+ }
}
if (mProfileApp != null || mProfileProc != null || mProfileFile != null
|| mProfileFd != null) {
- pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
- pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
- pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
- + mAutoStopProfiler);
+ if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
+ pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
+ pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
+ + mAutoStopProfiler);
+ }
}
- if (mAlwaysFinishActivities || mController != null) {
- pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
- + " mController=" + mController);
+ if (dumpPackage == null) {
+ if (mAlwaysFinishActivities || mController != null) {
+ pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
+ + " mController=" + mController);
+ }
+ if (dumpAll) {
+ pw.println(" Total persistent processes: " + numPers);
+ pw.println(" mStartRunning=" + mStartRunning
+ + " mProcessesReady=" + mProcessesReady
+ + " mSystemReady=" + mSystemReady);
+ pw.println(" mBooting=" + mBooting
+ + " mBooted=" + mBooted
+ + " mFactoryTest=" + mFactoryTest);
+ pw.print(" mLastPowerCheckRealtime=");
+ TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
+ pw.println("");
+ pw.print(" mLastPowerCheckUptime=");
+ TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
+ pw.println("");
+ pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
+ pw.println(" mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
+ pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
+ pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
+ + " mNumCachedProcs=" + mNumCachedProcs
+ + " mNumServiceProcs=" + mNumServiceProcs
+ + " mNewNumServiceProcs=" + mNewNumServiceProcs);
+ }
}
- if (dumpAll) {
- pw.println(" Total persistent processes: " + numPers);
- pw.println(" mStartRunning=" + mStartRunning
- + " mProcessesReady=" + mProcessesReady
- + " mSystemReady=" + mSystemReady);
- pw.println(" mBooting=" + mBooting
- + " mBooted=" + mBooted
- + " mFactoryTest=" + mFactoryTest);
- pw.print(" mLastPowerCheckRealtime=");
- TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
- pw.println("");
- pw.print(" mLastPowerCheckUptime=");
- TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
- pw.println("");
- pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
- pw.println(" mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
- pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
- pw.println(" mNumNonHiddenProcs=" + mNumNonHiddenProcs
- + " mNumHiddenProcs=" + mNumHiddenProcs
- + " mNumServiceProcs=" + mNumServiceProcs
- + " mNewNumServiceProcs=" + mNewNumServiceProcs);
+
+ if (!printedAnything) {
+ pw.println(" (nothing)");
}
-
- return true;
}
boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
@@ -9862,7 +9980,7 @@
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Processes that are waiting to GC:");
printed = true;
@@ -9885,7 +10003,7 @@
boolean needSep = false;
if (mLruProcesses.size() > 0) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" OOM levels:");
pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
@@ -9899,14 +10017,14 @@
pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
- pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
- pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
+ pw.print(" CACHED_APP_MIN_ADJ: "); pw.println(ProcessList.CACHED_APP_MIN_ADJ);
+ pw.print(" CACHED_APP_MAX_ADJ: "); pw.println(ProcessList.CACHED_APP_MAX_ADJ);
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Process OOM control:");
dumpProcessOomList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", true, null);
+ "Proc", "PERS", true, null, false, null);
needSep = true;
}
@@ -10098,11 +10216,11 @@
}
}
- boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
- boolean dumpedHeader = false;
boolean needSep = false;
boolean onlyHistory = false;
+ boolean printedAnything = false;
if ("history".equals(dumpPackage)) {
if (opti < args.length && "-s".equals(args[opti])) {
@@ -10127,6 +10245,7 @@
pw.println(" Registered Receivers:");
needSep = true;
printed = true;
+ printedAnything = true;
}
pw.print(" * "); pw.println(r);
r.dump(pw, " ");
@@ -10137,11 +10256,13 @@
"\n Receiver Resolver Table:" : " Receiver Resolver Table:",
" ", dumpPackage, false)) {
needSep = true;
+ printedAnything = true;
}
}
for (BroadcastQueue q : mBroadcastQueues) {
needSep = q.dumpLocked(fd, pw, args, opti, dumpAll, dumpPackage, needSep);
+ printedAnything |= needSep;
}
needSep = true;
@@ -10152,6 +10273,7 @@
pw.println();
}
needSep = true;
+ printedAnything = true;
pw.print(" Sticky broadcasts for user ");
pw.print(mStickyBroadcasts.keyAt(user)); pw.println(":");
StringBuilder sb = new StringBuilder(128);
@@ -10189,14 +10311,18 @@
pw.println(" mHandler:");
mHandler.dump(new PrintWriterPrinter(pw), " ");
needSep = true;
+ printedAnything = true;
}
- return needSep;
+ if (!printedAnything) {
+ pw.println(" (nothing)");
+ }
}
- boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
boolean needSep;
+ boolean printedAnything = false;
ItemMatcher matcher = new ItemMatcher();
matcher.build(args, opti);
@@ -10204,6 +10330,7 @@
pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
+ printedAnything |= needSep;
if (mLaunchingProviders.size() > 0) {
boolean printed = false;
@@ -10213,10 +10340,11 @@
continue;
}
if (!printed) {
- if (needSep) pw.println(" ");
+ if (needSep) pw.println();
needSep = true;
pw.println(" Launching content providers:");
printed = true;
+ printedAnything = true;
}
pw.print(" Launching #"); pw.print(i); pw.print(": ");
pw.println(r);
@@ -10225,7 +10353,7 @@
if (mGrantedUriPermissions.size() > 0) {
boolean printed = false;
- int dumpUid = -1;
+ int dumpUid = -2;
if (dumpPackage != null) {
try {
dumpUid = mContext.getPackageManager().getPackageUid(dumpPackage, 0);
@@ -10235,7 +10363,7 @@
}
for (int i=0; i<mGrantedUriPermissions.size(); i++) {
int uid = mGrantedUriPermissions.keyAt(i);
- if (dumpUid >= 0 && UserHandle.getAppId(uid) != dumpUid) {
+ if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
continue;
}
HashMap<Uri, UriPermission> perms
@@ -10245,6 +10373,7 @@
needSep = true;
pw.println(" Granted Uri Permissions:");
printed = true;
+ printedAnything = true;
}
pw.print(" * UID "); pw.print(uid);
pw.println(" holds:");
@@ -10256,16 +10385,19 @@
}
}
}
-
- return needSep;
+
+ if (!printedAnything) {
+ pw.println(" (nothing)");
+ }
}
- boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ void dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
- boolean needSep = false;
-
+ boolean printed = false;
+
+ pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
+
if (mIntentSenderRecords.size() > 0) {
- boolean printed = false;
Iterator<WeakReference<PendingIntentRecord>> it
= mIntentSenderRecords.values().iterator();
while (it.hasNext()) {
@@ -10275,11 +10407,7 @@
|| !dumpPackage.equals(rec.key.packageName))) {
continue;
}
- if (!printed) {
- pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
- printed = true;
- }
- needSep = true;
+ printed = true;
if (rec != null) {
pw.print(" * "); pw.println(rec);
if (dumpAll) {
@@ -10290,8 +10418,10 @@
}
}
}
-
- return needSep;
+
+ if (!printed) {
+ pw.println(" (nothing)");
+ }
}
private static String buildOomTag(String prefix, String space, int val, int base) {
@@ -10326,13 +10456,13 @@
private static final boolean dumpProcessOomList(PrintWriter pw,
ActivityManagerService service, List<ProcessRecord> origList,
String prefix, String normalLabel, String persistentLabel,
- boolean inclDetails, String dumpPackage) {
+ boolean inclDetails, String dumpPackage, boolean needSep, String header) {
ArrayList<Pair<ProcessRecord, Integer>> list
= new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
for (int i=0; i<origList.size(); i++) {
ProcessRecord r = origList.get(i);
- if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
+ if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
continue;
}
list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
@@ -10341,7 +10471,14 @@
if (list.size() <= 0) {
return false;
}
-
+
+ if (header != null) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(header);
+ }
+
Comparator<Pair<ProcessRecord, Integer>> comparator
= new Comparator<Pair<ProcessRecord, Integer>>() {
@Override
@@ -10367,8 +10504,8 @@
for (int i=list.size()-1; i>=0; i--) {
ProcessRecord r = list.get(i).first;
String oomAdj;
- if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
- oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
+ if (r.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ oomAdj = buildOomTag("cch", " ", r.setAdj, ProcessList.CACHED_APP_MIN_ADJ);
} else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
} else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
@@ -10443,8 +10580,8 @@
pw.print(prefix);
pw.print(" ");
pw.print("oom: max="); pw.print(r.maxAdj);
- pw.print(" hidden="); pw.print(r.hiddenAdj);
- pw.print(" client="); pw.print(r.clientHiddenAdj);
+ pw.print(" cached="); pw.print(r.cachedAdj);
+ pw.print(" client="); pw.print(r.clientCachedAdj);
pw.print(" empty="); pw.print(r.emptyAdj);
pw.print(" curRaw="); pw.print(r.curRawAdj);
pw.print(" setRaw="); pw.print(r.setRawAdj);
@@ -10453,7 +10590,7 @@
pw.print(prefix);
pw.print(" ");
pw.print("keeping="); pw.print(r.keeping);
- pw.print(" hidden="); pw.print(r.hidden);
+ pw.print(" cached="); pw.print(r.cached);
pw.print(" empty="); pw.print(r.empty);
pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
@@ -10665,13 +10802,13 @@
ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
- ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
+ ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MAX_ADJ
};
static final String[] DUMP_MEM_OOM_LABEL = new String[] {
"System", "Persistent", "Foreground",
"Visible", "Perceptible", "Heavy Weight",
"Backup", "A Services", "Home", "Previous",
- "B Services", "Background"
+ "B Services", "Cached"
};
final void dumpApplicationMemoryUsage(FileDescriptor fd,
@@ -10939,6 +11076,13 @@
return false;
}
+ final void dumpProcessTracker(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (this) {
+ pw.println("Process Stats:");
+ mProcessTracker.dumpLocked(fd, pw, args);
+ }
+ }
+
private final boolean removeDyingProviderLocked(ProcessRecord proc,
ContentProviderRecord cpr, boolean always) {
final boolean inLaunching = mLaunchingProviders.contains(cpr);
@@ -11584,7 +11728,7 @@
private final List getStickiesLocked(String action, IntentFilter filter,
List cur, int userId) {
final ContentResolver resolver = mContext.getContentResolver();
- HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+ ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
return cur;
}
@@ -12092,7 +12236,7 @@
// But first, if this is not a broadcast to all users, then
// make sure it doesn't conflict with an existing broadcast to
// all users.
- HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
+ ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
UserHandle.USER_ALL);
if (stickies != null) {
ArrayList<Intent> list = stickies.get(intent.getAction());
@@ -12109,9 +12253,9 @@
}
}
}
- HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+ ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
- stickies = new HashMap<String, ArrayList<Intent>>();
+ stickies = new ArrayMap<String, ArrayList<Intent>>();
mStickyBroadcasts.put(userId, stickies);
}
ArrayList<Intent> list = stickies.get(intent.getAction());
@@ -12364,7 +12508,7 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
+ ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies != null) {
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list != null) {
@@ -12857,18 +13001,18 @@
return null;
}
- private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj, int clientHiddenAdj,
+ private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, int clientCachedAdj,
int emptyAdj, ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
if (mAdjSeq == app.adjSeq) {
// This adjustment has already been computed. If we are calling
// from the top, we may have already computed our adjustment with
- // an earlier hidden adjustment that isn't really for us... if
- // so, use the new hidden adjustment.
- if (!recursed && app.hidden) {
+ // an earlier cached adjustment that isn't really for us... if
+ // so, use the new cached adjustment.
+ if (!recursed && app.cached) {
if (app.hasActivities) {
- app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj;
+ app.curAdj = app.curRawAdj = app.nonStoppingAdj = cachedAdj;
} else if (app.hasClientActivities) {
- app.curAdj = app.curRawAdj = app.nonStoppingAdj = clientHiddenAdj;
+ app.curAdj = app.curRawAdj = app.nonStoppingAdj = clientCachedAdj;
} else {
app.curAdj = app.curRawAdj = app.nonStoppingAdj = emptyAdj;
}
@@ -12879,14 +13023,14 @@
if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- return (app.curAdj=app.curRawAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
+ return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
}
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
app.empty = false;
- app.hidden = false;
+ app.cached = false;
app.hasClientActivities = false;
final int activitiesSize = app.activities.size();
@@ -12964,12 +13108,12 @@
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.adjType = "exec-service";
} else {
- // Assume process is hidden (has activities); we will correct
+ // Assume process is cached (has activities); we will correct
// later if this is not the case.
- adj = hiddenAdj;
+ adj = cachedAdj;
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- app.hidden = true;
- app.adjType = "bg-act";
+ app.cached = true;
+ app.adjType = "cch-act";
}
boolean hasStoppingActivities = false;
@@ -12985,7 +13129,7 @@
app.adjType = "visible";
}
schedGroup = Process.THREAD_GROUP_DEFAULT;
- app.hidden = false;
+ app.cached = false;
app.hasActivities = true;
foregroundActivities = true;
break;
@@ -12994,13 +13138,13 @@
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pausing";
}
- app.hidden = false;
+ app.cached = false;
foregroundActivities = true;
} else if (r.state == ActivityState.STOPPING) {
// We will apply the actual adjustment later, because
// we want to allow this process to immediately go through
// any memory trimming that is in effect.
- app.hidden = false;
+ app.cached = false;
foregroundActivities = true;
hasStoppingActivities = true;
}
@@ -13010,16 +13154,16 @@
}
}
- if (adj == hiddenAdj && !app.hasActivities) {
+ if (adj == cachedAdj && !app.hasActivities) {
if (app.hasClientActivities) {
- adj = clientHiddenAdj;
- app.adjType = "bg-client-act";
+ adj = clientCachedAdj;
+ app.adjType = "cch-client-act";
} else {
// Whoops, this process is completely empty as far as we know
// at this point.
adj = emptyAdj;
app.empty = true;
- app.adjType = "bg-empty";
+ app.adjType = "cch-empty";
}
}
@@ -13027,13 +13171,13 @@
if (app.foregroundServices) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.hidden = false;
+ app.cached = false;
app.adjType = "fg-service";
schedGroup = Process.THREAD_GROUP_DEFAULT;
} else if (app.forcingToForeground != null) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.hidden = false;
+ app.cached = false;
app.adjType = "force-fg";
app.adjSource = app.forcingToForeground;
schedGroup = Process.THREAD_GROUP_DEFAULT;
@@ -13048,7 +13192,7 @@
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- app.hidden = false;
+ app.cached = false;
app.adjType = "heavy";
}
@@ -13057,7 +13201,7 @@
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- app.hidden = false;
+ app.cached = false;
app.adjType = "home";
}
@@ -13068,7 +13212,7 @@
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- app.hidden = false;
+ app.cached = false;
app.adjType = "previous";
}
@@ -13088,7 +13232,7 @@
if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
adj = ProcessList.BACKUP_APP_ADJ;
app.adjType = "backup";
- app.hidden = false;
+ app.cached = false;
}
}
@@ -13107,7 +13251,7 @@
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > ProcessList.SERVICE_ADJ) {
- app.adjType = "started-bg-ui-services";
+ app.adjType = "cch-started-ui-services";
}
} else {
if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
@@ -13117,14 +13261,14 @@
if (adj > ProcessList.SERVICE_ADJ) {
adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
- app.hidden = false;
+ app.cached = false;
}
}
// If we have let the service slide into the background
// state, still have some text describing what it is doing
// even though the service no longer has an impact.
if (adj > ProcessList.SERVICE_ADJ) {
- app.adjType = "started-bg-services";
+ app.adjType = "cch-started-services";
}
}
// Don't kill this process because it is doing work; it
@@ -13150,20 +13294,20 @@
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
int clientAdj = adj;
- int myHiddenAdj = hiddenAdj;
- if (myHiddenAdj > client.hiddenAdj) {
- if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
- myHiddenAdj = client.hiddenAdj;
+ int myCachedAdj = cachedAdj;
+ if (myCachedAdj > client.cachedAdj) {
+ if (client.cachedAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ myCachedAdj = client.cachedAdj;
} else {
- myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+ myCachedAdj = ProcessList.VISIBLE_APP_ADJ;
}
}
- int myClientHiddenAdj = clientHiddenAdj;
- if (myClientHiddenAdj > client.clientHiddenAdj) {
- if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
- myClientHiddenAdj = client.clientHiddenAdj;
+ int myClientCachedAdj = clientCachedAdj;
+ if (myClientCachedAdj > client.clientCachedAdj) {
+ if (client.clientCachedAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ myClientCachedAdj = client.clientCachedAdj;
} else {
- myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+ myClientCachedAdj = ProcessList.VISIBLE_APP_ADJ;
}
}
int myEmptyAdj = emptyAdj;
@@ -13174,8 +13318,8 @@
myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
}
}
- clientAdj = computeOomAdjLocked(client, myHiddenAdj,
- myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+ clientAdj = computeOomAdjLocked(client, myCachedAdj,
+ myClientCachedAdj, myEmptyAdj, TOP_APP, true, doingAll);
String adjType = null;
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
@@ -13186,9 +13330,9 @@
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
if (adj > clientAdj) {
- adjType = "bound-bg-ui-services";
+ adjType = "cch-bound-ui-services";
}
- app.hidden = false;
+ app.cached = false;
clientAdj = adj;
} else {
if (now >= (s.lastActivity
@@ -13199,7 +13343,7 @@
// it around. We'll also tag it with a label just
// to help debug and undertand what is going on.
if (adj > clientAdj) {
- adjType = "bound-bg-services";
+ adjType = "cch-bound-services";
}
clientAdj = adj;
}
@@ -13210,7 +13354,7 @@
// created, then we want to try to better follow
// its memory management semantics for activities.
// That is, if it is sitting in the background
- // LRU list as a hidden process (with activities),
+ // LRU list as a cached process (with activities),
// we don't want the service it is connected to
// to go into the empty LRU and quickly get killed,
// because I'll we'll do is just end up restarting
@@ -13228,7 +13372,7 @@
// memory.
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adjType = "bound-bg-ui-services";
+ adjType = "cch-bound-ui-services";
} else {
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
@@ -13245,8 +13389,8 @@
adj = ProcessList.VISIBLE_APP_ADJ;
}
}
- if (!client.hidden) {
- app.hidden = false;
+ if (!client.cached) {
+ app.cached = false;
}
if (client.keeping) {
app.keeping = true;
@@ -13277,7 +13421,7 @@
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
- app.hidden = false;
+ app.cached = false;
app.adjType = "service";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
@@ -13295,10 +13439,10 @@
// application from running. By default we put the process in
// with the rest of the background processes; as we scan through
// its services we may bump it up from there.
- if (adj > hiddenAdj) {
- adj = hiddenAdj;
- app.hidden = false;
- app.adjType = "bg-services";
+ if (adj > cachedAdj) {
+ adj = cachedAdj;
+ app.cached = false;
+ app.adjType = "cch-services";
}
}
@@ -13317,20 +13461,20 @@
// Being our own client is not interesting.
continue;
}
- int myHiddenAdj = hiddenAdj;
- if (myHiddenAdj > client.hiddenAdj) {
- if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
- myHiddenAdj = client.hiddenAdj;
+ int myCachedAdj = cachedAdj;
+ if (myCachedAdj > client.cachedAdj) {
+ if (client.cachedAdj > ProcessList.FOREGROUND_APP_ADJ) {
+ myCachedAdj = client.cachedAdj;
} else {
- myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
+ myCachedAdj = ProcessList.FOREGROUND_APP_ADJ;
}
}
- int myClientHiddenAdj = clientHiddenAdj;
- if (myClientHiddenAdj > client.clientHiddenAdj) {
- if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- myClientHiddenAdj = client.clientHiddenAdj;
+ int myClientCachedAdj = clientCachedAdj;
+ if (myClientCachedAdj > client.clientCachedAdj) {
+ if (client.clientCachedAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ myClientCachedAdj = client.clientCachedAdj;
} else {
- myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
+ myClientCachedAdj = ProcessList.FOREGROUND_APP_ADJ;
}
}
int myEmptyAdj = emptyAdj;
@@ -13341,19 +13485,19 @@
myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
}
}
- int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
- myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+ int clientAdj = computeOomAdjLocked(client, myCachedAdj,
+ myClientCachedAdj, myEmptyAdj, TOP_APP, true, doingAll);
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- app.adjType = "bg-ui-provider";
+ app.adjType = "cch-ui-provider";
} else {
adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
app.adjType = "provider";
}
- if (!client.hidden) {
- app.hidden = false;
+ if (!client.cached) {
+ app.cached = false;
}
if (client.keeping) {
app.keeping = true;
@@ -13375,7 +13519,7 @@
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
- app.hidden = false;
+ app.cached = false;
app.keeping = true;
app.adjType = "provider";
app.adjTarget = cpr.name;
@@ -13415,7 +13559,7 @@
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
- if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
app.keeping = true;
}
@@ -13431,9 +13575,9 @@
adj = ProcessList.VISIBLE_APP_ADJ;
} else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
- adj = ProcessList.HIDDEN_APP_MIN_ADJ;
- } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
+ } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
+ adj = ProcessList.CACHED_APP_MIN_ADJ;
+ } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
adj++;
}
}
@@ -13447,7 +13591,7 @@
// interesting in this process then we will push it to the
// background importance.
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- } else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ } else if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
} else if (adj >= ProcessList.SERVICE_B_ADJ) {
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
@@ -13753,10 +13897,10 @@
}
}
- private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj,
- int clientHiddenAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
- app.hiddenAdj = hiddenAdj;
- app.clientHiddenAdj = clientHiddenAdj;
+ private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
+ int clientCachedAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
+ app.cachedAdj = cachedAdj;
+ app.clientCachedAdj = clientCachedAdj;
app.emptyAdj = emptyAdj;
if (app.thread == null) {
@@ -13767,7 +13911,7 @@
boolean success = true;
- computeOomAdjLocked(app, hiddenAdj, clientHiddenAdj, emptyAdj, TOP_APP, false, doingAll);
+ computeOomAdjLocked(app, cachedAdj, clientCachedAdj, emptyAdj, TOP_APP, false, doingAll);
if (app.curRawAdj != app.setRawAdj) {
if (wasKeeping && !app.keeping) {
@@ -13791,6 +13935,10 @@
TAG, "Set " + app.pid + " " + app.processName +
" adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
+ if (app.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ app.tracker.setState(mProcessList.adjToTrackedState(app.setAdj),
+ SystemClock.uptimeMillis());
+ }
} else {
success = false;
Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
@@ -13842,17 +13990,17 @@
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
int curAdj = app.curAdj;
- final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
- && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
+ final boolean wasCached = curAdj >= ProcessList.CACHED_APP_MIN_ADJ
+ && curAdj <= ProcessList.CACHED_APP_MAX_ADJ;
mAdjSeq++;
- boolean success = updateOomAdjLocked(app, app.hiddenAdj, app.clientHiddenAdj,
+ boolean success = updateOomAdjLocked(app, app.cachedAdj, app.clientCachedAdj,
app.emptyAdj, TOP_APP, false);
- final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
- && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
- if (nowHidden != wasHidden) {
- // Changed to/from hidden state, so apps after it in the LRU
+ final boolean nowCached = app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
+ && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ;
+ if (nowCached != wasCached) {
+ // Changed to/from cached state, so apps after it in the LRU
// list may also be changed.
updateOomAdjLocked();
}
@@ -13874,100 +14022,100 @@
mNewNumServiceProcs = 0;
final int emptyProcessLimit;
- final int hiddenProcessLimit;
+ final int cachedProcessLimit;
if (mProcessLimit <= 0) {
- emptyProcessLimit = hiddenProcessLimit = 0;
+ emptyProcessLimit = cachedProcessLimit = 0;
} else if (mProcessLimit == 1) {
emptyProcessLimit = 1;
- hiddenProcessLimit = 0;
+ cachedProcessLimit = 0;
} else {
emptyProcessLimit = (mProcessLimit*2)/3;
- hiddenProcessLimit = mProcessLimit - emptyProcessLimit;
+ cachedProcessLimit = mProcessLimit - emptyProcessLimit;
}
// Let's determine how many processes we have running vs.
// how many slots we have for background processes; we may want
// to put multiple processes in a slot of there are enough of
// them.
- int numSlots = (ProcessList.HIDDEN_APP_MAX_ADJ
- - ProcessList.HIDDEN_APP_MIN_ADJ + 1) / 2;
- int numEmptyProcs = mLruProcesses.size()-mNumNonHiddenProcs-mNumHiddenProcs;
- if (numEmptyProcs > hiddenProcessLimit) {
- // If there are more empty processes than our limit on hidden
- // processes, then use the hidden process limit for the factor.
+ int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
+ - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
+ int numEmptyProcs = mLruProcesses.size()- mNumNonCachedProcs - mNumCachedProcs;
+ if (numEmptyProcs > cachedProcessLimit) {
+ // If there are more empty processes than our limit on cached
+ // processes, then use the cached process limit for the factor.
// This ensures that the really old empty processes get pushed
// down to the bottom, so if we are running low on memory we will
- // have a better chance at keeping around more hidden processes
+ // have a better chance at keeping around more cached processes
// instead of a gazillion empty processes.
- numEmptyProcs = hiddenProcessLimit;
+ numEmptyProcs = cachedProcessLimit;
}
int emptyFactor = numEmptyProcs/numSlots;
if (emptyFactor < 1) emptyFactor = 1;
- int hiddenFactor = (mNumHiddenProcs > 0 ? mNumHiddenProcs : 1)/numSlots;
- if (hiddenFactor < 1) hiddenFactor = 1;
- int stepHidden = 0;
+ int cachedFactor = (mNumCachedProcs > 0 ? mNumCachedProcs : 1)/numSlots;
+ if (cachedFactor < 1) cachedFactor = 1;
+ int stepCached = 0;
int stepEmpty = 0;
- int numHidden = 0;
+ int numCached = 0;
int numEmpty = 0;
int numTrimming = 0;
- mNumNonHiddenProcs = 0;
- mNumHiddenProcs = 0;
+ mNumNonCachedProcs = 0;
+ mNumCachedProcs = 0;
// First update the OOM adjustment for each of the
// application processes based on their current state.
int i = mLruProcesses.size();
- int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
- int nextHiddenAdj = curHiddenAdj+1;
- int curEmptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
+ int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
+ int nextCachedAdj = curCachedAdj+1;
+ int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;
- int curClientHiddenAdj = curEmptyAdj;
+ int curClientCachedAdj = curEmptyAdj;
while (i > 0) {
i--;
ProcessRecord app = mLruProcesses.get(i);
- //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
- updateOomAdjLocked(app, curHiddenAdj, curClientHiddenAdj, curEmptyAdj, TOP_APP, true);
+ //Slog.i(TAG, "OOM " + app + ": cur cached=" + curCachedAdj);
+ updateOomAdjLocked(app, curCachedAdj, curClientCachedAdj, curEmptyAdj, TOP_APP, true);
if (!app.killedBackground) {
- if (app.curRawAdj == curHiddenAdj && app.hasActivities) {
- // This process was assigned as a hidden process... step the
- // hidden level.
- mNumHiddenProcs++;
- if (curHiddenAdj != nextHiddenAdj) {
- stepHidden++;
- if (stepHidden >= hiddenFactor) {
- stepHidden = 0;
- curHiddenAdj = nextHiddenAdj;
- nextHiddenAdj += 2;
- if (nextHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
- nextHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+ if (app.curRawAdj == curCachedAdj && app.hasActivities) {
+ // This process was assigned as a cached process... step the
+ // cached level.
+ mNumCachedProcs++;
+ if (curCachedAdj != nextCachedAdj) {
+ stepCached++;
+ if (stepCached >= cachedFactor) {
+ stepCached = 0;
+ curCachedAdj = nextCachedAdj;
+ nextCachedAdj += 2;
+ if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+ nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
- if (curClientHiddenAdj <= curHiddenAdj) {
- curClientHiddenAdj = curHiddenAdj + 1;
- if (curClientHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
- curClientHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+ if (curClientCachedAdj <= curCachedAdj) {
+ curClientCachedAdj = curCachedAdj + 1;
+ if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+ curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
}
- numHidden++;
- if (numHidden > hiddenProcessLimit) {
+ numCached++;
+ if (numCached > cachedProcessLimit) {
Slog.i(TAG, "No longer want " + app.processName
- + " (pid " + app.pid + "): hidden #" + numHidden);
+ + " (pid " + app.pid + "): cached #" + numCached);
EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
app.processName, app.setAdj, "too many background");
app.killedBackground = true;
Process.killProcessQuiet(app.pid);
}
- } else if (app.curRawAdj == curHiddenAdj && app.hasClientActivities) {
+ } else if (app.curRawAdj == curCachedAdj && app.hasClientActivities) {
// This process has a client that has activities. We will have
- // given it the current hidden adj; here we will just leave it
- // without stepping the hidden adj.
- curClientHiddenAdj++;
- if (curClientHiddenAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
- curClientHiddenAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+ // given it the current cached adj; here we will just leave it
+ // without stepping the cached adj.
+ curClientCachedAdj++;
+ if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+ curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
} else {
- if (app.curRawAdj == curEmptyAdj || app.curRawAdj == curHiddenAdj) {
+ if (app.curRawAdj == curEmptyAdj || app.curRawAdj == curCachedAdj) {
// This process was assigned as an empty process... step the
// empty level.
if (curEmptyAdj != nextEmptyAdj) {
@@ -13976,15 +14124,15 @@
stepEmpty = 0;
curEmptyAdj = nextEmptyAdj;
nextEmptyAdj += 2;
- if (nextEmptyAdj > ProcessList.HIDDEN_APP_MAX_ADJ) {
- nextEmptyAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
+ if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+ nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
- } else if (app.curRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
- mNumNonHiddenProcs++;
+ } else if (app.curRawAdj < ProcessList.CACHED_APP_MIN_ADJ) {
+ mNumNonCachedProcs++;
}
- if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
+ if (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
&& !app.hasClientActivities) {
if (numEmpty > ProcessList.TRIM_EMPTY_APPS
&& app.lastActivityTime < oldTime) {
@@ -14039,9 +14187,9 @@
// are managing to keep around is less than half the maximum we desire;
// if we are keeping a good number around, we'll let them use whatever
// memory they want.
- if (numHidden <= ProcessList.TRIM_HIDDEN_APPS
+ if (numCached <= ProcessList.TRIM_CACHED_APPS
&& numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
- final int numHiddenAndEmpty = numHidden + numEmpty;
+ final int numCachedAndEmpty = numCached + numEmpty;
final int N = mLruProcesses.size();
int factor = numTrimming/3;
int minFactor = 2;
@@ -14050,9 +14198,9 @@
if (factor < minFactor) factor = minFactor;
int step = 0;
int fgTrimLevel;
- if (numHiddenAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
+ if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
- } else if (numHiddenAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
+ } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
} else {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
@@ -14327,7 +14475,7 @@
}
if (proc == null) {
- HashMap<String, SparseArray<ProcessRecord>> all
+ ArrayMap<String, SparseArray<ProcessRecord>> all
= mProcessNames.getMap();
SparseArray<ProcessRecord> procs = all.get(process);
if (procs != null && procs.size() > 0) {
diff --git a/services/java/com/android/server/am/ActivityResult.java b/services/java/com/android/server/am/ActivityResult.java
index 12eba34..6d5bdeb 100644
--- a/services/java/com/android/server/am/ActivityResult.java
+++ b/services/java/com/android/server/am/ActivityResult.java
@@ -23,7 +23,7 @@
/**
* Pending result information to send back to an activity.
*/
-class ActivityResult extends ResultInfo {
+final class ActivityResult extends ResultInfo {
final ActivityRecord mFrom;
public ActivityResult(ActivityRecord from, String resultWho,
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 5e88d3b..5e6bdb1 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3334,13 +3334,17 @@
}
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
- boolean dumpClient, String dumpPackage, boolean needSep) {
+ boolean dumpClient, String dumpPackage, boolean needSep, String header) {
boolean printed = false;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
mTaskHistory.get(taskNdx).mActivities, " ", "Hist", true, !dumpAll,
- dumpClient, dumpPackage, needSep, " Task " + taskNdx + ": id #" + task.taskId);
+ dumpClient, dumpPackage, needSep, header,
+ " Task " + taskNdx + ": id #" + task.taskId);
+ if (printed) {
+ header = null;
+ }
}
return printed;
}
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index a638981..af61bfb 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -80,7 +80,7 @@
import java.util.ArrayList;
import java.util.List;
-public class ActivityStackSupervisor {
+public final class ActivityStackSupervisor {
static final boolean DEBUG = ActivityManagerService.DEBUG || false;
static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
static final boolean DEBUG_APP = DEBUG || false;
@@ -2209,6 +2209,8 @@
pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
pw.println(mDismissKeyguardOnNextActivity);
pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
+ pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
+ pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
@@ -2221,66 +2223,72 @@
if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
if (needSep) {
pw.println();
- needSep = false;
}
pw.print(prefix);
pw.println(activity);
+ return true;
}
}
- return needSep;
+ return false;
}
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage) {
+ boolean printed = false;
+ boolean needSep = false;
final int numStacks = mStacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
- if (stackNdx != 0) {
- pw.println();
- }
- pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
- stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, false);
- dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
- dumpPackage, true, " Running activities (most recent first):");
+ StringBuilder stackHeader = new StringBuilder(128);
+ stackHeader.append(" Stack #");
+ stackHeader.append(mStacks.indexOf(stack));
+ stackHeader.append(":");
+ printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
+ stackHeader.toString());
+ printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
+ false, dumpPackage, true, " Running activities (most recent first):", null);
- boolean needSep = true;
- needSep = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+ needSep = printed;
+ boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
" mPausingActivity: ");
- needSep = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
" mResumedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
if (dumpAll) {
- printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+ pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
" mLastPausedActivity: ");
+ if (pr) {
+ printed = true;
+ }
}
+ needSep = printed;
}
- dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
- dumpPackage, true, " Activities waiting to finish:");
- dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
- dumpPackage, true, " Activities waiting to stop:");
- dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting for another to become visible:");
- dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
- dumpPackage, true, " Activities waiting to sleep:");
- dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
- dumpPackage, true, " Activities waiting to sleep:");
+ printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to finish:", null);
+ printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to stop:", null);
+ printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting for another to become visible:",
+ null);
+ printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to sleep:", null);
+ printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to sleep:", null);
- if (dumpPackage == null) {
- pw.println();
- pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
- if (dumpAll) {
- pw.println(" mSleepTimeout: " + mSleepTimeout);
- }
- if (dumpAll) {
- pw.println(" mCurTaskId: " + mCurTaskId);
- }
- }
- return true;
+ return printed;
}
static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
String prefix, String label, boolean complete, boolean brief, boolean client,
- String dumpPackage, boolean needNL, String header) {
+ String dumpPackage, boolean needNL, String header1, String header2) {
TaskRecord lastTask = null;
String innerPrefix = null;
String[] args = null;
@@ -2300,9 +2308,13 @@
pw.println("");
needNL = false;
}
- if (header != null) {
- pw.println(header);
- header = null;
+ if (header1 != null) {
+ pw.println(header1);
+ header1 = null;
+ }
+ if (header2 != null) {
+ pw.println(header2);
+ header2 = null;
}
if (lastTask != r.task) {
lastTask = r.task;
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java
index f1c54fa..06265fd 100644
--- a/services/java/com/android/server/am/AppBindRecord.java
+++ b/services/java/com/android/server/am/AppBindRecord.java
@@ -23,7 +23,7 @@
/**
* An association between a service and one of its client applications.
*/
-class AppBindRecord {
+final class AppBindRecord {
final ServiceRecord service; // The running service.
final IntentBindRecord intent; // The intent we are bound to.
final ProcessRecord client; // Who has started/bound the service.
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index ffa1e92..bfc86b0 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -25,7 +25,7 @@
import android.os.Message;
import android.view.WindowManager;
-class AppErrorDialog extends BaseErrorDialog {
+final class AppErrorDialog extends BaseErrorDialog {
private final ActivityManagerService mService;
private final AppErrorResult mResult;
private final ProcessRecord mProc;
diff --git a/services/java/com/android/server/am/AppErrorResult.java b/services/java/com/android/server/am/AppErrorResult.java
index ebfcfe2..c6a5720 100644
--- a/services/java/com/android/server/am/AppErrorResult.java
+++ b/services/java/com/android/server/am/AppErrorResult.java
@@ -16,8 +16,7 @@
package com.android.server.am;
-
-class AppErrorResult {
+final class AppErrorResult {
public void set(int res) {
synchronized (this) {
mHasResult = true;
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index af61c9b..b5e0715 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -28,7 +28,7 @@
import android.util.Slog;
import android.view.WindowManager;
-class AppNotRespondingDialog extends BaseErrorDialog {
+final class AppNotRespondingDialog extends BaseErrorDialog {
private static final String TAG = "AppNotRespondingDialog";
// Event 'what' codes
diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index d08bb10..27865a8 100644
--- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -22,7 +22,7 @@
import android.os.Message;
import android.view.WindowManager;
-class AppWaitingForDebuggerDialog extends BaseErrorDialog {
+final class AppWaitingForDebuggerDialog extends BaseErrorDialog {
final ActivityManagerService mService;
final ProcessRecord mProc;
private CharSequence mAppName;
diff --git a/services/java/com/android/server/am/BackupRecord.java b/services/java/com/android/server/am/BackupRecord.java
index 7e73106..5fa7e6a 100644
--- a/services/java/com/android/server/am/BackupRecord.java
+++ b/services/java/com/android/server/am/BackupRecord.java
@@ -21,7 +21,7 @@
import android.content.pm.ApplicationInfo;
/** @hide */
-class BackupRecord {
+final class BackupRecord {
// backup/restore modes
public static final int BACKUP_NORMAL = 0;
public static final int BACKUP_FULL = 1;
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 9b3fbe9..5a15f0b 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -431,6 +431,7 @@
}
}
+ @Override
public void noteNetworkInterfaceType(String iface, int type) {
enforceCallingPermission();
synchronized (mStats) {
@@ -438,6 +439,14 @@
}
}
+ @Override
+ public void noteNetworkStatsEnabled() {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteNetworkStatsEnabledLocked();
+ }
+ }
+
public boolean isOnBattery() {
return mStats.isOnBattery();
}
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index c631b6e..986b8ea 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -22,7 +22,7 @@
import java.io.PrintWriter;
-class BroadcastFilter extends IntentFilter {
+final class BroadcastFilter extends IntentFilter {
// Back-pointer to the list this filter is in.
final ReceiverList receiverList;
final String packageName;
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index ac7eb89..c7e6010 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -47,7 +47,7 @@
* We keep two broadcast queues and associated bookkeeping, one for those at
* foreground priority, and one for normal (background-priority) broadcasts.
*/
-public class BroadcastQueue {
+public final class BroadcastQueue {
static final String TAG = "BroadcastQueue";
static final String TAG_MU = ActivityManagerService.TAG_MU;
static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST;
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index 83cc0ea..eb1df6e 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -36,7 +36,7 @@
/**
* An active intent broadcast.
*/
-class BroadcastRecord extends Binder {
+final class BroadcastRecord extends Binder {
final Intent intent; // the original intent that generated us
final ComponentName targetComp; // original component name set on the intent
final ProcessRecord callerApp; // process that sent this
diff --git a/services/java/com/android/server/am/CompatModeDialog.java b/services/java/com/android/server/am/CompatModeDialog.java
index 0442bda..202cc7c 100644
--- a/services/java/com/android/server/am/CompatModeDialog.java
+++ b/services/java/com/android/server/am/CompatModeDialog.java
@@ -28,7 +28,7 @@
import android.widget.CompoundButton;
import android.widget.Switch;
-public class CompatModeDialog extends Dialog {
+public final class CompatModeDialog extends Dialog {
final ActivityManagerService mService;
final ApplicationInfo mAppInfo;
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index e697f88..f56371c 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -25,7 +25,7 @@
import android.util.Slog;
import android.util.Xml;
-public class CompatModePackages {
+public final class CompatModePackages {
private final String TAG = ActivityManagerService.TAG;
private final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 4ed3c31..dd81493 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -25,7 +25,7 @@
/**
* Description of a single binding to a service.
*/
-class ConnectionRecord {
+final class ConnectionRecord {
final AppBindRecord binding; // The application/service binding.
final ActivityRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
diff --git a/services/java/com/android/server/am/ContentProviderConnection.java b/services/java/com/android/server/am/ContentProviderConnection.java
index 7f69b24..f2c9e2f 100644
--- a/services/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/java/com/android/server/am/ContentProviderConnection.java
@@ -23,7 +23,7 @@
/**
* Represents a link between a content provider and client.
*/
-public class ContentProviderConnection extends Binder {
+public final class ContentProviderConnection extends Binder {
public final ContentProviderRecord provider;
public final ProcessRecord client;
public final long createTime;
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 8fb6a93..646b7d2 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -33,7 +33,7 @@
import java.util.HashMap;
import java.util.HashSet;
-class ContentProviderRecord {
+final class ContentProviderRecord {
final ActivityManagerService service;
public final ProviderInfo info;
final int uid;
diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/java/com/android/server/am/CoreSettingsObserver.java
index 585cf2b..10ea67c 100644
--- a/services/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/java/com/android/server/am/CoreSettingsObserver.java
@@ -33,7 +33,7 @@
* disk I/O operations. Note: This class assumes that all core settings reside
* in {@link Settings.Secure}.
*/
-class CoreSettingsObserver extends ContentObserver {
+final class CoreSettingsObserver extends ContentObserver {
private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
// mapping form property name to its type
diff --git a/services/java/com/android/server/am/DeviceMonitor.java b/services/java/com/android/server/am/DeviceMonitor.java
deleted file mode 100644
index 21e7252..0000000
--- a/services/java/com/android/server/am/DeviceMonitor.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.os.SELinux;
-import android.util.Slog;
-
-import java.io.*;
-import java.util.Arrays;
-
-/**
- * Monitors device resources periodically for some period of time. Useful for
- * tracking down performance problems.
- */
-class DeviceMonitor {
-
- private static final String LOG_TAG = DeviceMonitor.class.getName();
-
- /** Number of samples to take. */
- private static final int SAMPLE_COUNT = 10;
-
- /** Time to wait in ms between samples. */
- private static final int INTERVAL = 1000;
-
- /** Time to wait in ms between samples. */
- private static final int MAX_FILES = 30;
-
- private final byte[] buffer = new byte[1024];
-
- /** Is the monitor currently running? */
- private boolean running = false;
-
- private DeviceMonitor() {
- new Thread() {
- public void run() {
- monitor();
- }
- }.start();
- }
-
- /**
- * Loops continuously. Pauses until someone tells us to start monitoring.
- */
- @SuppressWarnings("InfiniteLoopStatement")
- private void monitor() {
- while (true) {
- waitForStart();
-
- purge();
-
- for (int i = 0; i < SAMPLE_COUNT; i++) {
- try {
- dump();
- } catch (IOException e) {
- Slog.w(LOG_TAG, "Dump failed.", e);
- }
- pause();
- }
-
- stop();
- }
- }
-
- private static final File PROC = new File("/proc");
- private static final File BASE = new File("/data/anr/");
- static {
- if (!BASE.isDirectory() && !BASE.mkdirs()) {
- throw new AssertionError("Couldn't create " + BASE + ".");
- }
- if (!SELinux.restorecon(BASE)) {
- throw new AssertionError("Couldn't restorecon " + BASE + ".");
- }
- }
-
- private static final File[] PATHS = {
- new File(PROC, "zoneinfo"),
- new File(PROC, "interrupts"),
- new File(PROC, "meminfo"),
- new File(PROC, "slabinfo"),
- };
-
-
- /**
- * Deletes old files.
- */
- private void purge() {
- File[] files = BASE.listFiles();
- int count = files.length - MAX_FILES;
- if (count > 0) {
- Arrays.sort(files);
- for (int i = 0; i < count; i++) {
- if (!files[i].delete()) {
- Slog.w(LOG_TAG, "Couldn't delete " + files[i] + ".");
- }
- }
- }
- }
-
- /**
- * Dumps the current device stats to a new file.
- */
- private void dump() throws IOException {
- OutputStream out = new FileOutputStream(
- new File(BASE, String.valueOf(System.currentTimeMillis())));
- try {
- // Copy /proc/*/stat
- for (File processDirectory : PROC.listFiles()) {
- if (isProcessDirectory(processDirectory)) {
- dump(new File(processDirectory, "stat"), out);
- }
- }
-
- // Copy other files.
- for (File file : PATHS) {
- dump(file, out);
- }
- } finally {
- closeQuietly(out);
- }
- }
-
- /**
- * Returns true if the given file represents a process directory.
- */
- private static boolean isProcessDirectory(File file) {
- try {
- Integer.parseInt(file.getName());
- return file.isDirectory();
- } catch (NumberFormatException e) {
- return false;
- }
- }
-
- /**
- * Copies from a file to an output stream.
- */
- private void dump(File from, OutputStream out) throws IOException {
- writeHeader(from, out);
-
- FileInputStream in = null;
- try {
- in = new FileInputStream(from);
- int count;
- while ((count = in.read(buffer)) != -1) {
- out.write(buffer, 0, count);
- }
- } finally {
- closeQuietly(in);
- }
- }
-
- /**
- * Writes a header for the given file.
- */
- private static void writeHeader(File file, OutputStream out)
- throws IOException {
- String header = "*** " + file.toString() + "\n";
- out.write(header.getBytes());
- }
-
- /**
- * Closes the given resource. Logs exceptions.
- * @param closeable
- */
- private static void closeQuietly(Closeable closeable) {
- try {
- if (closeable != null) {
- closeable.close();
- }
- } catch (IOException e) {
- Slog.w(LOG_TAG, e);
- }
- }
-
- /**
- * Pauses momentarily before we start the next dump.
- */
- private void pause() {
- try {
- Thread.sleep(INTERVAL);
- } catch (InterruptedException e) { /* ignore */ }
- }
-
- /**
- * Stops dumping.
- */
- private synchronized void stop() {
- running = false;
- }
-
- /**
- * Waits until someone starts us.
- */
- private synchronized void waitForStart() {
- while (!running) {
- try {
- wait();
- } catch (InterruptedException e) { /* ignore */ }
- }
- }
-
- /**
- * Instructs the monitoring to start if it hasn't already.
- */
- private synchronized void startMonitoring() {
- if (!running) {
- running = true;
- notifyAll();
- }
- }
-
- private static DeviceMonitor instance = new DeviceMonitor();
-
- /**
- * Starts monitoring if it hasn't started already.
- */
- static void start() {
- instance.startMonitoring();
- }
-}
diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java
index 0ffb588..f4632c13 100644
--- a/services/java/com/android/server/am/FactoryErrorDialog.java
+++ b/services/java/com/android/server/am/FactoryErrorDialog.java
@@ -22,7 +22,7 @@
import android.os.Message;
import android.view.WindowManager;
-class FactoryErrorDialog extends BaseErrorDialog {
+final class FactoryErrorDialog extends BaseErrorDialog {
public FactoryErrorDialog(Context context, CharSequence msg) {
super(context);
setCancelable(false);
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index 0a92964..6c84b9f 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -27,7 +27,7 @@
/**
* A particular Intent that has been bound to a Service.
*/
-class IntentBindRecord {
+final class IntentBindRecord {
/** The running service. */
final ServiceRecord service;
/** The intent that is bound.*/
diff --git a/services/java/com/android/server/am/LaunchWarningWindow.java b/services/java/com/android/server/am/LaunchWarningWindow.java
index cb2b7bb..30c3066 100644
--- a/services/java/com/android/server/am/LaunchWarningWindow.java
+++ b/services/java/com/android/server/am/LaunchWarningWindow.java
@@ -26,7 +26,7 @@
import android.widget.ImageView;
import android.widget.TextView;
-public class LaunchWarningWindow extends Dialog {
+public final class LaunchWarningWindow extends Dialog {
public LaunchWarningWindow(Context context, ActivityRecord cur, ActivityRecord next) {
super(context, R.style.Theme_Toast);
diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/java/com/android/server/am/NativeCrashListener.java
index a9454bd..307ab03 100644
--- a/services/java/com/android/server/am/NativeCrashListener.java
+++ b/services/java/com/android/server/am/NativeCrashListener.java
@@ -40,7 +40,7 @@
*
* Note that this component runs in a separate thread.
*/
-class NativeCrashListener extends Thread {
+final class NativeCrashListener extends Thread {
static final String TAG = "NativeCrashListener";
static final boolean DEBUG = false;
static final boolean MORE_DEBUG = DEBUG && false;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 28593fe..17f24a9 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -31,7 +31,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-class PendingIntentRecord extends IIntentSender.Stub {
+final class PendingIntentRecord extends IIntentSender.Stub {
final ActivityManagerService owner;
final Key key;
final int uid;
diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/java/com/android/server/am/PendingThumbnailsRecord.java
index c460791..e4eb4d0 100644
--- a/services/java/com/android/server/am/PendingThumbnailsRecord.java
+++ b/services/java/com/android/server/am/PendingThumbnailsRecord.java
@@ -24,7 +24,7 @@
* This class keeps track of calls to getTasks() that are still
* waiting for thumbnail images.
*/
-class PendingThumbnailsRecord
+final class PendingThumbnailsRecord
{
final IThumbnailReceiver receiver; // who is waiting.
final HashSet<ActivityRecord> pendingRecords; // HistoryRecord objects we still wait for.
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index 1a635a9a..e937d35 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -29,7 +29,7 @@
/**
* Activity manager code dealing with processes.
*/
-class ProcessList {
+final class ProcessList {
// The minimum time we allow between crashes, for us to consider this
// application to be bad and stop and its services and reject broadcasts.
static final int MIN_CRASH_INTERVAL = 60*1000;
@@ -38,8 +38,8 @@
// This is a process only hosting activities that are not visible,
// so it can be killed without any disruption.
- static final int HIDDEN_APP_MAX_ADJ = 15;
- static int HIDDEN_APP_MIN_ADJ = 9;
+ static final int CACHED_APP_MAX_ADJ = 15;
+ static int CACHED_APP_MIN_ADJ = 9;
// The B list of SERVICE_ADJ -- these are the old and decrepit
// services that aren't as shiny and interesting as the ones in the A list.
@@ -94,37 +94,37 @@
// Memory pages are 4K.
static final int PAGE_SIZE = 4*1024;
- // The minimum number of hidden apps we want to be able to keep around,
+ // The minimum number of cached apps we want to be able to keep around,
// without empty apps being able to push them out of memory.
- static final int MIN_HIDDEN_APPS = 2;
+ static final int MIN_CACHED_APPS = 2;
- // The maximum number of hidden processes we will keep around before
+ // The maximum number of cached processes we will keep around before
// killing them; this is just a control to not let us go too crazy with
// keeping around processes on devices with large amounts of RAM.
- static final int MAX_HIDDEN_APPS = 24;
+ static final int MAX_CACHED_APPS = 24;
// We allow empty processes to stick around for at most 30 minutes.
static final long MAX_EMPTY_TIME = 30*60*1000;
- // The number of hidden at which we don't consider it necessary to do
+ // The number of cached at which we don't consider it necessary to do
// memory trimming.
- static final int TRIM_HIDDEN_APPS = 3;
+ static final int TRIM_CACHED_APPS = 3;
// The number of empty apps at which we don't consider it necessary to do
// memory trimming.
static final int TRIM_EMPTY_APPS = 3;
- // Threshold of number of hidden+empty where we consider memory critical.
+ // Threshold of number of cached+empty where we consider memory critical.
static final int TRIM_CRITICAL_THRESHOLD = 3;
- // Threshold of number of hidden+empty where we consider memory critical.
+ // Threshold of number of cached+empty where we consider memory critical.
static final int TRIM_LOW_THRESHOLD = 5;
- // We put empty content processes after any hidden processes that have
+ // We put empty content processes after any cached processes that have
// been idle for less than 15 seconds.
static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
- // We put empty content processes after any hidden processes that have
+ // We put empty content processes after any cached processes that have
// been idle for less than 120 seconds.
static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
@@ -133,7 +133,7 @@
// can't give it a different value for every possible kind of process.
private final int[] mOomAdj = new int[] {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
- BACKUP_APP_ADJ, HIDDEN_APP_MIN_ADJ, HIDDEN_APP_MAX_ADJ
+ BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
};
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
@@ -154,11 +154,34 @@
private boolean mHaveDisplaySize;
+ private final int[] mAdjToTrackedState = new int[CACHED_APP_MAX_ADJ+1];
+
ProcessList() {
MemInfoReader minfo = new MemInfoReader();
minfo.readMemInfo();
mTotalMemMb = minfo.getTotalSize()/(1024*1024);
updateOomLevels(0, 0, false);
+ for (int i=0; i<=CACHED_APP_MAX_ADJ; i++) {
+ if (i <= FOREGROUND_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_FOREGROUND;
+ } else if (i <= VISIBLE_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_VISIBLE;
+ } else if (i <= PERCEPTIBLE_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_PERCEPTIBLE;
+ } else if (i <= BACKUP_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_BACKUP;
+ } else if (i <= SERVICE_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_SERVICE;
+ } else if (i <= HOME_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_HOME;
+ } else if (i <= PREVIOUS_APP_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_PREVIOUS;
+ } else if (i <= SERVICE_B_ADJ) {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_SERVICE;
+ } else {
+ mAdjToTrackedState[i] = ProcessTracker.STATE_CACHED;
+ }
+ }
}
void applyDisplaySize(WindowManagerService wm) {
@@ -220,6 +243,10 @@
return mOomMinFree[mOomAdj.length-1] * 1024;
}
+ int adjToTrackedState(int adj) {
+ return mAdjToTrackedState[adj];
+ }
+
private void writeFile(String path, String data) {
FileOutputStream fos = null;
try {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 3a4a34c..6cae67c 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -44,13 +44,14 @@
* Full information about a particular process that
* is currently running.
*/
-class ProcessRecord {
+final class ProcessRecord {
final BatteryStatsImpl.Uid.Proc batteryStats; // where to collect runtime statistics
final ApplicationInfo info; // all about the first app in the process
final boolean isolated; // true if this is a special isolated process
final int uid; // uid of process; may be different from 'info' if isolated
final int userId; // user of process.
final String processName; // name of the process
+ final ProcessTracker.ProcessState tracker; // tracking execution of process
// List of packages running in the process
final HashSet<String> pkgList = new HashSet<String>();
IApplicationThread thread; // the actual proc... may be null only if
@@ -61,8 +62,8 @@
long lastActivityTime; // For managing the LRU list
long lruWeight; // Weight for ordering in LRU list
int maxAdj; // Maximum OOM adjustment for this process
- int hiddenAdj; // If hidden, this is the adjustment to use
- int clientHiddenAdj; // If empty but hidden client, this is the adjustment to use
+ int cachedAdj; // If cached, this is the adjustment to use
+ int clientCachedAdj; // If empty but cached client, this is the adjustment to use
int emptyAdj; // If empty, this is the adjustment to use
int curRawAdj; // Current OOM unlimited adjustment for this process
int setRawAdj; // Last set OOM unlimited adjustment for this process
@@ -108,7 +109,7 @@
long lastLowMemory; // When we last told the app that memory is low
boolean reportLowMemory; // Set to true when waiting to report low mem
boolean empty; // Is this an empty background process?
- boolean hidden; // Is this a hidden process?
+ boolean cached; // Is this a cached process?
int lastPss; // Last pss size reported by app.
String adjType; // Debugging: primary thing impacting oom_adj.
int adjTypeCode; // Debugging: adj code to report to app.
@@ -201,11 +202,11 @@
pw.print(" lruWeight="); pw.print(lruWeight);
pw.print(" serviceb="); pw.print(serviceb);
pw.print(" keeping="); pw.print(keeping);
- pw.print(" hidden="); pw.print(hidden);
+ pw.print(" cached="); pw.print(cached);
pw.print(" empty="); pw.println(empty);
pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
- pw.print(" hidden="); pw.print(hiddenAdj);
- pw.print(" client="); pw.print(clientHiddenAdj);
+ pw.print(" cached="); pw.print(cachedAdj);
+ pw.print(" client="); pw.print(clientCachedAdj);
pw.print(" empty="); pw.print(emptyAdj);
pw.print(" curRaw="); pw.print(curRawAdj);
pw.print(" setRaw="); pw.print(setRawAdj);
@@ -325,17 +326,19 @@
}
ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
- ApplicationInfo _info, String _processName, int _uid) {
+ ApplicationInfo _info, String _processName, int _uid,
+ ProcessTracker.ProcessState _tracker) {
batteryStats = _batteryStats;
info = _info;
isolated = _info.uid != _uid;
uid = _uid;
userId = UserHandle.getUserId(_uid);
processName = _processName;
+ tracker = _tracker;
pkgList.add(_info.packageName);
thread = _thread;
- maxAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
- hiddenAdj = clientHiddenAdj = emptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
+ maxAdj = ProcessList.CACHED_APP_MAX_ADJ;
+ cachedAdj = clientCachedAdj = emptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
curRawAdj = setRawAdj = -100;
curAdj = setAdj = -100;
persistent = false;
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
new file mode 100644
index 0000000..4eb71c7
--- /dev/null
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import com.android.server.ProcessMap;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public final class ProcessTracker {
+ public static final int STATE_NOTHING = -1;
+ public static final int STATE_TOP = 0;
+ public static final int STATE_FOREGROUND = 1;
+ public static final int STATE_VISIBLE = 2;
+ public static final int STATE_PERCEPTIBLE = 3;
+ public static final int STATE_BACKUP = 4;
+ public static final int STATE_SERVICE = 5;
+ public static final int STATE_HOME = 6;
+ public static final int STATE_PREVIOUS = 7;
+ public static final int STATE_CACHED = 8;
+ public static final int STATE_SCREEN_ON_MOD = STATE_CACHED+1;
+ public static final int STATE_COUNT = STATE_SCREEN_ON_MOD*2;
+
+ static String[] STATE_NAMES = new String[] {
+ "Top ", "Foreground ", "Visible ", "Perceptible", "Backup ",
+ "Service ", "Home ", "Previous ", "Cached "
+ };
+
+ public static final class ProcessState {
+ final long[] mTimes = new long[STATE_COUNT];
+ int mCurState = STATE_NOTHING;
+ long mStartTime;
+
+ public void setState(int state, long now) {
+ if (mCurState != STATE_NOTHING) {
+ mTimes[mCurState] += now - mStartTime;
+ }
+ mCurState = state;
+ mStartTime = now;
+ }
+ }
+
+ static final class State {
+ final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
+ }
+
+ final State mState = new State();
+
+ public ProcessTracker() {
+ }
+
+ public ProcessState getStateLocked(String name, int uid) {
+ ProcessState ps = mState.mProcesses.get(name, uid);
+ if (ps != null) {
+ return ps;
+ }
+ ps = new ProcessState();
+ mState.mProcesses.put(name, uid, ps);
+ return ps;
+ }
+
+ public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
+ final long now = SystemClock.uptimeMillis();
+ ArrayMap<String, SparseArray<ProcessState>> pmap = mState.mProcesses.getMap();
+ for (int ip=0; ip<pmap.size(); ip++) {
+ String procName = pmap.keyAt(ip);
+ SparseArray<ProcessState> procs = pmap.valueAt(ip);
+ for (int iu=0; iu<procs.size(); iu++) {
+ int uid = procs.keyAt(iu);
+ ProcessState state = procs.valueAt(iu);
+ pw.print(" "); pw.print(procName); pw.print(" / "); pw.print(uid); pw.println(":");
+ long totalTime = 0;
+ for (int is=0; is<STATE_NAMES.length; is++) {
+ long time = state.mTimes[is];
+ if (state.mCurState == is) {
+ time += now - state.mStartTime;
+ }
+ if (time != 0) {
+ pw.print(" "); pw.print(STATE_NAMES[is]); pw.print(": ");
+ TimeUtils.formatDuration(time, pw); pw.println();
+ totalTime += time;
+ }
+ }
+ if (totalTime != 0) {
+ pw.print(" TOTAL : ");
+ TimeUtils.formatDuration(totalTime, pw);
+ pw.println();
+ }
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 3249e1e..5759a44 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -35,7 +35,7 @@
* Keeps track of content providers by authority (name) and class. It separates the mapping by
* user and ones that are not user-specific (system providers).
*/
-public class ProviderMap {
+public final class ProviderMap {
private static final String TAG = "ProviderMap";
@@ -287,8 +287,7 @@
boolean needSep = false;
if (mSingletonByClass.size() > 0) {
- pw.println(" Published single-user content providers (by class):");
- needSep = dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+ needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
" Published single-user content providers (by class):", needSep,
mSingletonByClass);
}
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 9b6701e..b19cc5d 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -32,7 +32,7 @@
* A receiver object that has registered for one or more broadcasts.
* The ArrayList holds BroadcastFilter objects.
*/
-class ReceiverList extends ArrayList<BroadcastFilter>
+final class ReceiverList extends ArrayList<BroadcastFilter>
implements IBinder.DeathRecipient {
final ActivityManagerService owner;
public final IIntentReceiver receiver;
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 707e8ee..45e248b 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -47,7 +47,7 @@
/**
* A running application service.
*/
-class ServiceRecord extends Binder {
+final class ServiceRecord extends Binder {
// Maximum number of delivery attempts before giving up.
static final int MAX_DELIVERY_COUNT = 3;
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
index 35d50a1..b6d0daa 100644
--- a/services/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -25,7 +25,7 @@
import android.os.Message;
import android.util.Slog;
-class StrictModeViolationDialog extends BaseErrorDialog {
+final class StrictModeViolationDialog extends BaseErrorDialog {
private final static String TAG = "StrictModeViolationDialog";
private final ActivityManagerService mService;
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 58392ef..d79211c 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -33,7 +33,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-class TaskRecord extends ThumbnailHolder {
+final class TaskRecord extends ThumbnailHolder {
final int taskId; // Unique identifier for this task.
final String affinity; // The affinity name for this task, or null.
Intent intent; // The original intent that started the task.
@@ -57,7 +57,7 @@
/** Current stack */
ActivityStack stack;
- private boolean mApplicationTask;
+ private boolean mApplicationTask = true;
TaskRecord(int _taskId, ActivityInfo info, Intent _intent, ActivityStack _stack) {
taskId = _taskId;
@@ -164,7 +164,10 @@
// Was not previously in list.
numFullscreen++;
}
- mApplicationTask = r.isApplicationActivity();
+ // Only set this to be an application task if it has not already been set as home task.
+ if (mApplicationTask) {
+ mApplicationTask = r.isApplicationActivity();
+ }
mActivities.add(index, r);
}
diff --git a/services/java/com/android/server/am/TransferPipe.java b/services/java/com/android/server/am/TransferPipe.java
index c3f4f93..055c577 100644
--- a/services/java/com/android/server/am/TransferPipe.java
+++ b/services/java/com/android/server/am/TransferPipe.java
@@ -32,7 +32,7 @@
/**
* Helper for transferring data through a pipe from a client app.
*/
-class TransferPipe implements Runnable {
+final class TransferPipe implements Runnable {
static final String TAG = "TransferPipe";
static final boolean DEBUG = false;
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index cba8e0d..5e2ad009 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -35,7 +35,7 @@
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
* src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
*/
-class UriPermission {
+final class UriPermission {
private static final String TAG = "UriPermission";
final int userHandle;
diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java
index 90ac88d..7bbd3bc 100644
--- a/services/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/java/com/android/server/am/UriPermissionOwner.java
@@ -24,7 +24,7 @@
import java.util.HashSet;
import java.util.Iterator;
-class UriPermissionOwner {
+final class UriPermissionOwner {
final ActivityManagerService service;
final Object owner;
diff --git a/services/java/com/android/server/am/UserStartedState.java b/services/java/com/android/server/am/UserStartedState.java
index 0e71f81..d3e73d5 100644
--- a/services/java/com/android/server/am/UserStartedState.java
+++ b/services/java/com/android/server/am/UserStartedState.java
@@ -22,7 +22,7 @@
import android.app.IStopUserCallback;
import android.os.UserHandle;
-public class UserStartedState {
+public final class UserStartedState {
// User is first coming up.
public final static int STATE_BOOTING = 0;
// User is in the normal running state.
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index cf593ce..80c7d88 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -1966,6 +1966,10 @@
for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
final Bundle extras = info.periodicSyncs.get(i).first;
final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
+ // Skip if the period is invalid
+ if (periodInMillis <= 0) {
+ continue;
+ }
// find when this periodic sync was last scheduled to run
final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/java/com/android/server/display/PersistentDataStore.java
index 105c253..d5d7132 100644
--- a/services/java/com/android/server/display/PersistentDataStore.java
+++ b/services/java/com/android/server/display/PersistentDataStore.java
@@ -105,7 +105,8 @@
alias = mRememberedWifiDisplays.get(index).getDeviceAlias();
}
if (!Objects.equal(display.getDeviceAlias(), alias)) {
- return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(), alias);
+ return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(),
+ alias, display.canConnect());
}
}
return display;
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index 8c8b360..e595df4 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -897,7 +897,8 @@
}
private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
- return new WifiDisplay(device.deviceAddress, device.deviceName, null);
+ return new WifiDisplay(device.deviceAddress, device.deviceName, null,
+ device.wfdInfo.isSessionAvailable());
}
private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 0647296..4a3699c 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -340,7 +340,7 @@
boolean setStackBoxSize(Rect contentRect) {
boolean change = false;
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- change |= mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect);
+ change |= mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect, true);
}
return change;
}
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index 15f5dff..d352464 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -79,6 +79,9 @@
/** Dirty flag. Something inside this or some descendant of this has changed. */
boolean layoutNeeded;
+ /** True if this StackBox sits below the Status Bar. */
+ boolean mUnderStatusBar;
+
/** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */
Rect mTmpRect = new Rect();
@@ -286,14 +289,19 @@
/** If this is a terminal StackBox (contains a TaskStack) set the bounds.
* @param bounds The rectangle to set the bounds to.
+ * @param underStatusBar True if the StackBox is directly below the Status Bar.
* @return True if the bounds changed, false otherwise. */
- boolean setStackBoxSizes(Rect bounds) {
- boolean change;
+ boolean setStackBoxSizes(Rect bounds, boolean underStatusBar) {
+ boolean change = false;
+ if (mUnderStatusBar != underStatusBar) {
+ change = true;
+ mUnderStatusBar = underStatusBar;
+ }
if (mStack != null) {
- change = !mBounds.equals(bounds);
+ change |= !mBounds.equals(bounds);
if (change) {
mBounds.set(bounds);
- mStack.setBounds(bounds);
+ mStack.setBounds(bounds, underStatusBar);
}
} else {
mTmpRect.set(bounds);
@@ -301,18 +309,18 @@
final int height = bounds.height();
int firstHeight = (int)(height * mWeight);
mTmpRect.bottom = bounds.top + firstHeight;
- change = mFirst.setStackBoxSizes(mTmpRect);
+ change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
mTmpRect.top = mTmpRect.bottom;
mTmpRect.bottom = bounds.top + height;
- change |= mSecond.setStackBoxSizes(mTmpRect);
+ change |= mSecond.setStackBoxSizes(mTmpRect, false);
} else {
final int width = bounds.width();
int firstWidth = (int)(width * mWeight);
mTmpRect.right = bounds.left + firstWidth;
- change = mFirst.setStackBoxSizes(mTmpRect);
+ change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
mTmpRect.left = mTmpRect.right;
mTmpRect.right = bounds.left + width;
- change |= mSecond.setStackBoxSizes(mTmpRect);
+ change |= mSecond.setStackBoxSizes(mTmpRect, underStatusBar);
}
}
return change;
diff --git a/services/java/com/android/server/wm/StackTapDetector.java b/services/java/com/android/server/wm/StackTapDetector.java
index a71b075..7127fd2 100644
--- a/services/java/com/android/server/wm/StackTapDetector.java
+++ b/services/java/com/android/server/wm/StackTapDetector.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import android.graphics.Rect;
import android.graphics.Region;
import android.os.Looper;
import android.view.DisplayInfo;
@@ -52,49 +51,54 @@
@Override
public void onInputEvent(InputEvent event) {
- if (!(event instanceof MotionEvent)
- || !event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
- return;
- }
- final MotionEvent motionEvent = (MotionEvent)event;
- final int action = motionEvent.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- mPointerId = motionEvent.getPointerId(0);
- mDownX = motionEvent.getX();
- mDownY = motionEvent.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- if (mPointerId >= 0) {
- int index = motionEvent.findPointerIndex(mPointerId);
- if ((motionEvent.getEventTime() - motionEvent.getDownTime()) > TAP_TIMEOUT_MSEC
- || (motionEvent.getX(index) - mDownX) > mMotionSlop
- || (motionEvent.getY(index) - mDownY) > mMotionSlop) {
- mPointerId = -1;
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP: {
- int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- // Extract the index of the pointer that left the touch sensor
- if (mPointerId == motionEvent.getPointerId(index)) {
- final int x = (int)motionEvent.getX(index);
- final int y = (int)motionEvent.getY(index);
- synchronized (this) {
+ try {
+ if (!(event instanceof MotionEvent)
+ || !event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+ return;
+ }
+ final MotionEvent motionEvent = (MotionEvent)event;
+ final int action = motionEvent.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ mPointerId = motionEvent.getPointerId(0);
+ mDownX = motionEvent.getX();
+ mDownY = motionEvent.getY();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mPointerId >= 0) {
+ int index = motionEvent.findPointerIndex(mPointerId);
if ((motionEvent.getEventTime() - motionEvent.getDownTime())
- < TAP_TIMEOUT_MSEC
- && (x - mDownX) < mMotionSlop && (y - mDownY) < mMotionSlop
- && !mTouchExcludeRegion.contains(x, y)) {
- mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y, mDisplayContent)
- .sendToTarget();
+ > TAP_TIMEOUT_MSEC
+ || (motionEvent.getX(index) - mDownX) > mMotionSlop
+ || (motionEvent.getY(index) - mDownY) > mMotionSlop) {
+ mPointerId = -1;
}
}
- mPointerId = -1;
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP: {
+ int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ // Extract the index of the pointer that left the touch sensor
+ if (mPointerId == motionEvent.getPointerId(index)) {
+ final int x = (int)motionEvent.getX(index);
+ final int y = (int)motionEvent.getY(index);
+ synchronized (this) {
+ if ((motionEvent.getEventTime() - motionEvent.getDownTime())
+ < TAP_TIMEOUT_MSEC
+ && (x - mDownX) < mMotionSlop && (y - mDownY) < mMotionSlop
+ && !mTouchExcludeRegion.contains(x, y)) {
+ mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y,
+ mDisplayContent).sendToTarget();
+ }
+ }
+ mPointerId = -1;
+ }
+ break;
}
- break;
}
+ } finally {
+ finishInputEvent(event, false /*ignored for monitors*/);
}
}
}
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 6fd8745..827958d 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -222,7 +222,7 @@
}
}
- void setBounds(Rect bounds) {
+ void setBounds(Rect bounds, boolean underStatusBar) {
mDimLayer.setBounds(bounds);
mAnimationBackgroundSurface.setBounds(bounds);
@@ -236,6 +236,7 @@
if (!resizingWindows.contains(win)) {
resizingWindows.add(win);
}
+ win.mUnderStatusBar = underStatusBar;
}
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index b4dcdec..f166c31 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3487,9 +3487,9 @@
final int firstToken = tokens.size() - 1;
for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
final AppWindowToken atoken = tokens.get(tokenNdx);
-
+
if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
-
+
// if we're about to tear down this window and not seek for
// the behind activity, don't use it for orientation
if (!findingBehind
@@ -3498,7 +3498,7 @@
+ " -- going to hide");
continue;
}
-
+
if (tokenNdx == firstToken) {
// If we have hit a new Task, and the bottom
// of the previous group didn't explicitly say to use
@@ -3512,19 +3512,19 @@
return lastOrientation;
}
}
-
+
// We ignore any hidden applications on the top.
if (atoken.hiddenRequested || atoken.willBeHidden) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
+ " -- hidden on top");
continue;
}
-
+
if (tokenNdx == 0) {
// Last token in this task.
lastOrientation = atoken.requestedOrientation;
}
-
+
int or = atoken.requestedOrientation;
// If this application is fullscreen, and didn't explicitly say
// to use the orientation behind it, then just take whatever
@@ -8605,7 +8605,7 @@
|| winAnimator.mSurfaceResized
|| configChanged) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Resize reasons: "
+ Slog.v(TAG, "Resize reasons for w=" + w + ": "
+ " contentInsetsChanged=" + w.mContentInsetsChanged
+ " " + w.mContentInsets.toShortString()
+ " visibleInsetsChanged=" + w.mVisibleInsetsChanged
@@ -9346,7 +9346,7 @@
}
setFocusedStackFrame();
-
+
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
enableScreenIfNeededLocked();
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 377e8e8..7c6da92 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -298,6 +298,10 @@
/** When true this window can be displayed on screens owther than mOwnerUid's */
private boolean mShowToOwnerOnly;
+ /** When true this window is at the top of the screen and should be layed out to extend under
+ * the status bar */
+ boolean mUnderStatusBar = true;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -434,6 +438,9 @@
if (mAppToken != null) {
mContainingFrame.set(getStackBounds());
+ if (mUnderStatusBar) {
+ mContainingFrame.top = pf.top;
+ }
} else {
mContainingFrame.set(pf);
}
diff --git a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
index 275d807..e2253a2 100644
--- a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
@@ -17,10 +17,13 @@
package com.android.server;
import static com.android.server.NativeDaemonConnector.appendEscaped;
+import static com.android.server.NativeDaemonConnector.makeCommand;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
+
/**
* Tests for {@link NativeDaemonConnector}.
*/
@@ -67,4 +70,28 @@
appendEscaped(builder, "caf\u00E9 c\u00F6ffee");
assertEquals("\"caf\u00E9 c\u00F6ffee\"", builder.toString());
}
+
+ public void testSensitiveArgs() throws Exception {
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", "bar", "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo bar baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("bar"), "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("foo bar"), "baz baz",
+ new SensitiveArg("wat"));
+ assertEquals("1 foo \"foo bar\" \"baz baz\" wat\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] \"baz baz\" [scrubbed]", logBuilder.toString());
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c14d61b..26dde1e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -130,10 +130,10 @@
* call. By default, the MMS app consumes this message and sends a text message to the caller. A
* third party app can provide this functionality in lieu of MMS app by consuming this Intent
* and sending the message using their own messaging system. The intent contains a URI
- * describing the recipient, and an EXTRA containg the message itself.
- * <p>
+ * describing the recipient, and an EXTRA containing the message itself.
+ * <p class="note"><strong>Note:</strong>
* The intent-filter which consumes this Intent needs to be in a service which requires the
- * permission SEND_RESPOND_VIA_MESSAGE.
+ * permission {@link android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE}.</p>
*
* <p>
* {@link android.content.Intent#getData} is a URI describing the recipient of the message.
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java b/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
index d9e1a83..7d82cd3 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
@@ -247,6 +247,18 @@
}
}
+ private static void dump(ArrayMap map1, ArrayMap map2) {
+ Log.e("test", "ArrayMap of " + map1.size() + " entries:");
+ Set<Map.Entry> mapSet = map1.entrySet();
+ for (int i=0; i<map2.size(); i++) {
+ Log.e("test", " " + map1.keyAt(i) + " -> " + map1.valueAt(i));
+ }
+ Log.e("test", "ArrayMap of " + map2.size() + " entries:");
+ for (int i=0; i<map2.size(); i++) {
+ Log.e("test", " " + map2.keyAt(i) + " -> " + map2.valueAt(i));
+ }
+ }
+
public static void run() {
HashMap<ControlledHash, Integer> mHashMap = new HashMap<ControlledHash, Integer>();
ArrayMap<ControlledHash, Integer> mArrayMap = new ArrayMap<ControlledHash, Integer>();
@@ -297,7 +309,63 @@
dump(mHashMap, mArrayMap);
}
+ if (!equalsTest()) {
+ return;
+ }
+
+ // copy constructor test
+ ArrayMap newMap = new ArrayMap<Integer, String>();
+ for (int i = 0; i < 10; ++i) {
+ newMap.put(i, String.valueOf(i));
+ }
+ ArrayMap mapCopy = new ArrayMap(newMap);
+ if (!compare(mapCopy, newMap)) {
+ Log.e("test", "ArrayMap copy constructor failure: expected " +
+ newMap + ", got " + mapCopy);
+ dump(mHashMap, mArrayMap);
+ return;
+ }
+
Log.e("test", "Test successful; printing final map.");
dump(mHashMap, mArrayMap);
}
+
+ private static boolean equalsTest() {
+ ArrayMap<Integer, String> map1 = new ArrayMap<Integer, String>();
+ ArrayMap<Integer, String> map2 = new ArrayMap<Integer, String>();
+ HashMap<Integer, String> map3 = new HashMap<Integer, String>();
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ Log.e("test", "ArrayMap equals failure for empty maps " + map1 + ", " +
+ map2 + ", " + map3);
+ return false;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ String value = String.valueOf(i);
+ map1.put(i, value);
+ map2.put(i, value);
+ map3.put(i, value);
+ }
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ Log.e("test", "ArrayMap equals failure for populated maps " + map1 + ", " +
+ map2 + ", " + map3);
+ return false;
+ }
+
+ map1.remove(0);
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ Log.e("test", "ArrayMap equals failure for map size " + map1 + ", " +
+ map2 + ", " + map3);
+ return false;
+ }
+
+ map1.put(0, "-1");
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ Log.e("test", "ArrayMap equals failure for map contents " + map1 + ", " +
+ map2 + ", " + map3);
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 13b6129..db6421e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -20,19 +20,15 @@
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
-import android.os.Environment;
import android.util.DisplayMetrics;
import android.view.ContextMenu;
import android.view.View;
-import android.view.ViewDebug;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
-import java.io.File;
-
@SuppressWarnings({"UnusedDeclaration"})
public class ListActivity extends Activity {
private static final String[] DATA_LIST = {
@@ -86,7 +82,7 @@
ListAdapter adapter = new SimpleListAdapter(this);
- ListView list = (ListView) findViewById(R.id.list);
+ final ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(adapter);
registerForContextMenu(list);
diff --git a/tests/TransitionTests/AndroidManifest.xml b/tests/TransitionTests/AndroidManifest.xml
index be6b145..98174ab 100644
--- a/tests/TransitionTests/AndroidManifest.xml
+++ b/tests/TransitionTests/AndroidManifest.xml
@@ -212,6 +212,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:label="DelayedTransition"
+ android:name="DelayedTransition">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
diff --git a/tests/TransitionTests/res/layout/two_buttons.xml b/tests/TransitionTests/res/layout/two_buttons.xml
new file mode 100644
index 0000000..23d59f8
--- /dev/null
+++ b/tests/TransitionTests/res/layout/two_buttons.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/container">
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/button1"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/button2"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
index 2fcdc30..d5f6a28 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
@@ -45,6 +45,8 @@
mScene2 = new Scene(mSceneRoot, R.layout.crossfade_1, this);
Crossfade crossfade = new Crossfade();
+ crossfade.setFadeBehavior(Crossfade.FADE_BEHAVIOR_CROSSFADE);
+ crossfade.setResizeBehavior(Crossfade.RESIZE_BEHAVIOR_NONE);
crossfade.setTargetIds(R.id.textview, R.id.textview1, R.id.textview2);
mTransitionManager = new TransitionManager();
TransitionGroup moveCrossFade = new TransitionGroup();
diff --git a/tests/TransitionTests/src/com/android/transitiontests/DelayedTransition.java b/tests/TransitionTests/src/com/android/transitiontests/DelayedTransition.java
new file mode 100644
index 0000000..f05ea78
--- /dev/null
+++ b/tests/TransitionTests/src/com/android/transitiontests/DelayedTransition.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.transitiontests;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.transition.TransitionManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import static android.widget.LinearLayout.LayoutParams;
+
+public class DelayedTransition extends Activity {
+
+ private static final int SEARCH_SCREEN = 0;
+ private static final int RESULTS_SCREEN = 1;
+ ViewGroup mSceneRoot;
+ static int mCurrentScene;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.two_buttons);
+
+ final Button button1 = (Button) findViewById(R.id.button1);
+ final Button button2 = (Button) findViewById(R.id.button2);
+ final LinearLayout container = (LinearLayout) findViewById(R.id.container);
+ button1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ int buttonWidth = button1.getWidth();
+ int containerWidth = container.getWidth();
+ if (buttonWidth < containerWidth) {
+ TransitionManager.beginDelayedTransition(container, null);
+ button1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT));
+ TransitionManager.beginDelayedTransition(container, null);
+ button2.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+ } else {
+ TransitionManager.beginDelayedTransition(container, null);
+ button1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ TransitionManager.beginDelayedTransition(container, null);
+ button2.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ }
+ }
+ });
+ }
+
+}