diff options
82 files changed, 1265 insertions, 402 deletions
diff --git a/api/current.txt b/api/current.txt index 047f8d5..eb7891a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -25582,10 +25582,6 @@ package android.provider { public static final class Telephony.Mms.Intents { field public static final java.lang.String CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED"; field public static final java.lang.String DELETED_CONTENTS = "deleted_contents"; - field public static final java.lang.String EXTRA_MMS_CONTENT_URI = "android.provider.Telephony.extra.MMS_CONTENT_URI"; - field public static final java.lang.String EXTRA_MMS_LOCATION_URL = "android.provider.Telephony.extra.MMS_LOCATION_URL"; - field public static final java.lang.String MMS_DOWNLOAD_ACTION = "android.provider.Telephony.MMS_DOWNLOAD"; - field public static final java.lang.String MMS_SEND_ACTION = "android.provider.Telephony.MMS_SEND"; } public static final class Telephony.Mms.Outbox implements android.provider.Telephony.BaseMmsColumns { @@ -25689,10 +25685,8 @@ package android.provider { field public static final java.lang.String SMS_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_CB_RECEIVED"; field public static final java.lang.String SMS_DELIVER_ACTION = "android.provider.Telephony.SMS_DELIVER"; field public static final java.lang.String SMS_EMERGENCY_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED"; - field public static final java.lang.String SMS_FILTER_ACTION = "android.provider.Telephony.SMS_FILTER"; field public static final java.lang.String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; field public static final java.lang.String SMS_REJECTED_ACTION = "android.provider.Telephony.SMS_REJECTED"; - field public static final java.lang.String SMS_SEND_ACTION = "android.provider.Telephony.SMS_SEND"; field public static final java.lang.String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION = "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED"; field public static final java.lang.String WAP_PUSH_DELIVER_ACTION = "android.provider.Telephony.WAP_PUSH_DELIVER"; field public static final java.lang.String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED"; @@ -27277,8 +27271,8 @@ package android.speech.tts { method public boolean isSpeaking(); method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String); method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); - method public int playSilence(long, int, java.lang.String); method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); + method public int playSilentUtterance(long, int, java.lang.String); method public int setAudioAttributes(android.media.AudioAttributes); method public deprecated int setEngineByPackageName(java.lang.String); method public int setLanguage(java.util.Locale); @@ -28374,14 +28368,10 @@ package android.telephony { method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent); method public android.os.Bundle getCarrierConfigValues(); method public static android.telephony.SmsManager getDefault(); - method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent); method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent); method public void sendMultimediaMessage(android.content.Context, android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent); method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>); method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent); - method public void updateMmsDownloadStatus(android.content.Context, int, int, android.net.Uri); - method public void updateMmsSendStatus(android.content.Context, int, byte[], int, android.net.Uri); - method public void updateSmsSendStatus(int, boolean); field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; @@ -28514,7 +28504,6 @@ package android.telephony { method public java.lang.String getSubscriberId(); method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); - method public int hasCarrierPrivileges(); method public boolean hasIccCard(); method public boolean iccCloseLogicalChannel(int); method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String); @@ -28525,18 +28514,11 @@ package android.telephony { method public boolean isSmsCapable(); method public void listen(android.telephony.PhoneStateListener, int); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); - method public boolean setGlobalPreferredNetworkType(); - method public void setLine1NumberForDisplay(java.lang.String, java.lang.String); - method public boolean setOperatorBrandOverride(java.lang.String); field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final int CALL_STATE_IDLE = 0; // 0x0 field public static final int CALL_STATE_OFFHOOK = 2; // 0x2 field public static final int CALL_STATE_RINGING = 1; // 0x1 - field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe - field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 - field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 - field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff field public static final int DATA_ACTIVITY_DORMANT = 4; // 0x4 field public static final int DATA_ACTIVITY_IN = 1; // 0x1 field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3 diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index e659b2b..0892311 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -397,6 +397,31 @@ void BootAnimation::checkExit() { } } +// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of +// characters in str is a hex number in [0, 255], which are converted to +// floating point values in the range [0.0, 1.0] and placed in the +// corresponding elements of color. +// +// If the input string isn't valid, parseColor returns false and color is +// left unchanged. +static bool parseColor(const char str[7], float color[3]) { + float tmpColor[3]; + for (int i = 0; i < 3; i++) { + int val = 0; + for (int j = 0; j < 2; j++) { + val *= 16; + char c = str[2*i + j]; + if (c >= '0' && c <= '9') val += c - '0'; + else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10; + else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10; + else return false; + } + tmpColor[i] = static_cast<float>(val) / 255.0f; + } + memcpy(color, tmpColor, sizeof(tmpColor)); + return true; +} + bool BootAnimation::movie() { ZipEntryRO desc = mZip->findEntryByName("desc.txt"); @@ -427,20 +452,28 @@ bool BootAnimation::movie() const char* l = line.string(); int fps, width, height, count, pause; char path[ANIM_ENTRY_NAME_MAX]; + char color[7] = "000000"; // default to black if unspecified + char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { - //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); + // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } - else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { - //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); + else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) { + // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; + if (!parseColor(color, part.backgroundColor)) { + ALOGE("> invalid color '#%s'", color); + part.backgroundColor[0] = 0.0f; + part.backgroundColor[1] = 0.0f; + part.backgroundColor[2] = 0.0f; + } animation.parts.add(part); } @@ -526,6 +559,12 @@ bool BootAnimation::movie() if(exitPending() && !part.playUntilComplete) break; + glClearColor( + part.backgroundColor[0], + part.backgroundColor[1], + part.backgroundColor[2], + 1.0f); + for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index ba1c507..72cd62b 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -71,6 +71,7 @@ private: String8 path; SortedVector<Frame> frames; bool playUntilComplete; + float backgroundColor[3]; }; int fps; int width; diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java index b37f896..6a8fb05 100644 --- a/cmds/media/src/com/android/commands/media/Media.java +++ b/cmds/media/src/com/android/commands/media/Media.java @@ -204,7 +204,8 @@ public class Media extends BaseCommand { @Override public void onQueueChanged(ParceledListSlice queue) throws RemoteException { - System.out.println("onQueueChanged, size=" + queue.getList().size()); + System.out.println("onQueueChanged, " + + (queue == null ? "null queue" : " size=" + queue.getList().size())); } @Override diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 2276229..c203a8e 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -51,7 +51,6 @@ public final class BluetoothGatt implements BluetoothProfile { private int mConnState; private final Object mStateLock = new Object(); private Boolean mDeviceBusy = false; - private Boolean mIsCongested = false; private int mTransport; private static final int CONN_STATE_IDLE = 0; @@ -607,21 +606,6 @@ public final class BluetoothGatt implements BluetoothProfile { Log.w(TAG, "Unhandled exception in callback", ex); } } - - /** - * Callback indicating the remote device connection is congested. - * @hide - */ - public void onConnectionCongested(String address, boolean congested) { - if (DBG) Log.d(TAG, "onConnectionCongested() - Device=" + address - + " congested=" + congested); - if (!address.equals(mDevice.getAddress())) return; - try { - mIsCongested = congested; - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); - } - } }; /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device, diff --git a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java index da992f5..cdb24f4 100644 --- a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java +++ b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java @@ -120,10 +120,6 @@ public class BluetoothGattCallbackWrapper extends IBluetoothGattCallback.Stub { } @Override - public void onConnectionCongested(String address, boolean congested) throws RemoteException { - } - - @Override public void onFoundOrLost(boolean onFound, ScanResult scanResult) throws RemoteException { } diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index a7f117b..e94a8ce 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -48,7 +48,6 @@ public final class BluetoothGattServer implements BluetoothProfile { private BluetoothAdapter mAdapter; private IBluetoothGatt mService; private BluetoothGattServerCallback mCallback; - private Boolean mIsCongested = false; private Object mServerIfLock = new Object(); private int mServerIf; @@ -285,24 +284,6 @@ public final class BluetoothGattServer implements BluetoothProfile { Log.w(TAG, "Unhandled exception: " + ex); } } - - /** - * Callback indicating the remote device connection is congested. - * @hide - */ - public void onConnectionCongested(String address, boolean congested) { - if (DBG) Log.d(TAG, "onConnectionCongested() - Device=" + address - + " congested=" + congested); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mIsCongested = congested; - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); - } - } }; /** diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl index 00b6b1b..91e62ea 100644 --- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl @@ -68,6 +68,5 @@ oneway interface IBluetoothGattCallback { void onMultiAdvertiseCallback(in int status, boolean isStart, in AdvertiseSettings advertiseSettings); void onConfigureMTU(in String address, in int mtu, in int status); - void onConnectionCongested(in String address, in boolean congested); void onFoundOrLost(in boolean onFound, in ScanResult scanResult); } diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl index 6e31da1..5d4d6c6 100644 --- a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl @@ -59,5 +59,4 @@ oneway interface IBluetoothGattServerCallback { in byte[] value); void onExecuteWrite(in String address, in int transId, in boolean execWrite); void onNotificationSent(in String address, in int status); - void onConnectionCongested(in String address, in boolean congested); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 702ac6b..77981f4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2723,6 +2723,9 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE"; + /** {@hide} */ + public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). @@ -3425,6 +3428,9 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT = "android.intent.extra.TIME_PREF_24_HOUR_FORMAT"; + /** {@hide} */ + public static final String EXTRA_REASON = "android.intent.extra.REASON"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java index c141c51..b9c89f8 100644 --- a/core/java/android/hardware/camera2/legacy/BurstHolder.java +++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java @@ -22,6 +22,7 @@ import android.util.Log; import android.view.Surface; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -38,14 +39,16 @@ public class BurstHolder { * * @param requestId id of the burst request. * @param repeating true if this burst is repeating. - * @param requests a {@link java.util.List} of {@link CaptureRequest}s in this burst. + * @param requests a {@link List} of {@link CaptureRequest}s in this burst. + * @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs. */ - public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests) { - mRequestBuilders = new ArrayList<RequestHolder.Builder>(); + public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests, + Collection<Long> jpegSurfaceIds) { + mRequestBuilders = new ArrayList<>(); int i = 0; for (CaptureRequest r : requests) { mRequestBuilders.add(new RequestHolder.Builder(requestId, /*subsequenceId*/i, - /*request*/r, repeating)); + /*request*/r, repeating, jpegSurfaceIds)); ++i; } mRepeating = repeating; diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index e19f587..fcf172c 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -336,8 +336,16 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(cameraId, info); + Camera.Parameters legacyParameters = null; + try { + legacyParameters = legacyCamera.getParameters(); + } catch (RuntimeException e) { + throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR, + "Unable to get initial parameters", e); + } + CameraCharacteristics characteristics = - LegacyMetadataMapper.createCharacteristics(legacyCamera.getParameters(), info); + LegacyMetadataMapper.createCharacteristics(legacyParameters, info); LegacyCameraDevice device = new LegacyCameraDevice( cameraId, legacyCamera, characteristics, threadCallbacks); return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks); diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index a724b41..4587c6f 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -522,7 +522,7 @@ public class LegacyCameraDevice implements AutoCloseable { return surfaceIds; } - static boolean containsSurfaceId(Surface s, List<Long> ids) { + static boolean containsSurfaceId(Surface s, Collection<Long> ids) { long id = getSurfaceId(s); return ids.contains(id); } diff --git a/core/java/android/hardware/camera2/legacy/RequestHolder.java b/core/java/android/hardware/camera2/legacy/RequestHolder.java index 69c140b..edd8e4e 100644 --- a/core/java/android/hardware/camera2/legacy/RequestHolder.java +++ b/core/java/android/hardware/camera2/legacy/RequestHolder.java @@ -43,71 +43,6 @@ public class RequestHolder { private volatile boolean mFailed = false; /** - * Returns true if the given surface requires jpeg buffers. - * - * @param s a {@link android.view.Surface} to check. - * @return true if the surface requires a jpeg buffer. - */ - public static boolean jpegType(Surface s) - throws LegacyExceptionUtils.BufferQueueAbandonedException { - return LegacyCameraDevice.detectSurfaceType(s) == - CameraMetadataNative.NATIVE_JPEG_FORMAT; - } - - /** - * Returns true if the given surface requires non-jpeg buffer types. - * - * <p> - * "Jpeg buffer" refers to the buffers returned in the jpeg - * {@link android.hardware.Camera.PictureCallback}. Non-jpeg buffers are created using a tee - * of the preview stream drawn to the surface - * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or - * equivalent methods. - * </p> - * @param s a {@link android.view.Surface} to check. - * @return true if the surface requires a non-jpeg buffer type. - */ - public static boolean previewType(Surface s) - throws LegacyExceptionUtils.BufferQueueAbandonedException { - return LegacyCameraDevice.detectSurfaceType(s) != - CameraMetadataNative.NATIVE_JPEG_FORMAT; - } - - /** - * Returns the number of surfaces targeted by the request that require jpeg buffers. - */ - private static int numJpegTargets(CaptureRequest request) { - int count = 0; - for (Surface s : request.getTargets()) { - try { - if (jpegType(s)) { - ++count; - } - } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { - Log.w(TAG, "Surface abandoned, skipping...", e); - } - } - return count; - } - - /** - * Returns the number of surfaces targeted by the request that require non-jpeg buffers. - */ - private static int numPreviewTargets(CaptureRequest request) { - int count = 0; - for (Surface s : request.getTargets()) { - try { - if (previewType(s)) { - ++count; - } - } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { - Log.w(TAG, "Surface abandoned, skipping...", e); - } - } - return count; - } - - /** * A builder class for {@link RequestHolder} objects. * * <p> @@ -121,6 +56,7 @@ public class RequestHolder { private final boolean mRepeating; private final int mNumJpegTargets; private final int mNumPreviewTargets; + private final Collection<Long> mJpegSurfaceIds; /** * Construct a new {@link Builder} to generate {@link RequestHolder} objects. @@ -132,17 +68,81 @@ public class RequestHolder { * @param repeating {@code true} if the request is repeating. */ public Builder(int requestId, int subsequenceId, CaptureRequest request, - boolean repeating) { + boolean repeating, Collection<Long> jpegSurfaceIds) { checkNotNull(request, "request must not be null"); mRequestId = requestId; mSubsequenceId = subsequenceId; mRequest = request; mRepeating = repeating; + mJpegSurfaceIds = jpegSurfaceIds; mNumJpegTargets = numJpegTargets(mRequest); mNumPreviewTargets = numPreviewTargets(mRequest); } /** + * Returns true if the given surface requires jpeg buffers. + * + * @param s a {@link android.view.Surface} to check. + * @return true if the surface requires a jpeg buffer. + */ + private boolean jpegType(Surface s) + throws LegacyExceptionUtils.BufferQueueAbandonedException { + return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds); + } + + /** + * Returns true if the given surface requires non-jpeg buffer types. + * + * <p> + * "Jpeg buffer" refers to the buffers returned in the jpeg + * {@link android.hardware.Camera.PictureCallback}. Non-jpeg buffers are created using a tee + * of the preview stream drawn to the surface + * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or + * equivalent methods. + * </p> + * @param s a {@link android.view.Surface} to check. + * @return true if the surface requires a non-jpeg buffer type. + */ + private boolean previewType(Surface s) + throws LegacyExceptionUtils.BufferQueueAbandonedException { + return !jpegType(s); + } + + /** + * Returns the number of surfaces targeted by the request that require jpeg buffers. + */ + private int numJpegTargets(CaptureRequest request) { + int count = 0; + for (Surface s : request.getTargets()) { + try { + if (jpegType(s)) { + ++count; + } + } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { + Log.d(TAG, "Surface abandoned, skipping...", e); + } + } + return count; + } + + /** + * Returns the number of surfaces targeted by the request that require non-jpeg buffers. + */ + private int numPreviewTargets(CaptureRequest request) { + int count = 0; + for (Surface s : request.getTargets()) { + try { + if (previewType(s)) { + ++count; + } + } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { + Log.d(TAG, "Surface abandoned, skipping...", e); + } + } + return count; + } + + /** * Build a new {@link RequestHolder} using with parameters generated from this * {@link Builder}. * diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java index 7598f99..c995029 100644 --- a/core/java/android/hardware/camera2/legacy/RequestQueue.java +++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java @@ -39,8 +39,11 @@ public class RequestQueue { private long mCurrentFrameNumber = 0; private long mCurrentRepeatingFrameNumber = INVALID_FRAME; private int mCurrentRequestId = 0; + private final List<Long> mJpegSurfaceIds; - public RequestQueue() {} + public RequestQueue(List<Long> jpegSurfaceIds) { + mJpegSurfaceIds = jpegSurfaceIds; + } /** * Return and remove the next burst on the queue. @@ -117,7 +120,7 @@ public class RequestQueue { public synchronized int submit(List<CaptureRequest> requests, boolean repeating, /*out*/LongParcelable frameNumber) { int requestId = mCurrentRequestId++; - BurstHolder burst = new BurstHolder(requestId, repeating, requests); + BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); long ret = INVALID_FRAME; if (burst.isRepeating()) { Log.i(TAG, "Repeating capture request set."); diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 4f8fe0b..a7ea89c 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -91,9 +91,11 @@ public class RequestThreadManager { private SurfaceTexture mPreviewTexture; private Camera.Parameters mParams; + private final List<Long> mJpegSurfaceIds = new ArrayList<>(); + private Size mIntermediateBufferSize; - private final RequestQueue mRequestQueue = new RequestQueue(); + private final RequestQueue mRequestQueue = new RequestQueue(mJpegSurfaceIds); private LegacyRequest mLastRequest = null; private SurfaceTexture mDummyTexture; private Surface mDummySurface; @@ -102,6 +104,10 @@ public class RequestThreadManager { private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); + // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write + // limitations for (b/17379185). + private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; + /** * Container object for Configure messages. */ @@ -189,18 +195,21 @@ public class RequestThreadManager { public void onPictureTaken(byte[] data, Camera camera) { Log.i(TAG, "Received jpeg."); Pair<RequestHolder, Long> captureInfo = mCaptureCollector.jpegProduced(); - RequestHolder holder = captureInfo.first; - long timestamp = captureInfo.second; - if (holder == null) { + if (captureInfo == null || captureInfo.first == null) { Log.e(TAG, "Dropping jpeg frame."); return; } + RequestHolder holder = captureInfo.first; + long timestamp = captureInfo.second; for (Surface s : holder.getHolderTargets()) { try { - if (RequestHolder.jpegType(s)) { + if (LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds)) { Log.i(TAG, "Producing jpeg buffer..."); - LegacyCameraDevice.setSurfaceDimens(s, data.length + - LegacyCameraDevice.nativeGetJpegFooterSize(), /*height*/1); + + int totalSize = data.length + LegacyCameraDevice.nativeGetJpegFooterSize(); + totalSize += ((totalSize - 1) & ~0x3) + 4; // align to next octonibble + + LegacyCameraDevice.setSurfaceDimens(s, totalSize, /*height*/1); LegacyCameraDevice.setNextTimestamp(s, timestamp); LegacyCameraDevice.produceFrame(s, data, data.length, /*height*/1, CameraMetadataNative.NATIVE_JPEG_FORMAT); @@ -316,8 +325,10 @@ public class RequestThreadManager { mGLThreadManager.ignoreNewFrames(); mGLThreadManager.waitUntilIdle(); } + resetJpegSurfaceFormats(mCallbackOutputs); mPreviewOutputs.clear(); mCallbackOutputs.clear(); + mJpegSurfaceIds.clear(); mPreviewTexture = null; int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING); @@ -329,6 +340,12 @@ public class RequestThreadManager { LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation); switch (format) { case CameraMetadataNative.NATIVE_JPEG_FORMAT: + if (USE_BLOB_FORMAT_OVERRIDE) { + // Override to RGBA_8888 format. + LegacyCameraDevice.setSurfaceFormat(s, + LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888); + } + mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s)); mCallbackOutputs.add(s); break; default: @@ -340,7 +357,14 @@ public class RequestThreadManager { } } } - mParams = mCamera.getParameters(); + try { + mParams = mCamera.getParameters(); + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + return; + } List<int[]> supportedFpsRanges = mParams.getSupportedPreviewFpsRange(); int[] bestRange = getPhotoPreviewFpsRange(supportedFpsRanges); @@ -426,8 +450,19 @@ public class RequestThreadManager { } mCamera.setParameters(mParams); - // TODO: configure the JPEG surface with some arbitrary size - // using LegacyCameraDevice.nativeConfigureSurface + } + + private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { + if (!USE_BLOB_FORMAT_OVERRIDE || surfaces == null) { + return; + } + for(Surface s : surfaces) { + try { + LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB); + } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { + Log.w(TAG, "Surface abandoned, skipping...", e); + } + } } /** @@ -459,9 +494,8 @@ public class RequestThreadManager { List<Size> configuredJpegSizes = new ArrayList<Size>(); for (Surface callbackSurface : callbackOutputs) { try { - int format = LegacyCameraDevice.detectSurfaceType(callbackSurface); - if (format != CameraMetadataNative.NATIVE_JPEG_FORMAT) { + if (!LegacyCameraDevice.containsSurfaceId(callbackSurface, mJpegSurfaceIds)) { continue; // Ignore non-JPEG callback formats } @@ -754,7 +788,14 @@ public class RequestThreadManager { if (DEBUG) { Log.d(TAG, "Params changed -- getting new Parameters from HAL."); } - mParams = mCamera.getParameters(); + try { + mParams = mCamera.getParameters(); + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + break; + } // Update parameters to the latest that we think the camera is using mLastRequest.setParameters(mParams); @@ -821,6 +862,7 @@ public class RequestThreadManager { if (mCamera != null) { mCamera.release(); } + resetJpegSurfaceFormats(mCallbackOutputs); break; default: throw new AssertionError("Unhandled message " + msg.what + diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java index c018c3e..c0d1d5e 100644 --- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java +++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java @@ -581,6 +581,7 @@ public class SurfaceTextureRenderer { // If pixel conversions aren't handled by egl, use a pbuffer try { if (LegacyCameraDevice.needsConversion(s)) { + // Always override to YV12 output for YUV surface formats. LegacyCameraDevice.setSurfaceFormat(s, ImageFormat.YV12); EGLSurfaceHolder holder = new EGLSurfaceHolder(); holder.surface = s; diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index ba71605..362afba 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -17,6 +17,7 @@ package android.os; import android.util.Log; +import android.util.Slog; import com.android.internal.util.FastPrintWriter; import java.io.FileDescriptor; @@ -48,7 +49,7 @@ public class Binder implements IBinder { * of classes can potentially create leaks. */ private static final boolean FIND_POTENTIAL_LEAKS = false; - private static final String TAG = "Binder"; + static final String TAG = "Binder"; /** * Control whether dump() calls are allowed. @@ -385,7 +386,14 @@ public class Binder implements IBinder { super.finalize(); } } - + + static void checkParcel(Parcel parcel, String msg) { + if (parcel.dataSize() >= 800*1024) { + // Trying to send > 800k, this is way too much + Slog.wtfStack(TAG, msg + parcel.dataSize()); + } + } + private native final void init(); private native final void destroy(); @@ -424,6 +432,7 @@ public class Binder implements IBinder { reply.writeException(re); res = true; } + checkParcel(reply, "Unreasonably large binder reply buffer: "); reply.recycle(); data.recycle(); return res; @@ -433,13 +442,18 @@ public class Binder implements IBinder { final class BinderProxy implements IBinder { public native boolean pingBinder(); public native boolean isBinderAlive(); - + public IInterface queryLocalInterface(String descriptor) { return null; } - + + public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + Binder.checkParcel(data, "Unreasonably large binder buffer: "); + return transactNative(code, data, reply, flags); + } + public native String getInterfaceDescriptor() throws RemoteException; - public native boolean transact(int code, Parcel data, Parcel reply, + public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException; diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 7a46e40..b879c83 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.UserManager; +import android.text.TextUtils; import android.util.Log; import java.io.ByteArrayInputStream; @@ -333,9 +334,10 @@ public class RecoverySystem { throws IOException { String filename = packageFile.getCanonicalPath(); Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); - String arg = "--update_package=" + filename + - "\n--locale=" + Locale.getDefault().toString(); - bootCommand(context, arg); + + final String filenameArg = "--update_package=" + filename; + final String localeArg = "--locale=" + Locale.getDefault().toString(); + bootCommand(context, filenameArg, localeArg); } /** @@ -352,7 +354,18 @@ public class RecoverySystem { * @throws SecurityException if the current user is not allowed to wipe data. */ public static void rebootWipeUserData(Context context) throws IOException { - rebootWipeUserData(context, false); + rebootWipeUserData(context, false, context.getPackageName()); + } + + /** {@hide} */ + public static void rebootWipeUserData(Context context, String reason) throws IOException { + rebootWipeUserData(context, false, reason); + } + + /** {@hide} */ + public static void rebootWipeUserData(Context context, boolean shutdown) + throws IOException { + rebootWipeUserData(context, shutdown, context.getPackageName()); } /** @@ -373,8 +386,8 @@ public class RecoverySystem { * * @hide */ - public static void rebootWipeUserData(Context context, boolean shutdown) - throws IOException { + public static void rebootWipeUserData(Context context, boolean shutdown, String reason) + throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); @@ -395,13 +408,18 @@ public class RecoverySystem { // Block until the ordered broadcast has completed. condition.block(); - String shutdownArg = ""; + String shutdownArg = null; if (shutdown) { - shutdownArg = "--shutdown_after\n"; + shutdownArg = "--shutdown_after"; + } + + String reasonArg = null; + if (!TextUtils.isEmpty(reason)) { + reasonArg = "--reason=" + sanitizeArg(reason); } - bootCommand(context, shutdownArg + "--wipe_data\n--locale=" + - Locale.getDefault().toString()); + final String localeArg = "--locale=" + Locale.getDefault().toString(); + bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg); } /** @@ -409,23 +427,38 @@ public class RecoverySystem { * @throws IOException if something goes wrong. */ public static void rebootWipeCache(Context context) throws IOException { - bootCommand(context, "--wipe_cache\n--locale=" + Locale.getDefault().toString()); + rebootWipeCache(context, context.getPackageName()); + } + + /** {@hide} */ + public static void rebootWipeCache(Context context, String reason) throws IOException { + String reasonArg = null; + if (!TextUtils.isEmpty(reason)) { + reasonArg = "--reason=" + sanitizeArg(reason); + } + + final String localeArg = "--locale=" + Locale.getDefault().toString(); + bootCommand(context, "--wipe_cache", reasonArg, localeArg); } /** * Reboot into the recovery system with the supplied argument. - * @param arg to pass to the recovery utility. + * @param args to pass to the recovery utility. * @throws IOException if something goes wrong. */ - private static void bootCommand(Context context, String arg) throws IOException { + private static void bootCommand(Context context, String... args) throws IOException { RECOVERY_DIR.mkdirs(); // In case we need it COMMAND_FILE.delete(); // In case it's not writable LOG_FILE.delete(); FileWriter command = new FileWriter(COMMAND_FILE); try { - command.write(arg); - command.write("\n"); + for (String arg : args) { + if (!TextUtils.isEmpty(arg)) { + command.write(arg); + command.write("\n"); + } + } } finally { command.close(); } @@ -470,5 +503,15 @@ public class RecoverySystem { return log; } + /** + * Internally, recovery treats each line of the command file as a separate + * argv, so we only need to protect against newlines and nulls. + */ + private static String sanitizeArg(String arg) { + arg = arg.replace('\0', '?'); + arg = arg.replace('\n', '?'); + return arg; + } + private void RecoverySystem() { } // Do not instantiate } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 440b1ec..ec4a53e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -978,6 +978,19 @@ public final class Settings { public static final String EXTRA_INPUT_METHOD_ID = "input_method_id"; /** + * Activity Extra: The device identifier to act upon. + * <p> + * This can be passed as an extra field in an Activity Intent with a single + * InputDeviceIdentifier. This field is used by some activities to jump straight into the + * settings for the given device. + * <p> + * Example: The {@link #INPUT_METHOD_SETTINGS} intent opens the keyboard layout dialog for the + * given device. + * @hide + */ + public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier"; + + /** * @hide * Activity Extra: Enable or disable Airplane Mode. * <p> diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index b22fd9c..35fff74 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -478,7 +478,7 @@ public abstract class NotificationListenerService extends Service { public final int getCurrentInterruptionFilter() { if (!isBound()) return 0; try { - return getNotificationInterface().getHintsFromListener(mWrapper); + return getNotificationInterface().getInterruptionFilterFromListener(mWrapper); } catch (android.os.RemoteException ex) { Log.v(TAG, "Unable to contact notification manager", ex); return 0; diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java index d41aa67..6262fcb 100644 --- a/core/java/android/speech/tts/SynthesisRequest.java +++ b/core/java/android/speech/tts/SynthesisRequest.java @@ -61,7 +61,7 @@ public final class SynthesisRequest { /** * Gets the text which should be synthesized. - * @deprecated As of API level 20, replaced by {@link #getCharSequenceText}. + * @deprecated As of API level 21, replaced by {@link #getCharSequenceText}. */ @Deprecated public String getText() { diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 120c9e3..c59ca8a 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -575,7 +575,7 @@ public class TextToSpeech { * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String) * @see TextToSpeech#getFeatures(java.util.Locale) * - * @deprecated Starting from API level 20, to select network synthesis, call + * @deprecated Starting from API level 21, to select network synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable network voice * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). @@ -593,7 +593,7 @@ public class TextToSpeech { * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String) * @see TextToSpeech#getFeatures(java.util.Locale) - * @deprecated Starting from API level 20, to select embedded synthesis, call + * @deprecated Starting from API level 21, to select embedded synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). @@ -1015,7 +1015,7 @@ public class TextToSpeech { * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. * - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #addEarcon(String, File)}. */ @Deprecated @@ -1124,7 +1124,7 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #speak(CharSequence, int, Bundle, String)}. */ @Deprecated @@ -1194,7 +1194,7 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #playEarcon(String, int, Bundle, String)}. */ @Deprecated @@ -1218,9 +1218,9 @@ public class TextToSpeech { * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. * @param utteranceId An unique identifier for this request. * - * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation. + * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilentUtterance operation. */ - public int playSilence(final long durationInMs, final int queueMode, + public int playSilentUtterance(final long durationInMs, final int queueMode, final String utteranceId) { return runAction(new Action<Integer>() { @Override @@ -1228,7 +1228,7 @@ public class TextToSpeech { return service.playSilence(getCallerIdentity(), durationInMs, queueMode, utteranceId); } - }, ERROR, "playSilence"); + }, ERROR, "playSilentUtterance"); } /** @@ -1252,13 +1252,13 @@ public class TextToSpeech { * engine named "com.svox.pico" if it is being used. * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation. - * @deprecated As of API level 20, replaced by - * {@link #playSilence(long, int, String)}. + * @deprecated As of API level 21, replaced by + * {@link #playSilentUtterance(long, int, String)}. */ @Deprecated public int playSilence(final long durationInMs, final int queueMode, final HashMap<String, String> params) { - return playSilence(durationInMs, queueMode, + return playSilentUtterance(durationInMs, queueMode, params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1276,7 +1276,7 @@ public class TextToSpeech { * * @param locale The locale to query features for. * @return Set instance. May return {@code null} on error. - * @deprecated As of API level 20, please use voices. In order to query features of the voice, + * @deprecated As of API level 21, please use voices. In order to query features of the voice, * call {@link #getVoices()} to retrieve the list of available voices and * {@link Voice#getFeatures()} to retrieve the set of features. */ @@ -1421,7 +1421,7 @@ public class TextToSpeech { * * @return language, country (if any) and variant (if any) used by the client stored in a * Locale instance, or {@code null} on error. - * @deprecated As of API Level 20, use <code>getDefaultVoice().getLocale()</code> ({@link + * @deprecated As of API level 21, use <code>getDefaultVoice().getLocale()</code> ({@link * #getDefaultVoice()}) */ @Deprecated @@ -1476,7 +1476,7 @@ public class TextToSpeech { String variant = loc.getVariant(); - // As of API level 20, setLanguage is implemented using setVoice. + // As of API level 21, setLanguage is implemented using setVoice. // (which, in the default implementation, will call loadLanguage on the service // interface). @@ -1535,7 +1535,7 @@ public class TextToSpeech { * @return language, country (if any) and variant (if any) used by the client stored in a * Locale instance, or {@code null} on error. * - * @deprecated As of API level 20, please use <code>getVoice().getLocale()</code> + * @deprecated As of API level 21, please use <code>getVoice().getLocale()</code> * ({@link #getVoice()}). */ @Deprecated @@ -1831,7 +1831,7 @@ public class TextToSpeech { * something like "/sdcard/myappsounds/mysound.wav". * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. - * @deprecated As of API level 20, replaced by + * @deprecated As of API level 21, replaced by * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}. */ @Deprecated diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 079467a..9bb7f02 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -91,7 +91,7 @@ import java.util.Set; * The first three methods are siblings of the {@link #onGetLanguage}, * {@link #onIsLanguageAvailable} and {@link #onLoadLanguage} methods. The last one, * {@link #onGetDefaultVoiceNameFor(String, String, String)} is a link between locale and voice - * based methods. Since API level 20 {@link TextToSpeech#setLanguage} is implemented by + * based methods. Since API level 21 {@link TextToSpeech#setLanguage} is implemented by * calling {@link TextToSpeech#setVoice} with the voice returned by * {@link #onGetDefaultVoiceNameFor(String, String, String)}. * diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 946a3f7..c855e57 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -81,7 +81,7 @@ public class DisplayMetrics { /** * Intermediate density for screens that sit somewhere between - * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (560 dpi). + * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi). * This is not a density that applications should target, instead relying * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them. */ diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index a283b91..baa133d 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -889,7 +889,13 @@ final class AccessibilityInteractionController { } } } else { - AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(virtualViewId); + final AccessibilityNodeInfo root; + if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { + root = provider.createAccessibilityNodeInfo(virtualViewId); + } else { + root = provider.createAccessibilityNodeInfo( + AccessibilityNodeProvider.HOST_VIEW_ID); + } if (root != null) { outInfos.add(root); if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) { diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 08160c8..dffcca4 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -434,11 +434,12 @@ public final class WindowManagerGlobal { boolean hasVisibleWindows = false; synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { - if (mRoots.get(i).getHostVisibility() == View.VISIBLE - && mRoots.get(i).mAttachInfo.mHardwareRenderer != null) { + final ViewRootImpl root = mRoots.get(i); + if (root.mView != null && root.getHostVisibility() == View.VISIBLE + && root.mAttachInfo.mHardwareRenderer != null) { hasVisibleWindows = true; } else { - mRoots.get(i).destroyHardwareResources(); + root.destroyHardwareResources(); } } } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 2b8b4dc..0439168 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1493,11 +1493,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te super.onInitializeAccessibilityNodeInfo(info); info.setClassName(AbsListView.class.getName()); if (isEnabled()) { - if (getFirstVisiblePosition() > 0) { + if (canScrollUp()) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); info.setScrollable(true); } - if (getLastVisiblePosition() < getCount() - 1) { + if (canScrollDown()) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); info.setScrollable(true); } @@ -2203,36 +2203,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te void updateScrollIndicators() { if (mScrollUp != null) { - boolean canScrollUp; - // 0th element is not visible - canScrollUp = mFirstPosition > 0; - - // ... Or top of 0th element is not visible - if (!canScrollUp) { - if (getChildCount() > 0) { - View child = getChildAt(0); - canScrollUp = child.getTop() < mListPadding.top; - } - } - - mScrollUp.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE); + mScrollUp.setVisibility(canScrollUp() ? View.VISIBLE : View.INVISIBLE); } if (mScrollDown != null) { - boolean canScrollDown; - int count = getChildCount(); + mScrollDown.setVisibility(canScrollDown() ? View.VISIBLE : View.INVISIBLE); + } + } - // Last item is not visible - canScrollDown = (mFirstPosition + count) < mItemCount; + private boolean canScrollUp() { + boolean canScrollUp; + // 0th element is not visible + canScrollUp = mFirstPosition > 0; - // ... Or bottom of the last element is not visible - if (!canScrollDown && count > 0) { - View child = getChildAt(count - 1); - canScrollDown = child.getBottom() > mBottom - mListPadding.bottom; + // ... Or top of 0th element is not visible + if (!canScrollUp) { + if (getChildCount() > 0) { + View child = getChildAt(0); + canScrollUp = child.getTop() < mListPadding.top; } + } + + return canScrollUp; + } - mScrollDown.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE); + private boolean canScrollDown() { + boolean canScrollDown; + int count = getChildCount(); + + // Last item is not visible + canScrollDown = (mFirstPosition + count) < mItemCount; + + // ... Or bottom of the last element is not visible + if (!canScrollDown && count > 0) { + View child = getChildAt(count - 1); + canScrollDown = child.getBottom() > mBottom - mListPadding.bottom; } + + return canScrollDown; } @Override diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 22600de..5685ad7 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -128,7 +128,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic com.android.internal.R.string.whichSendApplicationNamed), DEFAULT(null, com.android.internal.R.string.whichApplication, - com.android.internal.R.string.whichApplicationNamed); + com.android.internal.R.string.whichApplicationNamed), + HOME(Intent.ACTION_MAIN, + com.android.internal.R.string.whichHomeApplication, + com.android.internal.R.string.whichHomeApplicationNamed); public final String action; public final int titleRes; @@ -142,7 +145,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic public static ActionTitle forAction(String action) { for (ActionTitle title : values()) { - if (action != null && action.equals(title.action)) { + if (title != HOME && action != null && action.equals(title.action)) { return title; } } @@ -165,26 +168,19 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic @Override protected void onCreate(Bundle savedInstanceState) { // Use a specialized prompt when we're handling the 'Home' app startActivity() - final int titleResource; final Intent intent = makeMyIntent(); final Set<String> categories = intent.getCategories(); if (Intent.ACTION_MAIN.equals(intent.getAction()) && categories != null && categories.size() == 1 && categories.contains(Intent.CATEGORY_HOME)) { - titleResource = com.android.internal.R.string.whichHomeApplication; - // Note: this field is not set to true in the compatibility version. mResolvingHome = true; - } else { - titleResource = 0; } setSafeForwardingMode(true); - onCreate(savedInstanceState, intent, - titleResource != 0 ? getResources().getText(titleResource) : null, titleResource, - null, null, true); + onCreate(savedInstanceState, intent, null, 0, null, null, true); } /** @@ -336,7 +332,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } protected CharSequence getTitleForAction(String action, int defaultTitleRes) { - final ActionTitle title = ActionTitle.forAction(action); + final ActionTitle title = mResolvingHome ? ActionTitle.HOME : ActionTitle.forAction(action); final boolean named = mAdapter.hasFilteredItem(); if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) { return getString(defaultTitleRes); diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java index fb7f215..a529923 100644 --- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java +++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java @@ -50,6 +50,7 @@ public class ExternalStorageFormatter extends Service private boolean mFactoryReset = false; private boolean mAlwaysReset = false; + private String mReason = null; StorageEventListener mStorageListener = new StorageEventListener() { @Override @@ -84,6 +85,7 @@ public class ExternalStorageFormatter extends Service mAlwaysReset = true; } + mReason = intent.getStringExtra(Intent.EXTRA_REASON); mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME); if (mProgressDialog == null) { @@ -135,7 +137,10 @@ public class ExternalStorageFormatter extends Service void fail(int msg) { Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); if (mAlwaysReset) { - sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); + Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.putExtra(Intent.EXTRA_REASON, mReason); + sendBroadcast(intent); } stopSelf(); } @@ -179,7 +184,10 @@ public class ExternalStorageFormatter extends Service } if (success) { if (mFactoryReset) { - sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); + Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.putExtra(Intent.EXTRA_REASON, mReason); + sendBroadcast(intent); // Intent handling is asynchronous -- assume it will happen soon. stopSelf(); return; @@ -188,7 +196,10 @@ public class ExternalStorageFormatter extends Service // If we didn't succeed, or aren't doing a full factory // reset, then it is time to remount the storage. if (!success && mAlwaysReset) { - sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); + Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.putExtra(Intent.EXTRA_REASON, mReason); + sendBroadcast(intent); } else { try { mountService.mountVolume(extStoragePath); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 7160724..85b58aa 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.os.AsyncTask; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -718,25 +719,31 @@ public class LockPatternUtils { } /** Update the encryption password if it is enabled **/ - private void updateEncryptionPassword(int type, String password) { + private void updateEncryptionPassword(final int type, final String password) { DevicePolicyManager dpm = getDevicePolicyManager(); if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId()) != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) { return; } - IBinder service = ServiceManager.getService("mount"); + final IBinder service = ServiceManager.getService("mount"); if (service == null) { Log.e(TAG, "Could not find the mount service to update the encryption password"); return; } - IMountService mountService = IMountService.Stub.asInterface(service); - try { - mountService.changeEncryptionPassword(type, password); - } catch (RemoteException e) { - Log.e(TAG, "Error changing encryption password", e); - } + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... dummy) { + IMountService mountService = IMountService.Stub.asInterface(service); + try { + mountService.changeEncryptionPassword(type, password); + } catch (RemoteException e) { + Log.e(TAG, "Error changing encryption password", e); + } + return null; + } + }.execute(); } /** @@ -773,9 +780,9 @@ public class LockPatternUtils { */ public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { try { - getLockSettings().setLockPassword(password, userHandle); DevicePolicyManager dpm = getDevicePolicyManager(); if (!TextUtils.isEmpty(password)) { + getLockSettings().setLockPassword(password, userHandle); int computedQuality = computePasswordQuality(password); if (userHandle == UserHandle.USER_OWNER) { @@ -853,6 +860,7 @@ public class LockPatternUtils { setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); } else { // Empty password + getLockSettings().setLockPassword(null, userHandle); if (userHandle == UserHandle.USER_OWNER) { // Set the encryption password to default. updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp index 980ead0..ee00161 100644 --- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp +++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp @@ -200,7 +200,7 @@ static status_t produceFrame(const sp<ANativeWindow>& anw, switch(pixelFmt) { case HAL_PIXEL_FORMAT_YCrCb_420_SP: { if (bufSize < width * height * 4) { - ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions", + ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions", __FUNCTION__, bufSize); return BAD_VALUE; } @@ -222,7 +222,7 @@ static status_t produceFrame(const sp<ANativeWindow>& anw, } case HAL_PIXEL_FORMAT_YV12: { if (bufSize < width * height * 4) { - ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions", + ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions", __FUNCTION__, bufSize); return BAD_VALUE; } @@ -259,7 +259,7 @@ static status_t produceFrame(const sp<ANativeWindow>& anw, // Software writes with YCbCr_420_888 format are unsupported // by the gralloc module for now if (bufSize < width * height * 4) { - ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions", + ALOGE("%s: PixelBuffer size %" PRId32 " too small for given dimensions", __FUNCTION__, bufSize); return BAD_VALUE; } @@ -281,6 +281,18 @@ static status_t produceFrame(const sp<ANativeWindow>& anw, return BAD_VALUE; } int8_t* img = NULL; + struct camera3_jpeg_blob footer = { + jpeg_blob_id: CAMERA3_JPEG_BLOB_ID, + jpeg_size: (uint32_t)width + }; + + size_t totalSize = static_cast<size_t>(width) + sizeof(footer); + size_t padding = ((totalSize - 1) & ~0x3) + 4; // align to next octonibble + totalSize += padding; + if (anb->width != totalSize) { + ALOGE("%s: gralloc buffer wrong size to hold jpeg, failed to produce buffer."); + return BAD_VALUE; + } ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); @@ -289,12 +301,9 @@ static status_t produceFrame(const sp<ANativeWindow>& anw, err); return err; } - struct camera3_jpeg_blob footer = { - jpeg_blob_id: CAMERA3_JPEG_BLOB_ID, - jpeg_size: (uint32_t)width - }; memcpy(img, pixelBuffer, width); - memcpy(img + anb->width - sizeof(footer), &footer, sizeof(footer)); + memset(img + width, 0, padding); + memcpy(img + totalSize - sizeof(footer), &footer, sizeof(footer)); break; } default: { diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 81e887d..2dbd382 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -1239,7 +1239,7 @@ static const JNINativeMethod gBinderProxyMethods[] = { {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, - {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, + {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 38f146b..bd9e2f6 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -365,6 +365,8 @@ <integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_5">12</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_24">24</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_5">36</integer> + <string translatable="false" name="config_wifi_random_mac_oui">DA-A1-19</string> + <bool translatable="false" name="config_wifi_framework_cellular_handover_enable_user_triggered_adjustment">true</bool> <!-- Integer packet threshold used to allow scan while associated --> @@ -1844,4 +1846,9 @@ <item>71610</item> <item>732101</item> </string-array> + + <!-- Config determines whether to update phone object when voice registration + state changes. Voice radio tech change will always trigger an update of + phone object irrespective of this config --> + <bool name="config_switch_phone_on_voice_reg_state_change">true</bool> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index fd4b40f..9fc7801 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3440,7 +3440,10 @@ and a previously used application is known. --> <string name="whichSendApplicationNamed">Share with %1$s</string> <!-- Title of intent resolver dialog when selecting a HOME application to run. --> - <string name="whichHomeApplication">Select a home app</string> + <string name="whichHomeApplication">Select a Home app</string> + <!-- Title of intent resolver dialog when selecting a HOME application to run + and a previously used application is known. --> + <string name="whichHomeApplicationNamed">Use %1$s as Home</string> <!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title--> <string name="alwaysUse">Use by default for this action.</string> <!-- Title of the list of alternate options to complete an action shown when the diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5c246a4..72f756a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -322,6 +322,8 @@ <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_link_speed_5" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_link_speed_24" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_link_speed_5" /> + <java-symbol type="string" name="config_wifi_random_mac_oui" /> + <java-symbol type="bool" name="editable_voicemailnumber" /> <java-symbol type="bool" name="config_wifi_framework_cellular_handover_enable_user_triggered_adjustment" /> @@ -2064,4 +2066,6 @@ <java-symbol type="array" name="dial_string_replace" /> <java-symbol type="bool" name="config_restart_radio_on_pdp_fail_regular_deactivation" /> <java-symbol type="array" name="networks_not_clear_data" /> + <java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" /> + <java-symbol type="string" name="whichHomeApplicationNamed" /> </resources> diff --git a/docs/html/app.yaml b/docs/html/app.yaml index 9ffb775..520ee99 100644 --- a/docs/html/app.yaml +++ b/docs/html/app.yaml @@ -1,38 +1,25 @@ application: androidappdocs-staging version: 1 -runtime: python +runtime: python27 +threadsafe: true api_version: 1 +# compatibility: gae-1.9.4+ -# This file defines two mutually exclusive -# hander blocks: -# - a handler for use on a local dev_appserver -# during development or non-production doc build -# - a handler for use on a production gae -# instance. This handler requires that the -# docs files in the app have been compressed -# with divide_and_compress.py and that main.py -# and gae_shell/ are present. -# -# Only one of the handler blocks should be -# uncommented at any given time. By default, -# the development handler is exposed. +# handler for local staging servers +# WARNING: NOT FOR USE IN PRODUCTION + +# Use this handler definition with +# Google App Engine 1.9.4 or higher. +# NOT compatible with prior GAE versions handlers: # DEVELOPMENT HANDLER -# (this handler block *must* be commented -# out before pushing to a production server) -- url: / - static_dir: / +- url: /(.+) + static_files: \1 + upload: (.+) -# PRODUCTION GAE HANDLER -#- url: /gae_shell/static -# static_dir: gae_shell/static -# expiration: 1d -# -#- url: /gae_shell/.* -# script: /gae_shell/shell.py -# login: admin -# -#- url: .* -# script: main.py +# Direct default, blank requests +- url: / + static_files: index.html + upload: index.html
\ No newline at end of file diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 49e8b9d..df1b126 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -137,8 +137,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { private boolean mMutated; public AnimatedVectorDrawable() { - mAnimatedVectorState = new AnimatedVectorDrawableState( - new AnimatedVectorDrawableState(null)); + mAnimatedVectorState = new AnimatedVectorDrawableState(null); } private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res, @@ -160,10 +159,16 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { @Override public ConstantState getConstantState() { + mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations(); return mAnimatedVectorState; } @Override + public int getChangingConfigurations() { + return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations; + } + + @Override public void draw(Canvas canvas) { mAnimatedVectorState.mVectorDrawable.draw(canvas); if (isStarted()) { @@ -347,6 +352,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { mTargetNameMap.put(animClone, targetName); } } + } else { + mVectorDrawable = new VectorDrawable(); } } diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java index 4e709b5..faa89bf 100644 --- a/graphics/java/android/graphics/drawable/RippleBackground.java +++ b/graphics/java/android/graphics/drawable/RippleBackground.java @@ -106,7 +106,7 @@ class RippleBackground { public void setup(int maxRadius, int color, float density) { mColorOpaque = color | 0xFF000000; - mColorAlpha = Color.alpha(color); + mColorAlpha = Color.alpha(color) / 2; if (maxRadius != RippleDrawable.RADIUS_AUTO) { mHasMaxRadius = true; diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index f0a2072..e9e475c 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -289,7 +289,7 @@ public class GpsNetInitiatedHandler { + " mPopupImmediately: " + mPopupImmediately + " mInEmergency: " + getInEmergency()); - if (getLocationEnabled() && !getInEmergency()) { + if (!getLocationEnabled() && !getInEmergency()) { // Location is currently disabled, ignore all NI requests. try { mNetInitiatedListener.sendNiResponse(notif.notificationId, diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index b786f94..b541454 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -642,7 +642,7 @@ public class ImageReader implements AutoCloseable { private void createSurfacePlanes() { mPlanes = new SurfacePlane[ImageReader.this.mNumPlanes]; for (int i = 0; i < ImageReader.this.mNumPlanes; i++) { - mPlanes[i] = nativeCreatePlane(i); + mPlanes[i] = nativeCreatePlane(i, ImageReader.this.mFormat); } } private class SurfacePlane extends android.media.Image.Plane { @@ -661,7 +661,8 @@ public class ImageReader implements AutoCloseable { if (mBuffer != null) { return mBuffer; } else { - mBuffer = SurfaceImage.this.nativeImageGetBuffer(mIndex); + mBuffer = SurfaceImage.this.nativeImageGetBuffer(mIndex, + ImageReader.this.mFormat); // Set the byteBuffer order according to host endianness (native order), // otherwise, the byteBuffer order defaults to ByteOrder.BIG_ENDIAN. return mBuffer.order(ByteOrder.nativeOrder()); @@ -711,8 +712,8 @@ public class ImageReader implements AutoCloseable { private SurfacePlane[] mPlanes; private boolean mIsImageValid; - private synchronized native ByteBuffer nativeImageGetBuffer(int idx); - private synchronized native SurfacePlane nativeCreatePlane(int idx); + private synchronized native ByteBuffer nativeImageGetBuffer(int idx, int readerFormat); + private synchronized native SurfacePlane nativeCreatePlane(int idx, int readerFormat); } private synchronized native void nativeInit(Object weakSelf, int w, int h, diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 5fb4f12..420510a 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -827,8 +827,13 @@ final public class MediaCodec { invalidateByteBuffer(mCachedInputBuffers, index); mDequeuedInputBuffers.remove(index); } - native_queueInputBuffer( - index, offset, size, presentationTimeUs, flags); + try { + native_queueInputBuffer( + index, offset, size, presentationTimeUs, flags); + } catch (CryptoException | IllegalStateException e) { + revalidateByteBuffer(mCachedInputBuffers, index); + throw e; + } } private native final void native_queueInputBuffer( @@ -947,8 +952,13 @@ final public class MediaCodec { invalidateByteBuffer(mCachedInputBuffers, index); mDequeuedInputBuffers.remove(index); } - native_queueSecureInputBuffer( - index, offset, info, presentationTimeUs, flags); + try { + native_queueSecureInputBuffer( + index, offset, info, presentationTimeUs, flags); + } catch (CryptoException | IllegalStateException e) { + revalidateByteBuffer(mCachedInputBuffers, index); + throw e; + } } private native final void native_queueSecureInputBuffer( @@ -1270,6 +1280,18 @@ final public class MediaCodec { } } + private final void revalidateByteBuffer( + ByteBuffer[] buffers, int index) { + synchronized(mBufferLock) { + if (buffers != null && index >= 0 && index < buffers.length) { + ByteBuffer buffer = buffers[index]; + if (buffer != null) { + buffer.setAccessible(true); + } + } + } + } + private final void validateOutputByteBuffer( ByteBuffer[] buffers, int index, BufferInfo info) { if (buffers != null && index >= 0 && index < buffers.length) { @@ -1307,7 +1329,7 @@ final public class MediaCodec { } private final void freeAllTrackedBuffers() { - synchronized (mBufferLock) { + synchronized(mBufferLock) { freeByteBuffers(mCachedInputBuffers); freeByteBuffers(mCachedOutputBuffers); mCachedInputBuffers = null; diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java index 0dcbd65..bb848d9 100644 --- a/media/java/android/media/MediaCodecList.java +++ b/media/java/android/media/MediaCodecList.java @@ -204,7 +204,7 @@ final public class MediaCodecList { * requests, or {@code null} if no such codec has been found. */ public final String findEncoderForFormat(MediaFormat format) { - return findCodecForFormat(false /* encoder */, format); + return findCodecForFormat(true /* encoder */, format); } private String findCodecForFormat(boolean encoder, MediaFormat format) { diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java index 0f9bded..3e5919f 100644 --- a/media/java/android/media/browse/MediaBrowser.java +++ b/media/java/android/media/browse/MediaBrowser.java @@ -713,6 +713,7 @@ public final class MediaBrowser { // We make a new mServiceCallbacks each time we connect so that we can drop // responses from previous connections. mServiceCallbacks = getNewServiceCallbacks(); + mState = CONNECT_STATE_CONNECTING; // Call connect, which is async. When we get a response from that we will // say that we're connected. diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index cfbf3af..e490c2b 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -918,7 +918,8 @@ public final class MediaController { @Override public void onQueueChanged(ParceledListSlice parceledQueue) { - List<MediaSession.QueueItem> queue = parceledQueue.getList(); + List<MediaSession.QueueItem> queue = parceledQueue == null ? null : parceledQueue + .getList(); MediaController controller = mController.get(); if (controller != null) { controller.postMessage(MSG_UPDATE_QUEUE, queue, null); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 2c38697..ad018ad 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -427,7 +427,7 @@ public final class MediaSession { */ public void setQueue(@Nullable List<QueueItem> queue) { try { - mBinder.setQueue(new ParceledListSlice<QueueItem>(queue)); + mBinder.setQueue(queue == null ? null : new ParceledListSlice<QueueItem>(queue)); } catch (RemoteException e) { Log.wtf("Dead object in setQueue.", e); } diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index fa4439d..a734774 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -317,8 +317,18 @@ static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer) return size; } +static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat) +{ + // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW + // write limitations for some platforms (b/17379185). + if (readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) { + return HAL_PIXEL_FORMAT_BLOB; + } + return bufferFormat; +} + static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, - uint8_t **base, uint32_t *size) + uint8_t **base, uint32_t *size, int32_t readerFormat) { ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); ALOG_ASSERT(base != NULL, "base is NULL!!!"); @@ -334,6 +344,8 @@ static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* bu dataSize = ySize = cSize = cStride = 0; int32_t fmt = buffer->format; + + fmt = applyFormatOverrides(fmt, readerFormat); switch (fmt) { case HAL_PIXEL_FORMAT_YCbCr_420_888: pData = @@ -458,7 +470,8 @@ static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* bu *size = dataSize; } -static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx) +static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, + int32_t readerFormat) { ALOGV("%s: buffer index: %d", __FUNCTION__, idx); ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx); @@ -467,6 +480,9 @@ static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* bu ALOG_ASSERT(buffer != NULL, "buffer is NULL"); int32_t fmt = buffer->format; + + fmt = applyFormatOverrides(fmt, readerFormat); + switch (fmt) { case HAL_PIXEL_FORMAT_YCbCr_420_888: pixelStride = (idx == 0) ? 1 : buffer->chromaStep; @@ -515,7 +531,8 @@ static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* bu return pixelStride; } -static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx) +static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, + int32_t readerFormat) { ALOGV("%s: buffer index: %d", __FUNCTION__, idx); ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); @@ -525,6 +542,8 @@ static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buff int32_t fmt = buffer->format; + fmt = applyFormatOverrides(fmt, readerFormat); + switch (fmt) { case HAL_PIXEL_FORMAT_YCbCr_420_888: rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride; @@ -777,9 +796,10 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, outputHeight = buffer->crop.getHeight(); } + int imgReaderFmt = ctx->getBufferFormat(); int imageReaderWidth = ctx->getBufferWidth(); int imageReaderHeight = ctx->getBufferHeight(); - if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && + if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) && (imageReaderWidth != outputWidth || imageReaderHeight > outputHeight)) { /** * For video decoder, the buffer height is actually the vertical stride, @@ -795,15 +815,19 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, return -1; } - int imgReaderFmt = ctx->getBufferFormat(); int bufFmt = buffer->format; if (imgReaderFmt != bufFmt) { - // Special casing for when producer switches to a format compatible with flexible YUV - // (HAL_PIXEL_FORMAT_YCbCr_420_888). + if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt == HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) { + // Special casing for when producer switches to a format compatible with flexible YUV + // (HAL_PIXEL_FORMAT_YCbCr_420_888). ctx->setBufferFormat(bufFmt); - ALOGV("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt); + ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt); + } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) { + // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW + // write limitations for (b/17379185). + ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__); } else { // Return the buffer to the queue. consumer->unlockBuffer(*buffer); @@ -843,7 +867,7 @@ static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz) return android_view_Surface_createFromIGraphicBufferProducer(env, gbp); } -static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx) +static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat) { int rowStride, pixelStride; ALOGV("%s: buffer index: %d", __FUNCTION__, idx); @@ -854,8 +878,11 @@ static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx) if (buffer == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); } - rowStride = Image_imageGetRowStride(env, buffer, idx); - pixelStride = Image_imageGetPixelStride(env, buffer, idx); + + readerFormat = Image_getPixelFormat(env, readerFormat); + + rowStride = Image_imageGetRowStride(env, buffer, idx, readerFormat); + pixelStride = Image_imageGetPixelStride(env, buffer, idx, readerFormat); jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz, gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride); @@ -863,7 +890,7 @@ static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx) return surfPlaneObj; } -static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx) +static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat) { uint8_t *base = NULL; uint32_t size = 0; @@ -877,8 +904,10 @@ static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx) jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); } + readerFormat = Image_getPixelFormat(env, readerFormat); + // Create byteBuffer from native buffer - Image_getLockedBufferInfo(env, buffer, idx, &base, &size); + Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerFormat); if (size > static_cast<uint32_t>(INT32_MAX)) { // Byte buffer have 'int capacity', so check the range @@ -910,8 +939,8 @@ static JNINativeMethod gImageReaderMethods[] = { }; static JNINativeMethod gImageMethods[] = { - {"nativeImageGetBuffer", "(I)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer }, - {"nativeCreatePlane", "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;", + {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer }, + {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;", (void*)Image_createSurfacePlane }, }; diff --git a/packages/SystemUI/res/anim/zen_toast_enter.xml b/packages/SystemUI/res/anim/zen_toast_enter.xml new file mode 100644 index 0000000..e236782 --- /dev/null +++ b/packages/SystemUI/res/anim/zen_toast_enter.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:interpolator/decelerate_quad" + android:fromAlpha="0.0" android:toAlpha="1.0" + android:duration="@integer/zen_toast_animation_duration" /> diff --git a/packages/SystemUI/res/anim/zen_toast_exit.xml b/packages/SystemUI/res/anim/zen_toast_exit.xml new file mode 100644 index 0000000..a9b1ab2 --- /dev/null +++ b/packages/SystemUI/res/anim/zen_toast_exit.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:interpolator/accelerate_quad" + android:fromAlpha="1.0" android:toAlpha="0.0" + android:duration="@integer/zen_toast_animation_duration" /> diff --git a/packages/SystemUI/res/drawable/ic_zen_important.xml b/packages/SystemUI/res/drawable/ic_zen_important.xml new file mode 100644 index 0000000..11e9063 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_zen_important.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.0,17.273l6.1800003,3.7269993 -1.6350002,-7.0290003 5.455,-4.7269993 -7.191,-0.6170006 -2.809,-6.627 -2.809,6.627 -7.191,0.6170006 5.455,4.7269993 -1.6349998,7.0290003z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_zen_none.xml b/packages/SystemUI/res/drawable/ic_zen_none.xml new file mode 100644 index 0000000..681d499 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_zen_none.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0c0.0,11.0 9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0C44.0,13.0 35.0,4.0 24.0,4.0zM24.0,40.0c-8.8,0.0 -16.0,-7.2 -16.0,-16.0c0.0,-3.7 1.3,-7.1 3.4,-9.8l22.4,22.4C31.1,38.7 27.7,40.0 24.0,40.0zM36.6,33.8L14.2,11.4C16.9,9.3 20.3,8.0 24.0,8.0c8.8,0.0 16.0,7.2 16.0,16.0C40.0,27.7 38.7,31.1 36.6,33.8z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/zen_toast_background.xml b/packages/SystemUI/res/drawable/zen_toast_background.xml new file mode 100644 index 0000000..619fe20 --- /dev/null +++ b/packages/SystemUI/res/drawable/zen_toast_background.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/system_primary_color" /> + <corners android:radius="@dimen/notification_material_rounded_rect_radius" /> +</shape> diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml index d0fba20..ece6979 100644 --- a/packages/SystemUI/res/layout/zen_mode_panel.xml +++ b/packages/SystemUI/res/layout/zen_mode_panel.xml @@ -44,6 +44,7 @@ android:id="@+id/zen_subhead" android:layout_width="match_parent" android:layout_height="62dp" + android:gravity="center_vertical" android:paddingLeft="8dp" android:paddingRight="8dp" > diff --git a/packages/SystemUI/res/layout/zen_toast.xml b/packages/SystemUI/res/layout/zen_toast.xml new file mode 100644 index 0000000..1e3d3cf --- /dev/null +++ b/packages/SystemUI/res/layout/zen_toast.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/zen_toast_background" + android:translationZ="@dimen/volume_panel_z" + android:padding="18dp" + android:gravity="center_horizontal" + android:orientation="vertical" > + + <ImageView + android:id="@android:id/icon" + android:layout_width="32dp" + android:layout_height="32dp" + android:scaleType="center" /> + + <TextView + android:id="@android:id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="12dp" + android:lineSpacingExtra="4dp" + android:gravity="center_horizontal" + android:textAppearance="@style/TextAppearance.QS.ZenToast" /> + +</LinearLayout> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 2e6f898..13170ad 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -239,5 +239,11 @@ <!-- Number of times to show the strong alarm warning text in the volume dialog --> <integer name="zen_mode_alarm_warning_threshold">5</integer> + + <!-- Zen toast fade in/out duration --> + <integer name="zen_toast_animation_duration">500</integer> + + <!-- Zen toast visibility duration --> + <integer name="zen_toast_visible_duration">500</integer> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index c690ef4..4f41cd5 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -193,6 +193,9 @@ <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen> + <!-- Explicit width of the zen toast window --> + <dimen name="zen_toast_width">224dp</dimen> + <!-- used by DessertCase --> <dimen name="dessert_case_cell_size">192dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e9a1acf..48450dd 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -900,10 +900,10 @@ <!-- Body of notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=60] --> <string name="hidden_notifications_text">See them before you unlock</string> - <!-- Cancel action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=10] --> + <!-- Cancel action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=20] --> <string name="hidden_notifications_cancel">No thanks</string> - <!-- continue action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=10] --> + <!-- continue action for notification educating the user about enabling notifications on the lockscreen. [CHAR LIMIT=20] --> <string name="hidden_notifications_setup">Set up</string> <!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] --> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 46e7587..909dc42 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -167,6 +167,10 @@ <item name="android:textColor">@color/qs_subhead</item> </style> + <style name="TextAppearance.QS.ZenToast"> + <item name="android:textSize">14sp</item> + </style> + <style name="TextAppearance.QS.SegmentedButton"> <item name="android:textSize">14sp</item> <item name="android:textAllCaps">true</item> @@ -262,4 +266,9 @@ <style name="UserDetailView"> <item name="numColumns">3</item> </style> + + <style name="ZenToastAnimations"> + <item name="android:windowEnterAnimation">@anim/zen_toast_enter</item> + <item name="android:windowExitAnimation">@anim/zen_toast_exit</item> + </style> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java index 61ed095..d8d7042 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java @@ -62,7 +62,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio IntentFilter filter = new IntentFilter(); filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION); - context.registerReceiver(this, filter); + context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mStatusBarManager diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 2b541d3..c1681c7 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -78,6 +78,7 @@ public class ZenModePanel extends LinearLayout { private final Interpolator mFastOutSlowInInterpolator; private final int mSubheadWarningColor; private final int mSubheadColor; + private final ZenToast mZenToast; private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this)); @@ -112,6 +113,7 @@ public class ZenModePanel extends LinearLayout { final Resources res = mContext.getResources(); mSubheadWarningColor = res.getColor(R.color.system_warning_color); mSubheadColor = res.getColor(R.color.qs_subhead); + mZenToast = new ZenToast(mContext); if (DEBUG) Log.d(mTag, "new ZenModePanel"); } @@ -155,6 +157,7 @@ public class ZenModePanel extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); if (DEBUG) Log.d(mTag, "onAttachedToWindow"); + mZenToast.hide(); mAttachedZen = getSelectedZen(-1); mSessionZen = mAttachedZen; mSessionExitCondition = copy(mExitCondition); @@ -187,6 +190,10 @@ public class ZenModePanel extends LinearLayout { if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) { mPrefs.trackNoneSelected(); } + if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS + || selectedZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + mZenToast.show(selectedZen); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java b/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java new file mode 100644 index 0000000..96e2a8e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume; + +import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.os.Message; +import android.os.UserHandle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.systemui.R; + +public class ZenToast { + private static final String ACTION_SHOW = ZenToast.class.getName() + ".SHOW"; + private static final String ACTION_HIDE = ZenToast.class.getName() + ".HIDE"; + private static final String EXTRA_ZEN = "zen"; + private static final String EXTRA_TEXT = "text"; + + private static final int MSG_SHOW = 1; + private static final int MSG_HIDE = 2; + + private final Context mContext; + private final WindowManager mWindowManager; + + private View mZenToast; + + public ZenToast(Context context) { + mContext = context; + mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + final IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_SHOW); + filter.addAction(ACTION_HIDE); + mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); + } + + public void show(int zen) { + mHandler.removeMessages(MSG_HIDE); + mHandler.removeMessages(MSG_SHOW); + mHandler.obtainMessage(MSG_SHOW, zen, 0).sendToTarget(); + } + + public void hide() { + mHandler.removeMessages(MSG_HIDE); + mHandler.removeMessages(MSG_SHOW); + mHandler.obtainMessage(MSG_HIDE).sendToTarget(); + } + + private void handleShow(int zen, String overrideText) { + handleHide(); + + String text; + final int iconRes; + switch (zen) { + case ZEN_MODE_NO_INTERRUPTIONS: + text = mContext.getString(R.string.zen_no_interruptions); + iconRes = R.drawable.ic_zen_none; + break; + case ZEN_MODE_IMPORTANT_INTERRUPTIONS: + text = mContext.getString(R.string.zen_important_interruptions); + iconRes = R.drawable.ic_zen_important; + break; + default: + return; + } + if (overrideText != null) { + text = overrideText; + } + final Resources res = mContext.getResources(); + final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = res.getDimensionPixelSize(R.dimen.zen_toast_width); + params.format = PixelFormat.TRANSLUCENT; + params.windowAnimations = R.style.ZenToastAnimations; + params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; + params.setTitle(getClass().getSimpleName()); + params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + params.gravity = Gravity.CENTER; + params.packageName = mContext.getPackageName(); + mZenToast = LayoutInflater.from(mContext).inflate(R.layout.zen_toast, null); + final TextView message = (TextView) mZenToast.findViewById(android.R.id.message); + message.setText(text); + final ImageView icon = (ImageView) mZenToast.findViewById(android.R.id.icon); + icon.setImageResource(iconRes); + mWindowManager.addView(mZenToast, params); + final int animDuration = res.getInteger(R.integer.zen_toast_animation_duration); + final int visibleDuration = res.getInteger(R.integer.zen_toast_visible_duration); + mHandler.sendEmptyMessageDelayed(MSG_HIDE, animDuration + visibleDuration); + } + + private void handleHide() { + if (mZenToast != null) { + mWindowManager.removeView(mZenToast); + mZenToast = null; + } + } + + private final Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SHOW: + handleShow(msg.arg1, null); + break; + case MSG_HIDE: + handleHide(); + break; + } + } + }; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_SHOW.equals(intent.getAction())) { + final int zen = intent.getIntExtra(EXTRA_ZEN, ZEN_MODE_IMPORTANT_INTERRUPTIONS); + final String text = intent.getStringExtra(EXTRA_TEXT); + handleShow(zen, text); + } else if (ACTION_HIDE.equals(intent.getAction())) { + handleHide(); + } + } + }; +} diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 00026dc..42ee666 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -274,6 +274,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private long mBackgroundFadeDurationMillis = -1; private Boolean mSharedElementsUseOverlay; + private Rect mTempRect; + static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService("window")); @@ -2892,37 +2894,53 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // Show the status guard when the non-overlay contextual action bar is showing if (mActionModeView != null) { if (mActionModeView.getLayoutParams() instanceof MarginLayoutParams) { - MarginLayoutParams mlp = (MarginLayoutParams) mActionModeView.getLayoutParams(); + // Insets are magic! + final MarginLayoutParams mlp = (MarginLayoutParams) + mActionModeView.getLayoutParams(); boolean mlpChanged = false; if (mActionModeView.isShown()) { - final boolean nonOverlay = (getLocalFeatures() - & (1 << FEATURE_ACTION_MODE_OVERLAY)) == 0; - if (mlp.topMargin != insets.getSystemWindowInsetTop()) { + if (mTempRect == null) { + mTempRect = new Rect(); + } + final Rect rect = mTempRect; + + // If the parent doesn't consume the insets, manually + // apply the default system window insets. + mContentParent.computeSystemWindowInsets(insets, rect); + final int newMargin = rect.top == 0 ? insets.getSystemWindowInsetTop() : 0; + if (mlp.topMargin != newMargin) { mlpChanged = true; mlp.topMargin = insets.getSystemWindowInsetTop(); - // Only show status guard for non-overlay modes. - if (nonOverlay) { - if (mStatusGuard == null) { - mStatusGuard = new View(mContext); - mStatusGuard.setBackgroundColor(mContext.getResources() - .getColor(R.color.input_method_navigation_guard)); - addView(mStatusGuard, indexOfChild(mStatusColorView), - new LayoutParams(LayoutParams.MATCH_PARENT, - mlp.topMargin, - Gravity.START | Gravity.TOP)); - } else { - LayoutParams lp = (LayoutParams) mStatusGuard.getLayoutParams(); - if (lp.height != mlp.topMargin) { - lp.height = mlp.topMargin; - mStatusGuard.setLayoutParams(lp); - } + if (mStatusGuard == null) { + mStatusGuard = new View(mContext); + mStatusGuard.setBackgroundColor(mContext.getResources() + .getColor(R.color.input_method_navigation_guard)); + addView(mStatusGuard, indexOfChild(mStatusColorView), + new LayoutParams(LayoutParams.MATCH_PARENT, + mlp.topMargin, Gravity.START | Gravity.TOP)); + } else { + final LayoutParams lp = (LayoutParams) + mStatusGuard.getLayoutParams(); + if (lp.height != mlp.topMargin) { + lp.height = mlp.topMargin; + mStatusGuard.setLayoutParams(lp); } } } + + // We only need to consume the insets if the action + // mode is overlaid on the app content (e.g. it's + // sitting in a FrameLayout, see + // screen_simple_overlay_action_mode.xml). + final boolean nonOverlay = (getLocalFeatures() + & (1 << FEATURE_ACTION_MODE_OVERLAY)) == 0; insets = insets.consumeSystemWindowInsets( false, nonOverlay /* top */, false, false); - showStatusGuard = nonOverlay; + + // The action mode's theme may differ from the app, so + // always show the status guard above it. + showStatusGuard = true; } else { // reset top margin if (mlp.topMargin != 0) { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index ac78630..be3fc47 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -759,7 +759,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } int getActiveWindowId() { - return mSecurityPolicy.mActiveWindowId; + return mSecurityPolicy.getActiveWindowId(); } void onTouchInteractionStart() { @@ -1169,7 +1169,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // No enabled installed services => disable accessibility to avoid // sending accessibility events with no recipient across processes. - if (isEnabled && userState.mEnabledServices.isEmpty()) { + if (isEnabled && userState.mBoundServices.isEmpty() + && userState.mBindingServices.isEmpty()) { userState.mIsAccessibilityEnabled = false; Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId); @@ -2599,6 +2600,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mInstalledServices.remove(mAccessibilityServiceInfo); userState.mEnabledServices.remove(mComponentName); userState.destroyUiAutomationService(); + if (readConfigurationForUserStateLocked(userState)) { + onUserStateChangedLocked(userState); + } } } } @@ -2819,7 +2823,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) { - return mSecurityPolicy.mActiveWindowId; + return mSecurityPolicy.getActiveWindowId(); } return accessibilityWindowId; } @@ -3280,7 +3284,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void clearWindowsLocked() { List<AccessibilityWindowInfo> windows = Collections.emptyList(); + final int activeWindowId = mActiveWindowId; updateWindowsLocked(windows); + mActiveWindowId = activeWindowId; mWindows = null; } @@ -3493,6 +3499,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + public int getActiveWindowId() { + if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) { + mActiveWindowId = getFocusedWindowId(); + } + return mActiveWindowId; + } + private void setActiveWindowLocked(int windowId) { if (mActiveWindowId != windowId) { mActiveWindowId = windowId; diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index e88bdf8..f1d5aa3 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -38,6 +38,7 @@ public class MasterClearReceiver extends BroadcastReceiver { } final boolean shutdown = intent.getBooleanExtra("shutdown", false); + final String reason = intent.getStringExtra(Intent.EXTRA_REASON); Slog.w(TAG, "!!! FACTORY RESET !!!"); // The reboot call is blocking, so we need to do it on another thread. @@ -45,7 +46,7 @@ public class MasterClearReceiver extends BroadcastReceiver { @Override public void run() { try { - RecoverySystem.rebootWipeUserData(context, shutdown); + RecoverySystem.rebootWipeUserData(context, shutdown, reason); Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 8e8e4a6..01e80b7 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2134,7 +2134,8 @@ public final class ActiveServices { if (!hasCreate) { continue; } - if (proc != null && !proc.persistent && proc.thread != null + // XXX turned off for now until we have more time to get a better policy. + if (false && proc != null && !proc.persistent && proc.thread != null && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { proc.kill("bound to service " + sr.name.flattenToShortString() diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d2e3d25..4d2fd4c 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4690,8 +4690,8 @@ public final class ActivityManagerService extends ActivityManagerNative private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; - cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); - if (!restarting) { + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); + if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { ProcessList.remove(pid); @@ -4816,6 +4816,14 @@ public final class ActivityManagerService extends ActivityManagerNative } final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread) { + // First check if this ProcessRecord is actually active for the pid. + synchronized (mPidsSelfLocked) { + ProcessRecord curProc = mPidsSelfLocked.get(pid); + if (curProc != app) { + Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc); + return; + } + } BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { @@ -4833,7 +4841,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean doOomAdj = doLowMem; if (!app.killedByAm) { Slog.i(TAG, "Process " + app.processName + " (pid " + pid - + ") has died."); + + ") has died"); mAllowLowerMemLevel = true; } else { // Note that we always want to do oom adj to update our state with the @@ -14310,8 +14318,11 @@ public final class ActivityManagerService extends ActivityManagerNative * Main code for cleaning up a process when it has gone away. This is * called both as a result of the process dying, or directly when stopping * a process when running in single process mode. + * + * @return Returns true if the given process has been restarted, so the + * app that was passed in must remain on the process lists. */ - private final void cleanUpApplicationRecordLocked(ProcessRecord app, + private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index) { if (index >= 0) { removeLruProcessLocked(app); @@ -14434,7 +14445,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If the caller is restarting this app, then leave it in its // current lists and let the caller take care of it. if (restarting) { - return; + return false; } if (!app.persistent || app.isolated) { @@ -14470,8 +14481,12 @@ public final class ActivityManagerService extends ActivityManagerNative if (restart && !app.isolated) { // We have components that still need to be running in the // process, so re-launch it. + if (index < 0) { + ProcessList.remove(app.pid); + } mProcessNames.put(app.processName, app.uid, app); startProcessLocked(app, "restart", app.processName); + return true; } else if (app.pid > 0 && app.pid != MY_PID) { // Goodbye! boolean removed; @@ -14485,6 +14500,7 @@ public final class ActivityManagerService extends ActivityManagerNative } app.setPid(0); } + return false; } boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 7f89947..15dcd44 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -695,6 +695,8 @@ public class InputManagerService extends IInputManager.Stub final int numFullKeyboards = mTempFullKeyboards.size(); boolean missingLayoutForExternalKeyboard = false; boolean missingLayoutForExternalKeyboardAdded = false; + boolean multipleMissingLayoutsForExternalKeyboardsAdded = false; + InputDevice keyboardMissingLayout = null; synchronized (mDataStore) { for (int i = 0; i < numFullKeyboards; i++) { final InputDevice inputDevice = mTempFullKeyboards.get(i); @@ -704,13 +706,25 @@ public class InputManagerService extends IInputManager.Stub missingLayoutForExternalKeyboard = true; if (i < numFullKeyboardsAdded) { missingLayoutForExternalKeyboardAdded = true; + if (keyboardMissingLayout == null) { + keyboardMissingLayout = inputDevice; + } else { + multipleMissingLayoutsForExternalKeyboardsAdded = true; + } } } } } if (missingLayoutForExternalKeyboard) { if (missingLayoutForExternalKeyboardAdded) { - showMissingKeyboardLayoutNotification(); + if (multipleMissingLayoutsForExternalKeyboardsAdded) { + // We have more than one keyboard missing a layout, so drop the + // user at the generic input methods page so they can pick which + // one to set. + showMissingKeyboardLayoutNotification(null); + } else { + showMissingKeyboardLayoutNotification(keyboardMissingLayout); + } } } else if (mKeyboardLayoutNotificationShown) { hideMissingKeyboardLayoutNotification(); @@ -761,16 +775,17 @@ public class InputManagerService extends IInputManager.Stub } // Must be called on handler. - private void showMissingKeyboardLayoutNotification() { + private void showMissingKeyboardLayoutNotification(InputDevice device) { if (!mKeyboardLayoutNotificationShown) { - if (mKeyboardLayoutIntent == null) { - final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS"); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0, - intent, 0, null, UserHandle.CURRENT); + final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS); + if (device != null) { + intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier()); } + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0, + intent, 0, null, UserHandle.CURRENT); Resources r = mContext.getResources(); Notification notification = new Notification.Builder(mContext) @@ -778,7 +793,7 @@ public class InputManagerService extends IInputManager.Stub R.string.select_keyboard_layout_notification_title)) .setContentText(r.getString( R.string.select_keyboard_layout_notification_message)) - .setContentIntent(mKeyboardLayoutIntent) + .setContentIntent(keyboardLayoutIntent) .setSmallIcon(R.drawable.ic_settings_language) .setPriority(Notification.PRIORITY_LOW) .setColor(mContext.getResources().getColor( diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 2829e2b..d8e5a98 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -154,6 +154,16 @@ public class NotificationManagerService extends SystemService { static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true; static final boolean ENABLE_BLOCKED_TOASTS = true; + // When #matchesCallFilter is called from the ringer, wait at most + // 3s to resolve the contacts. This timeout is required since + // ContactsProvider might take a long time to start up. + // + // Return STARRED_CONTACT when the timeout is hit in order to avoid + // missed calls in ZEN mode "Important". + static final int MATCHES_CALL_FILTER_CONTACTS_TIMEOUT_MS = 3000; + static final float MATCHES_CALL_FILTER_TIMEOUT_AFFINITY = + ValidateNotificationPeople.STARRED_CONTACT; + private IActivityManager mAm; AudioManager mAudioManager; StatusBarManagerInternal mStatusBar; @@ -1474,8 +1484,12 @@ public class NotificationManagerService extends SystemService { @Override public boolean matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); - return mZenModeHelper.matchesCallFilter(UserHandle.getCallingUserHandle(), extras, - mRankingHelper.findExtractor(ValidateNotificationPeople.class)); + return mZenModeHelper.matchesCallFilter( + UserHandle.getCallingUserHandle(), + extras, + mRankingHelper.findExtractor(ValidateNotificationPeople.class), + MATCHES_CALL_FILTER_CONTACTS_TIMEOUT_MS, + MATCHES_CALL_FILTER_TIMEOUT_AFFINITY); } }; diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index 1c1a034..6e2a8ad 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -22,6 +22,7 @@ import android.content.pm.PackageManager; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; @@ -37,6 +38,8 @@ import android.util.Slog; import java.util.ArrayList; import java.util.LinkedList; import java.util.Map; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; /** * This {@link NotificationSignalExtractor} attempts to validate @@ -45,9 +48,10 @@ import java.util.Map; * {@hide} */ public class ValidateNotificationPeople implements NotificationSignalExtractor { - private static final String TAG = "ValidateNotificationPeople"; + // Using a shorter log tag since setprop has a limit of 32chars on variable name. + private static final String TAG = "ValidateNoPeople"; private static final boolean INFO = true; - private static final boolean DEBUG = false; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean ENABLE_PEOPLE_VALIDATOR = true; private static final String SETTING_ENABLE_PEOPLE_VALIDATOR = @@ -132,7 +136,14 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { // ignore: config has no relevant information yet. } - public float getContactAffinity(UserHandle userHandle, Bundle extras) { + /** + * @param extras extras of the notification with EXTRA_PEOPLE populated + * @param timeoutMs timeout in milliseconds to wait for contacts response + * @param timeoutAffinity affinity to return when the timeout specified via + * <code>timeoutMs</code> is hit + */ + public float getContactAffinity(UserHandle userHandle, Bundle extras, int timeoutMs, + float timeoutAffinity) { if (DEBUG) Slog.d(TAG, "checking affinity for " + userHandle); if (extras == null) return NONE; final String key = Long.toString(System.nanoTime()); @@ -143,8 +154,31 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { } final PeopleRankingReconsideration prr = validatePeople(context, key, extras, affinityOut); float affinity = affinityOut[0]; + if (prr != null) { - prr.work(); + // Perform the heavy work on a background thread so we can abort when we hit the + // timeout. + final Semaphore s = new Semaphore(0); + AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + prr.work(); + s.release(); + } + }); + + try { + if (!s.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { + Slog.w(TAG, "Timeout while waiting for affinity: " + key + ". " + + "Returning timeoutAffinity=" + timeoutAffinity); + return timeoutAffinity; + } + } catch (InterruptedException e) { + Slog.w(TAG, "InterruptedException while waiting for affinity: " + key + ". " + + "Returning affinity=" + affinity, e); + return affinity; + } + affinity = Math.max(prr.getContactAffinity(), affinity); } return affinity; @@ -391,6 +425,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { @Override public void work() { if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey); + long timeStartMs = System.currentTimeMillis(); for (final String handle: mPendingLookups) { LookupResult lookupResult = null; final Uri uri = Uri.parse(handle); @@ -415,6 +450,10 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); } } + if (DEBUG) { + Slog.d(TAG, "Validation finished in " + (System.currentTimeMillis() - timeStartMs) + + "ms"); + } } @Override diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 5038d03..557a44e 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -376,14 +376,21 @@ public class ZenModeHelper { return record.isCategory(Notification.CATEGORY_MESSAGE) || isDefaultMessagingApp(record); } + /** + * @param extras extras of the notification with EXTRA_PEOPLE populated + * @param contactsTimeoutMs timeout in milliseconds to wait for contacts response + * @param timeoutAffinity affinity to return when the timeout specified via + * <code>contactsTimeoutMs</code> is hit + */ public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, - ValidateNotificationPeople validator) { + ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { final int zen = mZenMode; if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { if (!mConfig.allowCalls) return false; // no calls get through if (validator != null) { - final float contactAffinity = validator.getContactAffinity(userHandle, extras); + final float contactAffinity = validator.getContactAffinity(userHandle, extras, + contactsTimeoutMs, timeoutAffinity); return audienceMatches(contactAffinity); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java index 5938819..9fd0e09 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java @@ -229,11 +229,20 @@ public class DeviceOwner { String profileOwnerComponentStr = parser.getAttributeValue(null, ATTR_COMPONENT_NAME); int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID)); - OwnerInfo profileOwnerInfo; + OwnerInfo profileOwnerInfo = null; if (profileOwnerComponentStr != null) { - profileOwnerInfo = new OwnerInfo(profileOwnerName, - ComponentName.unflattenFromString(profileOwnerComponentStr)); - } else { + ComponentName admin = ComponentName.unflattenFromString( + profileOwnerComponentStr); + if (admin != null) { + profileOwnerInfo = new OwnerInfo(profileOwnerName, admin); + } else { + // This shouldn't happen but switch from package name -> component name + // might have written bad device owner files. b/17652534 + Slog.e(TAG, "Error parsing device-owner file. Bad component name " + + profileOwnerComponentStr); + } + } + if (profileOwnerInfo == null) { profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName); } mProfileOwners.put(userId, profileOwnerInfo); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 59d3dc8..d1aba3c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2862,7 +2862,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } - void wipeDataLocked(int flags) { + void wipeDataLocked(int flags, String reason) { // If the SD card is encrypted and non-removable, we have to force a wipe. boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted(); boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0; @@ -2871,12 +2871,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) { Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET); intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true); + intent.putExtra(Intent.EXTRA_REASON, reason); intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); mWakeLock.acquire(10000); mContext.startService(intent); } else { try { - RecoverySystem.rebootWipeUserData(mContext); + RecoverySystem.rebootWipeUserData(mContext, reason); } catch (IOException e) { Slog.w(LOG_TAG, "Failed requesting data wipe", e); } catch (SecurityException e) { @@ -2885,6 +2886,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override public void wipeData(int flags, final int userHandle) { if (!mHasFeature) { return; @@ -2896,20 +2898,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. - getActiveAdminForCallerLocked(null, + final ActiveAdmin admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA); + + final String source; + if (admin != null && admin.info != null) { + final ComponentName cname = admin.info.getComponent(); + if (cname != null) { + source = cname.flattenToShortString(); + } else { + source = admin.info.getPackageName(); + } + } else { + source = "?"; + } + long ident = Binder.clearCallingIdentity(); try { - wipeDeviceOrUserLocked(flags, userHandle); + wipeDeviceOrUserLocked(flags, userHandle, + "DevicePolicyManager.wipeData() from " + source); } finally { Binder.restoreCallingIdentity(ident); } } } - private void wipeDeviceOrUserLocked(int flags, final int userHandle) { + private void wipeDeviceOrUserLocked(int flags, final int userHandle, String reason) { if (userHandle == UserHandle.USER_OWNER) { - wipeDataLocked(flags); + wipeDataLocked(flags, reason); } else { mHandler.post(new Runnable() { public void run() { @@ -3061,7 +3077,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (wipeData) { // Call without holding lock. - wipeDeviceOrUserLocked(0, identifier); + wipeDeviceOrUserLocked(0, identifier, "reportFailedPasswordAttempt()"); } } finally { Binder.restoreCallingIdentity(ident); diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index ffe787a..1d6d8bc 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -286,9 +286,6 @@ public class PhoneAccount implements Parcelable { * The raw callback number used for this {@code PhoneAccount}, as distinct from * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration - * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} - * has been used to alter the callback number. - * <p> * * @return The subscription number, suitable for display to the user. */ diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java index 796725b..b18cb96 100644 --- a/telecomm/java/android/telecom/RemoteConference.java +++ b/telecomm/java/android/telecom/RemoteConference.java @@ -166,6 +166,20 @@ public final class RemoteConference { } } + public void merge() { + try { + mConnectionService.mergeConference(mId); + } catch (RemoteException e) { + } + } + + public void swap() { + try { + mConnectionService.swapConference(mId); + } catch (RemoteException e) { + } + } + public void hold() { try { mConnectionService.hold(mId); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 34b1454..6ba151f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1746,6 +1746,7 @@ public class TelephonyManager { * * @param alphaTag alpha-tagging of the dailing nubmer * @param number The dialing number + * @hide */ public void setLine1NumberForDisplay(String alphaTag, String number) { setLine1NumberForDisplayForSubscriber(getDefaultSubscription(), alphaTag, number); @@ -2381,7 +2382,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param AID Application id. See ETSI 102.221 and 101.220. * @return an IccOpenLogicalChannelResponse object. @@ -2402,7 +2402,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param channel is the channel id to be closed as retruned by a successful * iccOpenLogicalChannel. @@ -2424,7 +2423,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param channel is the channel id to be closed as returned by a successful * iccOpenLogicalChannel. @@ -2456,7 +2454,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param cla Class of the APDU command. * @param instruction Instruction of the APDU command. @@ -2484,7 +2481,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param fileID * @param command @@ -2510,7 +2506,6 @@ public class TelephonyManager { * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} - * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @param content String containing SAT/USAT response in hexadecimal * format starting with command tag. See TS 102 223 for @@ -2960,6 +2955,7 @@ public class TelephonyManager { * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * * @return true on success; false on any failure. + * @hide */ public boolean setGlobalPreferredNetworkType() { return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); @@ -2967,10 +2963,23 @@ public class TelephonyManager { /** * Values used to return status for hasCarrierPrivileges call. + * @hide */ public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; + /** + * Values used to return status for hasCarrierPrivileges call. + * @hide + */ public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; + /** + * Values used to return status for hasCarrierPrivileges call. + * @hide + */ public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; + /** + * Values used to return status for hasCarrierPrivileges call. + * @hide + */ public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; /** @@ -2987,6 +2996,7 @@ public class TelephonyManager { * CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED if the carrier rules are not loaded. * CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES if there was an error loading carrier * rules (or if there are no rules). + * @hide */ public int hasCarrierPrivileges() { try { @@ -3013,6 +3023,7 @@ public class TelephonyManager { * * @param brand The brand name to display/set. * @return true if the operation was executed correctly. + * @hide */ public boolean setOperatorBrandOverride(String brand) { try { diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java index 8b7c883..2455c9c 100644 --- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java +++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.graphics.Bitmap; import android.media.MediaMetadata; import android.media.session.MediaSession; +import android.media.session.MediaSession.QueueItem; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.Bundle; @@ -44,6 +45,8 @@ public class PlayerSession { protected MediaSession.Callback mCallback; protected Renderer.Listener mRenderListener; protected MediaMetadata.Builder mMetadataBuilder; + protected ArrayList<MediaSession.QueueItem> mQueue; + protected boolean mUseQueue; protected PlaybackState mPlaybackState; protected Listener mListener; @@ -58,6 +61,7 @@ public class PlayerSession { PlaybackState.Builder psBob = new PlaybackState.Builder(); psBob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY); mPlaybackState = psBob.build(); + mQueue = new ArrayList<MediaSession.QueueItem>(); mRenderer.registerListener(mRenderListener); @@ -114,6 +118,8 @@ public class PlayerSession { public void setIcon(Bitmap icon) { mMetadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, icon); + mQueue.clear(); + mQueue.add(new QueueItem(mMetadataBuilder.build().getDescription(), 11)); updateMetadata(); } @@ -122,6 +128,10 @@ public class PlayerSession { // code if (mSession != null && mSession.isActive()) { mSession.setMetadata(mMetadataBuilder.build()); + // Just toggle the queue every time we update for testing + mSession.setQueue(mUseQueue ? mQueue : null); + mSession.setQueueTitle(mUseQueue ? "Queue title" : null); + mUseQueue = !mUseQueue; } } @@ -141,6 +151,8 @@ public class PlayerSession { "OneMedia display title"); mMetadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, "OneMedia display subtitle"); + + mQueue.add(new QueueItem(mMetadataBuilder.build().getDescription(), 11)); } public interface Listener { diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml index 4c835ec..7796953 100644 --- a/tests/VectorDrawableTest/AndroidManifest.xml +++ b/tests/VectorDrawableTest/AndroidManifest.xml @@ -99,6 +99,15 @@ </intent-filter> </activity> <activity + android:name="AnimatedVectorDrawableDupPerf" + android:label="Animated Vector Performance of clones" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + </activity> + <activity android:name="VectorDrawableStaticPerf" android:label="System icons" > <intent-filter> diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml index 5c1ccaa..f0b4699 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml @@ -19,8 +19,7 @@ android:viewportHeight="400" android:viewportWidth="400" > - <group android:name="backgroundGroup" - android:alpha = "0.5" > + <group android:name="backgroundGroup"> <path android:name="background1" android:fillColor="#FF000000" @@ -33,8 +32,7 @@ <group android:name="translateToCenterGroup" android:translateX="50.0" - android:translateY="90.0" - android:alpha = "0.5" > + android:translateY="90.0" > <path android:name="twoLines" android:pathData="@string/twoLinePathData" @@ -45,8 +43,7 @@ android:name="rotationGroup" android:pivotX="0.0" android:pivotY="0.0" - android:rotation="-45.0" - android:alpha = "0.5" > + android:rotation="-45.0"> <path android:name="twoLines1" android:pathData="@string/twoLinePathData" @@ -56,8 +53,7 @@ <group android:name="translateGroup" android:translateX="130.0" - android:translateY="160.0" - android:alpha = "0.5"> + android:translateY="160.0"> <group android:name="scaleGroup" > <path android:name="twoLines3" @@ -70,8 +66,7 @@ <group android:name="translateGroupHalf" android:translateX="65.0" - android:translateY="80.0" - android:alpha = "0.5"> + android:translateY="80.0"> <group android:name="scaleGroup" > <path android:name="twoLines2" diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml index 069a531..f46d14e 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml @@ -21,12 +21,10 @@ <group android:name="FirstLevelGroup" - android:alpha="0.9" android:translateX="100.0" android:translateY="0.0" > <group android:name="SecondLevelGroup1" - android:alpha="0.9" android:translateX="-100.0" android:translateY="50.0" > <path @@ -35,7 +33,6 @@ <group android:name="ThridLevelGroup1" - android:alpha="0.9" android:translateX="-100.0" android:translateY="50.0" > <path @@ -44,7 +41,6 @@ </group> <group android:name="ThridLevelGroup2" - android:alpha="0.8" android:translateX="100.0" android:translateY="50.0" > <path @@ -54,7 +50,6 @@ </group> <group android:name="SecondLevelGroup2" - android:alpha="0.8" android:translateX="100.0" android:translateY="50.0" > <path @@ -63,7 +58,6 @@ <group android:name="ThridLevelGroup3" - android:alpha="0.9" android:translateX="-100.0" android:translateY="50.0" > <path @@ -72,7 +66,6 @@ </group> <group android:name="ThridLevelGroup4" - android:alpha="0.8" android:translateX="100.0" android:translateY="50.0" > <path diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java new file mode 100644 index 0000000..047e494 --- /dev/null +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.test.dynamic; + +import android.app.Activity; +import android.content.res.Resources; +import android.graphics.drawable.AnimatedVectorDrawable; +import android.graphics.drawable.VectorDrawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; +import android.widget.Button; +import android.widget.GridLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.text.DecimalFormat; + + +@SuppressWarnings({"UnusedDeclaration"}) +public class AnimatedVectorDrawableDupPerf extends Activity { + + private static final String LOGTAG = "AnimatedVectorDrawableDupPerf"; + protected int[] icon = { + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + R.drawable.animation_vector_linear_progress_bar, + }; + + /** @hide */ + public static AnimatedVectorDrawable create(Resources resources, int rid) { + try { + final XmlPullParser parser = resources.getXml(rid); + final AttributeSet attrs = Xml.asAttributeSet(parser); + int type; + while ((type=parser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty loop + } + if (type != XmlPullParser.START_TAG) { + throw new XmlPullParserException("No start tag found"); + } + + final AnimatedVectorDrawable drawable = new AnimatedVectorDrawable(); + drawable.inflate(resources, parser, attrs); + + return drawable; + } catch (XmlPullParserException e) { + Log.e(LOGTAG, "parser error", e); + } catch (IOException e) { + Log.e(LOGTAG, "parser error", e); + } + return null; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ScrollView scrollView = new ScrollView(this); + GridLayout container = new GridLayout(this); + scrollView.addView(container); + container.setColumnCount(5); + Resources res = this.getResources(); + container.setBackgroundColor(0xFF888888); + AnimatedVectorDrawable []d = new AnimatedVectorDrawable[icon.length]; + long time = android.os.SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < icon.length; i++) { + d[i] = create(res,icon[i]); + } + time = android.os.SystemClock.elapsedRealtimeNanos()-time; + TextView t = new TextView(this); + DecimalFormat df = new DecimalFormat("#.##"); + t.setText("avgL=" + df.format(time / (icon.length * 1000000.)) + " ms"); + container.addView(t); + time = android.os.SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < icon.length; i++) { + Button button = new Button(this); + button.setWidth(200); + button.setBackgroundResource(icon[i]); + container.addView(button); + } + setContentView(scrollView); + time = android.os.SystemClock.elapsedRealtimeNanos()-time; + t = new TextView(this); + t.setText("avgS=" + df.format(time / (icon.length * 1000000.)) + " ms"); + container.addView(t); + } + +} diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index b8c3454..77d3beb 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -3310,6 +3310,19 @@ ResourceTable::Entry::Entry(const Entry& entry) , mParentId(entry.mParentId) , mPos(entry.mPos) {} +ResourceTable::Entry& ResourceTable::Entry::operator=(const Entry& entry) { + mName = entry.mName; + mParent = entry.mParent; + mType = entry.mType; + mItem = entry.mItem; + mItemFormat = entry.mItemFormat; + mBag = entry.mBag; + mNameIndex = entry.mNameIndex; + mParentId = entry.mParentId; + mPos = entry.mPos; + return *this; +} + status_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos) { if (mType == TYPE_BAG) { @@ -4352,7 +4365,11 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { String8(entriesToAdd[i].value->getName()).string(), entriesToAdd[i].key.toString().string()); - c->addEntry(entriesToAdd[i].key, entriesToAdd[i].value); + sp<Entry> newEntry = t->getEntry(c->getName(), + entriesToAdd[i].value->getPos(), + &entriesToAdd[i].key); + + *newEntry = *entriesToAdd[i].value; } } } diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index c548a85..eac5dd3 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -316,6 +316,7 @@ public: { } Entry(const Entry& entry); + Entry& operator=(const Entry& entry); virtual ~Entry() { } |
