Merge "Fix index out of bounds exception"
diff --git a/api/current.txt b/api/current.txt
index a9e4d70..a263946 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2525,7 +2525,14 @@
public static final class R.transition {
ctor public R.transition();
+ field public static final int explode = 17760259; // 0x10f0003
+ field public static final int fade = 17760258; // 0x10f0002
+ field public static final int move = 17760257; // 0x10f0001
field public static final int no_transition = 17760256; // 0x10f0000
+ field public static final int slide_bottom = 17760260; // 0x10f0004
+ field public static final int slide_left = 17760263; // 0x10f0007
+ field public static final int slide_right = 17760262; // 0x10f0006
+ field public static final int slide_top = 17760261; // 0x10f0005
}
public static final class R.xml {
@@ -14483,6 +14490,11 @@
method public java.lang.String getDefaultUrl();
}
+ public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
+ ctor public MediaDrm.MediaDrmStateException(int, java.lang.String);
+ method public int getErrorCode();
+ }
+
public static abstract interface MediaDrm.OnEventListener {
method public abstract void onEvent(android.media.MediaDrm, byte[], int, int, byte[]);
}
@@ -15351,6 +15363,19 @@
ctor public UnsupportedSchemeException(java.lang.String);
}
+ public abstract class VolumeProvider {
+ ctor public VolumeProvider(int, int);
+ method public final int getMaxVolume();
+ method public final int getVolumeControl();
+ method public final void notifyVolumeChanged();
+ method public void onAdjustVolumeBy(int);
+ method public abstract int onGetCurrentVolume();
+ method public void onSetVolumeTo(int);
+ field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+ field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+ field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+ }
+
}
package android.media.audiofx {
@@ -15717,6 +15742,7 @@
method public android.media.session.PlaybackState getPlaybackState();
method public int getRatingType();
method public android.media.session.MediaController.TransportControls getTransportControls();
+ method public android.media.session.MediaController.VolumeInfo getVolumeInfo();
method public void removeCallback(android.media.session.MediaController.Callback);
method public void sendControlCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
}
@@ -15740,6 +15766,14 @@
method public void stop();
}
+ public static final class MediaController.VolumeInfo {
+ method public int getAudioStream();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getVolumeControl();
+ method public int getVolumeType();
+ }
+
public final class MediaSession {
method public void addCallback(android.media.session.MediaSession.Callback);
method public void addCallback(android.media.session.MediaSession.Callback, android.os.Handler);
@@ -15757,9 +15791,11 @@
method public void setMetadata(android.media.MediaMetadata);
method public void setPlaybackState(android.media.session.PlaybackState);
method public void setPlaybackToLocal(int);
- method public void setPlaybackToRemote(android.media.session.RemoteVolumeProvider);
+ method public void setPlaybackToRemote(android.media.VolumeProvider);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
+ field public static final int VOLUME_TYPE_LOCAL = 1; // 0x1
+ field public static final int VOLUME_TYPE_REMOTE = 2; // 0x2
}
public static abstract class MediaSession.Callback {
@@ -15830,19 +15866,6 @@
field public static final int STATE_STOPPED = 1; // 0x1
}
- public abstract class RemoteVolumeProvider {
- ctor public RemoteVolumeProvider(int, int);
- method public final int getMaxVolume();
- method public final int getVolumeControl();
- method public final void notifyVolumeChanged();
- method public void onAdjustVolumeBy(int);
- method public abstract int onGetCurrentVolume();
- method public void onSetVolumeTo(int);
- field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
- field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
- field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
- }
-
}
package android.media.tv {
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 6296dd1..6b2a0e2 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -52,13 +52,13 @@
);
}
-static SkBitmap::Config flinger2skia(PixelFormat f)
+static SkColorType flinger2skia(PixelFormat f)
{
switch (f) {
case PIXEL_FORMAT_RGB_565:
- return SkBitmap::kRGB_565_Config;
+ return kRGB_565_SkColorType;
default:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
}
}
@@ -174,9 +174,10 @@
if (base) {
if (png) {
+ const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
+ kPremul_SkAlphaType);
SkBitmap b;
- b.setConfig(flinger2skia(f), w, h, s*bytesPerPixel(f));
- b.setPixels((void*)base);
+ b.installPixels(info, const_cast<void*>(base), s*bytesPerPixel(f));
SkDynamicMemoryWStream stream;
SkImageEncoder::EncodeStream(&stream, b,
SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index b78b9c9..c583998 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -188,6 +188,9 @@
endPerformanceSnapshot();
}
if (mPerfMetrics != null) {
+ if (results == null) {
+ results = new Bundle();
+ }
results.putAll(mPerfMetrics);
}
if (mUiAutomation != null) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3dfa78b..e24dc84 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -55,6 +55,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
/**
@@ -6821,72 +6822,12 @@
if (other == null) {
return false;
}
- if (mAction != other.mAction) {
- if (mAction != null) {
- if (!mAction.equals(other.mAction)) {
- return false;
- }
- } else {
- if (!other.mAction.equals(mAction)) {
- return false;
- }
- }
- }
- if (mData != other.mData) {
- if (mData != null) {
- if (!mData.equals(other.mData)) {
- return false;
- }
- } else {
- if (!other.mData.equals(mData)) {
- return false;
- }
- }
- }
- if (mType != other.mType) {
- if (mType != null) {
- if (!mType.equals(other.mType)) {
- return false;
- }
- } else {
- if (!other.mType.equals(mType)) {
- return false;
- }
- }
- }
- if (mPackage != other.mPackage) {
- if (mPackage != null) {
- if (!mPackage.equals(other.mPackage)) {
- return false;
- }
- } else {
- if (!other.mPackage.equals(mPackage)) {
- return false;
- }
- }
- }
- if (mComponent != other.mComponent) {
- if (mComponent != null) {
- if (!mComponent.equals(other.mComponent)) {
- return false;
- }
- } else {
- if (!other.mComponent.equals(mComponent)) {
- return false;
- }
- }
- }
- if (mCategories != other.mCategories) {
- if (mCategories != null) {
- if (!mCategories.equals(other.mCategories)) {
- return false;
- }
- } else {
- if (!other.mCategories.equals(mCategories)) {
- return false;
- }
- }
- }
+ if (!Objects.equals(this.mAction, other.mAction)) return false;
+ if (!Objects.equals(this.mData, other.mData)) return false;
+ if (!Objects.equals(this.mType, other.mType)) return false;
+ if (!Objects.equals(this.mPackage, other.mPackage)) return false;
+ if (!Objects.equals(this.mComponent, other.mComponent)) return false;
+ if (!Objects.equals(this.mCategories, other.mCategories)) return false;
return true;
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 44fc3b6..cc8503b 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -167,7 +167,7 @@
private boolean mOneShot;
private boolean mWithBuffer;
private boolean mFaceDetectionRunning = false;
- private Object mAutoFocusCallbackLock = new Object();
+ private final Object mAutoFocusCallbackLock = new Object();
private static final int NO_ERROR = 0;
private static final int EACCESS = -13;
@@ -202,14 +202,14 @@
/**
* A constant meaning the normal camera connect/open will be used.
- * @hide
*/
- public static final int CAMERA_HAL_API_VERSION_NORMAL_OPEN = -2;
+ private static final int CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2;
/**
* Used to indicate HAL version un-specified.
*/
private static final int CAMERA_HAL_API_VERSION_UNSPECIFIED = -1;
+
/**
* Hardware face detection. It does not use much CPU.
*/
@@ -376,18 +376,25 @@
*
* @param cameraId The hardware camera to access, between 0 and
* {@link #getNumberOfCameras()}-1.
- * @param halVersion The HAL API version this camera device to be opened as. When
- * it is {@value #CAMERA_HAL_API_VERSION_NORMAL_OPEN}, the methods will be equivalent
- * to {@link #open}, but more detailed error information will be returned to managed code.
+ * @param halVersion The HAL API version this camera device to be opened as.
* @return a new Camera object, connected, locked and ready for use.
+ *
+ * @throws IllegalArgumentException if the {@code halVersion} is invalid
+ *
* @throws RuntimeException if opening the camera fails (for example, if the
* camera is in use by another process or device policy manager has disabled
* the camera).
+ *
* @see android.app.admin.DevicePolicyManager#getCameraDisabled(android.content.ComponentName)
+ * @see #CAMERA_HAL_API_VERSION_1_0
*
* @hide
*/
public static Camera openLegacy(int cameraId, int halVersion) {
+ if (halVersion < CAMERA_HAL_API_VERSION_1_0) {
+ throw new IllegalArgumentException("Invalid HAL version " + halVersion);
+ }
+
return new Camera(cameraId, halVersion);
}
@@ -399,7 +406,7 @@
* @param halVersion The HAL API version this camera device to be opened as.
*/
private Camera(int cameraId, int halVersion) {
- int err = cameraInit(cameraId, halVersion);
+ int err = cameraInitVersion(cameraId, halVersion);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
@@ -428,13 +435,7 @@
}
}
- private int cameraInit(int cameraId, int halVersion) {
- // This function should be only called by Camera(int cameraId, int halVersion).
- if (halVersion < CAMERA_HAL_API_VERSION_1_0 &&
- halVersion != CAMERA_HAL_API_VERSION_NORMAL_OPEN) {
- throw new IllegalArgumentException("Invalid HAL version " + halVersion);
- }
-
+ private int cameraInitVersion(int cameraId, int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
@@ -457,8 +458,31 @@
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
}
+ private int cameraInitNormal(int cameraId) {
+ return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
+ }
+
+ /**
+ * Connect to the camera service using #connectLegacy
+ *
+ * <p>
+ * This acts the same as normal except that it will return
+ * the detailed error code if open fails instead of
+ * converting everything into {@code NO_INIT}.</p>
+ *
+ * <p>Intended to use by the camera2 shim only, do <i>not</i> use this for other code.</p>
+ *
+ * @return a detailed errno error code, or {@code NO_ERROR} on success
+ *
+ * @hide
+ */
+ public int cameraInitUnspecified(int cameraId) {
+ return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_UNSPECIFIED);
+ }
+
+ /** used by Camera#open, Camera#open(int) */
Camera(int cameraId) {
- int err = cameraInit(cameraId);
+ int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
@@ -472,32 +496,6 @@
}
}
- /**
- * @hide
- */
- public int cameraInit(int cameraId) {
- mShutterCallback = null;
- mRawImageCallback = null;
- mJpegCallback = null;
- mPreviewCallback = null;
- mPostviewCallback = null;
- mUsingPreviewAllocation = false;
- mZoomListener = null;
-
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else {
- mEventHandler = null;
- }
-
- String packageName = ActivityThread.currentPackageName();
-
- return native_setup(new WeakReference<Camera>(this), cameraId,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, packageName);
- }
/**
* @hide
@@ -519,6 +517,7 @@
Camera() {
}
+ @Override
protected void finalize() {
release();
}
@@ -1056,7 +1055,7 @@
private class EventHandler extends Handler
{
- private Camera mCamera;
+ private final Camera mCamera;
public EventHandler(Camera c, Looper looper) {
super(looper);
@@ -2337,6 +2336,7 @@
* @hide
* @deprecated
*/
+ @Deprecated
public void dump() {
Log.e(TAG, "dump: size=" + mMap.size());
for (String k : mMap.keySet()) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4a87680..e2f88eb 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -579,6 +579,7 @@
* of the lens that can be focused correctly.</p>
* <p>If the lens is fixed-focus, this should be
* 0.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*/
public static final Key<Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE =
new Key<Float>("android.lens.info.minimumFocusDistance", float.class);
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 73188ff..9a3d806 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -278,14 +278,19 @@
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
int id = Integer.parseInt(cameraId);
try {
- mCameraService.connectDevice(callbacks, id, mContext.getPackageName(),
- USE_CALLING_UID, holder);
- cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
- } catch (CameraRuntimeException e) {
- if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
+ if (supportsCamera2Api(cameraId)) {
+ // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
+ mCameraService.connectDevice(callbacks, id, mContext.getPackageName(),
+ USE_CALLING_UID, holder);
+ cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+ } else {
// Use legacy camera implementation for HAL1 devices
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
+ }
+ } catch (CameraRuntimeException e) {
+ if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
+ throw new AssertionError("Should've gone down the shim path");
} else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
e.getReason() == CameraAccessException.CAMERA_DISABLED ||
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index de1d9a3..2e59eee 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -460,7 +460,7 @@
* starting and stopping repeating request and flushing.
*
* <p>If lastFrameNumber is NO_FRAMES_CAPTURED, it means that the request was never
- * sent to HAL. Then onCaptureSequenceCompleted is immediately triggered.
+ * sent to HAL. Then onCaptureSequenceAborted is immediately triggered.
* If lastFrameNumber is non-negative, then the requestId and lastFrameNumber pair
* is added to the list mFrameNumberRequestPairs.</p>
*
@@ -471,7 +471,7 @@
private void checkEarlyTriggerSequenceComplete(
final int requestId, final long lastFrameNumber) {
// lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
- // was never sent to HAL. Should trigger onCaptureSequenceCompleted immediately.
+ // was never sent to HAL. Should trigger onCaptureSequenceAborted immediately.
if (lastFrameNumber == CaptureListener.NO_FRAMES_CAPTURED) {
final CaptureListenerHolder holder;
int index = mCaptureListenerMap.indexOfKey(requestId);
@@ -488,7 +488,7 @@
if (holder != null) {
if (DEBUG) {
- Log.v(TAG, "immediately trigger onCaptureSequenceCompleted because"
+ Log.v(TAG, "immediately trigger onCaptureSequenceAborted because"
+ " request did not reach HAL");
}
@@ -505,10 +505,9 @@
|| lastFrameNumber > Integer.MAX_VALUE) {
throw new AssertionError(lastFrameNumber + " cannot be cast to int");
}
- holder.getListener().onCaptureSequenceCompleted(
+ holder.getListener().onCaptureSequenceAborted(
CameraDeviceImpl.this,
- requestId,
- lastFrameNumber);
+ requestId);
}
}
};
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index e4412ce..abd69c1 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -76,13 +76,11 @@
}
// TODO: Move open/init into LegacyCameraDevice thread when API is switched to async.
Camera legacyCamera = Camera.openUninitialized();
- int initErrors = legacyCamera.cameraInit(cameraId);
+ int initErrors = legacyCamera.cameraInitUnspecified(cameraId);
+
// Check errors old HAL initialization
- if (Camera.checkInitErrors(initErrors)) {
- // TODO: Map over old camera error codes. This likely involves improving the error
- // reporting in the HAL1 connect path.
- throw new CameraRuntimeException(CameraAccessException.CAMERA_DISCONNECTED);
- }
+ CameraBinderDecorator.throwOnError(initErrors);
+
LegacyCameraDevice device = new LegacyCameraDevice(cameraId, legacyCamera, callbacks);
return new CameraDeviceUserShim(cameraId, device);
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 6fa2134..048878c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -48,6 +48,9 @@
private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
+ // for metadata
+ private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f;
+
private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // ms
private static final long APPROXIMATE_SENSOR_AREA = (1 << 20); // 8mp
private static final long APPROXIMATE_JPEG_ENCODE_TIME = 600; // ms
@@ -94,10 +97,12 @@
}
private static void mapCameraParameters(CameraMetadataNative m, Camera.Parameters p) {
+ m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
mapStreamConfigs(m, p);
mapAeConfig(m, p);
mapCapabilities(m, p);
-
+ mapLens(m, p);
+ mapFlash(m, p);
// TODO: map other fields
}
@@ -200,6 +205,30 @@
m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
}
+ private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
+ /*
+ * We can tell if the lens is fixed focus;
+ * but if it's not, we can't tell the minimum focus distance, so leave it null then.
+ */
+ if (p.getFocusMode() == Camera.Parameters.FOCUS_MODE_FIXED) {
+ m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
+ }
+ }
+
+ private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) {
+ boolean flashAvailable = false;
+ List<String> supportedFlashModes = p.getSupportedFlashModes();
+ if (supportedFlashModes != null) {
+ // If only 'OFF' is available, we don't really have flash support
+ if (!(supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_OFF) &&
+ supportedFlashModes.size() == 1)) {
+ flashAvailable = true;
+ }
+ }
+
+ m.set(FLASH_INFO_AVAILABLE, flashAvailable);
+ }
+
private static void appendStreamConfig(
ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) {
for (Camera.Size size : sizes) {
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index af1de78..fa14bfd 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -253,10 +253,9 @@
ViewPropertyAnimator(View view) {
mView = view;
view.ensureTransformationInfo();
- // TODO: Disabled because of b/15287046
- //if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
- // mRTBackend = new ViewPropertyAnimatorRT(view);
- //}
+ if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
+ mRTBackend = new ViewPropertyAnimatorRT(view);
+ }
}
/**
@@ -434,6 +433,9 @@
}
mPendingAnimations.clear();
mView.removeCallbacks(mAnimationStarter);
+ if (mRTBackend != null) {
+ mRTBackend.cancelAll();
+ }
}
/**
diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java
index 709efdb..254f254 100644
--- a/core/java/android/view/ViewPropertyAnimatorRT.java
+++ b/core/java/android/view/ViewPropertyAnimatorRT.java
@@ -50,6 +50,15 @@
return true;
}
+ public void cancelAll() {
+ for (int i = 0; i < mAnimators.length; i++) {
+ if (mAnimators[i] != null) {
+ mAnimators[i].cancel();
+ mAnimators[i] = null;
+ }
+ }
+ }
+
private void doStartAnimation(ViewPropertyAnimator parent) {
int size = parent.mPendingAnimations.size();
@@ -99,10 +108,27 @@
if (parent.hasActions()) {
return false;
}
+ if (hasAlphaAnimation(parent)) {
+ // TODO: Alpha does too much weird stuff currently to safely RT-accelerate
+ // see View:getFinalAlpha() and friends, which need to be fixed to
+ // work with RT animators
+ return false;
+ }
// Here goes nothing...
return true;
}
+ private boolean hasAlphaAnimation(ViewPropertyAnimator parent) {
+ int size = parent.mPendingAnimations.size();
+ for (int i = 0; i < size; i++) {
+ NameValuesHolder holder = parent.mPendingAnimations.get(i);
+ if (holder.mNameConstant == ViewPropertyAnimator.ALPHA) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) {
int size = mPendingAnimations.size();
for (int i = 0; i < size; i++) {
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 9998995..c139c9d 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -258,16 +258,16 @@
// can return NULL
static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
- switch (src.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (src.colorType()) {
+ case kN32_SkColorType:
if (src.isOpaque()) return ToColor_S32_Opaque;
return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
if (src.isOpaque()) return ToColor_S4444_Opaque;
return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return ToColor_S565;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
if (src.getColorTable() == NULL) {
return NULL;
}
@@ -291,7 +291,7 @@
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
jint offset, jint stride, jint width, jint height,
jint configHandle, jboolean isMutable) {
- SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+ SkColorType colorType = SkBitmapConfigToColorType(static_cast<SkBitmap::Config>(configHandle));
if (NULL != jColors) {
size_t n = env->GetArrayLength(jColors);
if (n < SkAbs32(stride) * (size_t)height) {
@@ -301,12 +301,12 @@
}
// ARGB_4444 is a deprecated format, convert automatically to 8888
- if (config == SkBitmap::kARGB_4444_Config) {
- config = SkBitmap::kARGB_8888_Config;
+ if (colorType == kARGB_4444_SkColorType) {
+ colorType = kN32_SkColorType;
}
SkBitmap bitmap;
- bitmap.setConfig(config, width, height);
+ bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
if (NULL == buff) {
@@ -515,28 +515,29 @@
android::Parcel* p = android::parcelForJavaObject(env, parcel);
- const bool isMutable = p->readInt32() != 0;
- const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
- const int width = p->readInt32();
- const int height = p->readInt32();
- const int rowBytes = p->readInt32();
- const int density = p->readInt32();
+ const bool isMutable = p->readInt32() != 0;
+ const SkColorType colorType = (SkColorType)p->readInt32();
+ const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
+ const int width = p->readInt32();
+ const int height = p->readInt32();
+ const int rowBytes = p->readInt32();
+ const int density = p->readInt32();
- if (SkBitmap::kARGB_8888_Config != config &&
- SkBitmap::kRGB_565_Config != config &&
- SkBitmap::kARGB_4444_Config != config &&
- SkBitmap::kIndex8_Config != config &&
- SkBitmap::kA8_Config != config) {
- SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
+ if (kN32_SkColorType != colorType &&
+ kRGB_565_SkColorType != colorType &&
+ kARGB_4444_SkColorType != colorType &&
+ kIndex_8_SkColorType != colorType &&
+ kAlpha_8_SkColorType != colorType) {
+ SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
return NULL;
}
SkBitmap* bitmap = new SkBitmap;
- bitmap->setConfig(config, width, height, rowBytes);
+ bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes);
SkColorTable* ctable = NULL;
- if (config == SkBitmap::kIndex8_Config) {
+ if (colorType == kIndex_8_SkColorType) {
int count = p->readInt32();
if (count > 0) {
size_t size = count * sizeof(SkPMColor);
@@ -587,13 +588,14 @@
android::Parcel* p = android::parcelForJavaObject(env, parcel);
p->writeInt32(isMutable);
- p->writeInt32(bitmap->config());
+ p->writeInt32(bitmap->colorType());
+ p->writeInt32(bitmap->alphaType());
p->writeInt32(bitmap->width());
p->writeInt32(bitmap->height());
p->writeInt32(bitmap->rowBytes());
p->writeInt32(density);
- if (bitmap->config() == SkBitmap::kIndex8_Config) {
+ if (bitmap->colorType() == kIndex_8_SkColorType) {
SkColorTable* ctable = bitmap->getColorTable();
if (ctable != NULL) {
int count = ctable->count();
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 5106f0d..86ed677 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -386,7 +386,7 @@
// FIXME: If the alphaType is kUnpremul and the image has alpha, the
// colors may not be correct, since Skia does not yet support drawing
// to/from unpremultiplied bitmaps.
- outputBitmap->setConfig(SkImageInfo::Make(scaledWidth, scaledHeight,
+ outputBitmap->setInfo(SkImageInfo::Make(scaledWidth, scaledHeight,
colorType, decodingBitmap.alphaType()));
if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 935e3a0..9e09280 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -703,10 +703,11 @@
jboolean hasAlpha, jlong paintHandle) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
SkBitmap bitmap;
- bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
- SkBitmap::kRGB_565_Config, width, height);
- if (!bitmap.allocPixels()) {
+ if (!bitmap.allocPixels(info)) {
return;
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4c9feca..f8bab24 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -36,6 +36,11 @@
using namespace android;
+enum {
+ // Keep up to date with Camera.java
+ CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2,
+};
+
struct fields_t {
jfieldID context;
jfieldID facing;
@@ -475,8 +480,8 @@
env->ReleaseStringChars(clientPackageName, rawClientName);
sp<Camera> camera;
- if (halVersion == ICameraService::CAMERA_HAL_API_VERSION_UNSPECIFIED) {
- // Default path: hal version is unspecified, do normal camera open.
+ if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
+ // Default path: hal version is don't care, do normal camera connect.
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
} else {
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index ee4c619..849531c 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -287,6 +287,8 @@
env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
"errorCallbackFromNative","(I)V"),
check_AudioSystem_Command(err));
+
+ env->DeleteLocalRef(clazz);
}
static jint
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index dc1ea06..4362018 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -388,11 +388,11 @@
static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
jlong rendererPtr, jintArray colors, jint offset, jint stride,
jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
+ const SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
SkBitmap* bitmap = new SkBitmap;
- bitmap->setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config,
- width, height);
-
- if (!bitmap->allocPixels()) {
+ if (!bitmap->allocPixels(info)) {
delete bitmap;
return;
}
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 0210bd9..5ebed9c 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -142,16 +142,16 @@
// Canvas management
// ----------------------------------------------------------------------------
-static inline SkBitmap::Config convertPixelFormat(int32_t format) {
+static inline SkColorType convertPixelFormat(int32_t format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
case PIXEL_FORMAT_RGBX_8888:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
case PIXEL_FORMAT_RGB_565:
- return SkBitmap::kRGB_565_Config;
+ return kRGB_565_SkColorType;
default:
- return SkBitmap::kNo_Config;
+ return kUnknown_SkColorType;
}
}
@@ -188,8 +188,10 @@
ssize_t bytesCount = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat());
SkBitmap bitmap;
- bitmap.setConfig(convertPixelFormat(buffer->getPixelFormat()),
- buffer->getWidth(), buffer->getHeight(), bytesCount);
+ bitmap.setInfo(SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
+ convertPixelFormat(buffer->getPixelFormat()),
+ kPremul_SkAlphaType),
+ bytesCount);
if (buffer->getWidth() > 0 && buffer->getHeight() > 0) {
bitmap.setPixels(bits);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3d14aaf..7018751 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -173,17 +173,17 @@
return value;
}
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+static inline SkColorType convertPixelFormat(PixelFormat format) {
/* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
- we can map to SkBitmap::kARGB_8888_Config, and optionally call
+ we can map to kN32_SkColorType, and optionally call
bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
(as an accelerator)
*/
switch (format) {
- case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
- default: return SkBitmap::kNo_Config;
+ case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
+ case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
+ case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
+ default: return kUnknown_SkColorType;
}
}
@@ -220,12 +220,16 @@
// Associate a SkCanvas object to this surface
env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
+ SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
+ convertPixelFormat(outBuffer.format),
+ kPremul_SkAlphaType);
+ if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
+ info.fAlphaType = kOpaque_SkAlphaType;
+ }
+
SkBitmap bitmap;
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
- bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
- if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
- bitmap.setAlphaType(kOpaque_SkAlphaType);
- }
+ bitmap.setInfo(info, bpr);
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);
} else {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index cfc8eb8..9783e91 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -175,7 +175,7 @@
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
SkBitmap* bitmap = new SkBitmap();
- bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
+ bitmap->setInfo(screenshotInfo, (size_t)rowBytes);
if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
// takes ownership of ScreenshotClient
SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index c1ab515..5c04a78 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -73,17 +73,28 @@
// Native layer
// ----------------------------------------------------------------------------
-static inline SkBitmap::Config convertPixelFormat(int32_t format) {
- switch (format) {
+// FIXME: consider exporting this to share (e.g. android_view_Surface.cpp)
+static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer) {
+ SkImageInfo info;
+ info.fWidth = buffer.width;
+ info.fHeight = buffer.height;
+ switch (buffer.format) {
case WINDOW_FORMAT_RGBA_8888:
- return SkBitmap::kARGB_8888_Config;
+ info.fColorType = kN32_SkColorType;
+ info.fAlphaType = kPremul_SkAlphaType;
+ break;
case WINDOW_FORMAT_RGBX_8888:
- return SkBitmap::kARGB_8888_Config;
+ info.fColorType = kN32_SkColorType;
+ info.fAlphaType = kOpaque_SkAlphaType;
case WINDOW_FORMAT_RGB_565:
- return SkBitmap::kRGB_565_Config;
+ info.fColorType = kRGB_565_SkColorType;
+ info.fAlphaType = kOpaque_SkAlphaType;
default:
- return SkBitmap::kNo_Config;
+ info.fColorType = kUnknown_SkColorType;
+ info.fAlphaType = kIgnore_SkAlphaType;
+ break;
}
+ return info;
}
/**
@@ -148,11 +159,7 @@
ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format);
SkBitmap bitmap;
- bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount);
-
- if (buffer.format == WINDOW_FORMAT_RGBX_8888) {
- bitmap.setAlphaType(kOpaque_SkAlphaType);
- }
+ bitmap.setInfo(convertPixelFormat(buffer), bytesCount);
if (buffer.width > 0 && buffer.height > 0) {
bitmap.setPixels(buffer.bits);
diff --git a/core/res/res/transition/explode.xml b/core/res/res/transition/explode.xml
new file mode 100644
index 0000000..fe22284
--- /dev/null
+++ b/core/res/res/transition/explode.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<explode xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/core/res/res/transition/slide_bottom.xml b/core/res/res/transition/slide_bottom.xml
new file mode 100644
index 0000000..46dc0d6
--- /dev/null
+++ b/core/res/res/transition/slide_bottom.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="bottom"/>
diff --git a/core/res/res/transition/slide_left.xml b/core/res/res/transition/slide_left.xml
new file mode 100644
index 0000000..997bd97
--- /dev/null
+++ b/core/res/res/transition/slide_left.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="left"/>
diff --git a/core/res/res/transition/slide_right.xml b/core/res/res/transition/slide_right.xml
new file mode 100644
index 0000000..98f8f6a
--- /dev/null
+++ b/core/res/res/transition/slide_right.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="right"/>
diff --git a/core/res/res/transition/slide_top.xml b/core/res/res/transition/slide_top.xml
new file mode 100644
index 0000000..07ab945
--- /dev/null
+++ b/core/res/res/transition/slide_top.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="top"/>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 07a1e51..c3e4d94 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2461,5 +2461,26 @@
<!-- An interpolator which accelerates fast and keeps accelerating until the end. -->
<public type="interpolator" name="fast_out_linear_in" />
+ <!-- Used for Activity Transitions, this transition indicates that no Transition
+ should be used. -->
<public type="transition" name="no_transition" id="0x010f0000"/>
+ <!-- A transition that moves and resizes a view -->
+ <public type="transition" name="move"/>
+ <!-- A transition that fades views in and out. -->
+ <public type="transition" name="fade"/>
+ <!-- A transition that moves views in or out of the scene to or from the edges when
+ a view visibility changes. -->
+ <public type="transition" name="explode"/>
+ <!-- A transition that moves views in or out of the scene to or from the bottom edge when
+ a view visibility changes. -->
+ <public type="transition" name="slide_bottom"/>
+ <!-- A transition that moves views in or out of the scene to or from the top edge when
+ a view visibility changes. -->
+ <public type="transition" name="slide_top"/>
+ <!-- A transition that moves views in or out of the scene to or from the right edge when
+ a view visibility changes. -->
+ <public type="transition" name="slide_right"/>
+ <!-- A transition that moves views in or out of the scene to or from the left edge when
+ a view visibility changes. -->
+ <public type="transition" name="slide_left"/>
</resources>
diff --git a/docs/html/preview/images/l-dev-prev.png b/docs/html/preview/images/l-dev-prev.png
index 95bad8c..eae6ede 100644
--- a/docs/html/preview/images/l-dev-prev.png
+++ b/docs/html/preview/images/l-dev-prev.png
Binary files differ
diff --git a/docs/html/preview/index.html b/docs/html/preview/index.html
index 368db84..d4610b5 100644
--- a/docs/html/preview/index.html
+++ b/docs/html/preview/index.html
@@ -163,8 +163,8 @@
platform officially launches.
</div>
- <img src="/preview/images/l-dev-prev.png" style=" margin:10px 0 0 100px" width="700px"/>
- <div class="col-6" style="margin-left:630px; margin-top:-40px">
+ <img src="/preview/images/l-dev-prev.png" style=" margin:0px 0 0 40px" width="860px"/>
+ <div class="col-6" style="margin-left:660px; margin-top:-105px">
<a href="/preview/setup-sdk.html" class="landing-button landing-secondary" style="position:absolute;z-index:100;float:right;margin-top: 0px; background-color:#09c">Get Started</a><!--
<p>Set up your environment and check out all the docs to get up and running.</p>-->
@@ -176,7 +176,7 @@
-<div class="landing-section landing-gray-background" style="margin-top:-80px; padding-bottom:20px">
+<div class="landing-section landing-gray-background" style="margin-top:-135px; padding-bottom:20px">
<div class="wrap">
<div class="cols">
<div class="landing-body" style="margin-top:-80px" >
@@ -186,14 +186,14 @@
<p>A New UI Design</p>
<p class="landing-small">
Create a consistent experience across mobile and the web with
- material design, the new Google-wide standard.
+ <b>material design</b>, the new Google-wide standard.
</p>
<p class="landing-small">
<a href="/preview/material/index.html">Learn about material</a>
</p>
</div>
<div class="col-4">
- <p>A Rehauled Runtime</p>
+ <p>A New Runtime</p>
<p class="landing-small">
Test your apps and get them ready for <b>ART</b> (<b>A</b>ndroid <b>R</b>un<b>t</b>ime),
the default runtime in the next release.
@@ -205,21 +205,21 @@
<div class="col-4">
<p style="width:230px">Enhanced Notifications</p>
<p class="landing-small">
- Get more control over where notifications appear,
- how they look, and automatic syncing to non-handheld devices.
+ Get control over where notifications appear,
+ how they look, and how they sync to non-handheld devices.
</p>
<p class="landing-small">
- <a href="/preview/api-overview.html#UI">Learn more</a>
+ <a href="/preview/api-overview.html#UI">Learn about notifications</a>
</p>
</div>
<div class="col-4">
- <p>Project Volta</p>
+ <p>Increased Efficiency</p>
<p class="landing-small">
- We've tuned the platform to be more energy efficient and
+ <b>Project Volta</b> is our effort to make the platform energy efficient and
to give you more control over resource usage.
</p>
<p class="landing-small">
- <a href="/preview/api-overview.html#Power">Learn more</a>
+ <a href="/preview/api-overview.html#Power">Learn about Project Volta</a>
</p>
</div>
</div>
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index eff3011..dc6d852 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -160,6 +160,10 @@
(target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
}
+uint32_t RenderPropertyAnimator::dirtyMask() {
+ return mPropertyAccess->dirtyMask;
+}
+
float RenderPropertyAnimator::getValue(RenderNode* target) const {
return (target->properties().*mPropertyAccess->getter)();
}
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 203cdff..6cb72c4c 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -61,6 +61,8 @@
bool isFinished() { return mPlayState == FINISHED; }
float finalValue() { return mFinalValue; }
+ ANDROID_API virtual uint32_t dirtyMask() { return 0; }
+
protected:
BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
@@ -112,6 +114,8 @@
ANDROID_API virtual void onAttached(RenderNode* target);
+ ANDROID_API virtual uint32_t dirtyMask();
+
protected:
virtual float getValue(RenderNode* target) const;
virtual void setValue(RenderNode* target, float value);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 9dd5aa5..97eb583 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -104,8 +104,7 @@
}
static void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
- bitmap.setConfig(SkBitmap::kA8_Config, width, height);
- bitmap.allocPixels();
+ bitmap.allocPixels(SkImageInfo::MakeA8(width, height));
bitmap.eraseColor(0);
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index b2fe849..2d6d409 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -189,6 +189,8 @@
// UI thread only!
ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mStagingAnimators.erase(animator);
+ // Force a sync of the staging property value
+ mDirtyPropertyFields |= animator->dirtyMask();
mNeedsAnimatorsSync = true;
}
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 1001cae0..9212d0a 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -333,8 +333,7 @@
void TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap,
uint32_t width, uint32_t height) {
SkBitmap rgbaBitmap;
- rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0, bitmap->alphaType());
- rgbaBitmap.allocPixels();
+ rgbaBitmap.allocPixels(SkImageInfo::MakeN32(width, height, bitmap->alphaType()));
rgbaBitmap.eraseColor(0);
SkCanvas canvas(rgbaBitmap);
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 3f6ccc9..063383b 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -206,9 +206,8 @@
} else {
SkBitmap surfaceBitmap;
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
- surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
- outBuffer.width, outBuffer.height, bpr);
- surfaceBitmap.setPixels(outBuffer.bits);
+ surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
+ outBuffer.bits, bpr);
SkCanvas surfaceCanvas(surfaceBitmap);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 47b6024..fb19242 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2194,48 +2194,8 @@
Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
return;
}
- IAudioService service = getService();
- try {
- // pi != null, this is currently still needed to support across
- // reboot launching of the last app.
- service.registerMediaButtonIntent(pi, eventReceiver,
- eventReceiver == null ? mToken : null);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
- }
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
- helper.addMediaButtonListener(pi, mContext);
- }
-
- /**
- * @hide
- * Used internally by telephony package to register an intent receiver for ACTION_MEDIA_BUTTON.
- * @param eventReceiver the component that will receive the media button key events,
- * no-op if eventReceiver is null
- */
- public void registerMediaButtonEventReceiverForCalls(ComponentName eventReceiver) {
- if (eventReceiver == null) {
- return;
- }
- IAudioService service = getService();
- try {
- // eventReceiver != null
- service.registerMediaButtonEventReceiverForCalls(eventReceiver);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerMediaButtonEventReceiverForCalls", e);
- }
- }
-
- /**
- * @hide
- */
- public void unregisterMediaButtonEventReceiverForCalls() {
- IAudioService service = getService();
- try {
- service.unregisterMediaButtonEventReceiverForCalls();
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiverForCalls", e);
- }
+ helper.addMediaButtonListener(pi, eventReceiver, mContext);
}
/**
@@ -2272,12 +2232,6 @@
* @hide
*/
public void unregisterMediaButtonIntent(PendingIntent pi) {
- IAudioService service = getService();
- try {
- service.unregisterMediaButtonIntent(pi);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e);
- }
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
helper.removeMediaButtonListener(pi);
}
@@ -2443,46 +2397,6 @@
}
/**
- * @hide
- * Request the user of a RemoteControlClient to seek to the given playback position.
- * @param generationId the RemoteControlClient generation counter for which this request is
- * issued. Requests for an older generation than current one will be ignored.
- * @param timeMs the time in ms to seek to, must be positive.
- */
- public void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
- if (timeMs < 0) {
- return;
- }
- IAudioService service = getService();
- try {
- service.setRemoteControlClientPlaybackPosition(generationId, timeMs);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in setRccPlaybackPosition("+ generationId + ", "
- + timeMs + ")", e);
- }
- }
-
- /**
- * @hide
- * Notify the user of a RemoteControlClient that it should update its metadata with the
- * new value for the given key.
- * @param generationId the RemoteControlClient generation counter for which this request is
- * issued. Requests for an older generation than current one will be ignored.
- * @param key the metadata key for which a new value exists
- * @param value the new metadata value
- */
- public void updateRemoteControlClientMetadata(int generationId, int key,
- Rating value) {
- IAudioService service = getService();
- try {
- service.updateRemoteControlClientMetadata(generationId, key, value);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in updateRemoteControlClientMetadata("+ generationId + ", "
- + key +", " + value + ")", e);
- }
- }
-
- /**
* @hide
* Reload audio settings. This method is called by Settings backup
* agent when audio settings are restored and causes the AudioService
@@ -2898,12 +2812,9 @@
* @hide
*/
public int getRemoteStreamVolume() {
- try {
- return getService().getRemoteStreamVolume();
- } catch (RemoteException e) {
- Log.w(TAG, "Error getting remote stream volume", e);
- return 0;
- }
+ // TODO STOPSHIP switch callers to use media sessions instead
+ Log.e(TAG, "Need to implement new Remote Volume!");
+ return 0;
}
/**
@@ -2911,12 +2822,9 @@
* @hide
*/
public int getRemoteStreamMaxVolume() {
- try {
- return getService().getRemoteStreamMaxVolume();
- } catch (RemoteException e) {
- Log.w(TAG, "Error getting remote stream max volume", e);
- return 0;
- }
+ // TODO STOPSHIP switch callers to use media sessions instead
+ Log.e(TAG, "Need to implement new Remote Volume!");
+ return 0;
}
/**
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 6b7d7a9..0c224a6 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -4412,68 +4412,12 @@
mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync);
}
- public void registerMediaButtonEventReceiverForCalls(ComponentName c) {
- mMediaFocusControl.registerMediaButtonEventReceiverForCalls(c);
- }
-
- public void unregisterMediaButtonEventReceiverForCalls() {
- mMediaFocusControl.unregisterMediaButtonEventReceiverForCalls();
- }
-
- public void registerMediaButtonIntent(PendingIntent pi, ComponentName c, IBinder token) {
- mMediaFocusControl.registerMediaButtonIntent(pi, c, token);
- }
-
- public void unregisterMediaButtonIntent(PendingIntent pi) {
- mMediaFocusControl.unregisterMediaButtonIntent(pi);
- }
-
- public int registerRemoteControlClient(PendingIntent mediaIntent,
- IRemoteControlClient rcClient, String callingPckg) {
- return mMediaFocusControl.registerRemoteControlClient(mediaIntent, rcClient, callingPckg);
- }
-
- public void unregisterRemoteControlClient(PendingIntent mediaIntent,
- IRemoteControlClient rcClient) {
- mMediaFocusControl.unregisterRemoteControlClient(mediaIntent, rcClient);
- }
-
- public void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
- mMediaFocusControl.setRemoteControlClientPlaybackPosition(generationId, timeMs);
- }
-
- public void updateRemoteControlClientMetadata(int generationId, int key, Rating value) {
- mMediaFocusControl.updateRemoteControlClientMetadata(generationId, key, value);
- }
-
- public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
- mMediaFocusControl.registerRemoteVolumeObserverForRcc(rccId, rvo);
- }
-
- @Override
- public int getRemoteStreamVolume() {
- return mMediaFocusControl.getRemoteStreamVolume();
- }
-
- @Override
- public int getRemoteStreamMaxVolume() {
- return mMediaFocusControl.getRemoteStreamMaxVolume();
- }
-
@Override
public void setRemoteStreamVolume(int index) {
enforceSelfOrSystemUI("set the remote stream volume");
mMediaFocusControl.setRemoteStreamVolume(index);
}
- public void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) {
- mMediaFocusControl.setPlaybackStateForRcc(rccId, state, timeMs, speed);
- }
-
- public void setPlaybackInfoForRcc(int rccId, int what, int value) {
- mMediaFocusControl.setPlaybackInfoForRcc(rccId, what, value);
- }
-
//==========================================================================================
// Audio Focus
//==========================================================================================
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 41e691d..4dcdd19 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -122,12 +122,6 @@
int getCurrentAudioFocus();
- void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c, IBinder token);
- oneway void unregisterMediaButtonIntent(in PendingIntent pi);
-
- oneway void registerMediaButtonEventReceiverForCalls(in ComponentName c);
- oneway void unregisterMediaButtonEventReceiverForCalls();
-
/**
* Register an IRemoteControlDisplay.
* Success of registration is subject to a check on
@@ -180,41 +174,6 @@
*/
oneway void remoteControlDisplayWantsPlaybackPositionSync(in IRemoteControlDisplay rcd,
boolean wantsSync);
- /**
- * Request the user of a RemoteControlClient to seek to the given playback position.
- * @param generationId the RemoteControlClient generation counter for which this request is
- * issued. Requests for an older generation than current one will be ignored.
- * @param timeMs the time in ms to seek to, must be positive.
- */
- void setRemoteControlClientPlaybackPosition(int generationId, long timeMs);
- /**
- * Notify the user of a RemoteControlClient that it should update its metadata with the
- * new value for the given key.
- * @param generationId the RemoteControlClient generation counter for which this request is
- * issued. Requests for an older generation than current one will be ignored.
- * @param key the metadata key for which a new value exists
- * @param value the new metadata value
- */
- void updateRemoteControlClientMetadata(int generationId, int key, in Rating value);
-
- /**
- * Do not use directly, use instead
- * {@link android.media.AudioManager#registerRemoteControlClient(RemoteControlClient)}
- */
- int registerRemoteControlClient(in PendingIntent mediaIntent,
- in IRemoteControlClient rcClient, in String callingPackageName);
- /**
- * Do not use directly, use instead
- * {@link android.media.AudioManager#unregisterRemoteControlClient(RemoteControlClient)}
- */
- oneway void unregisterRemoteControlClient(in PendingIntent mediaIntent,
- in IRemoteControlClient rcClient);
-
- oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
- void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed);
- int getRemoteStreamMaxVolume();
- int getRemoteStreamVolume();
- oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo);
void startBluetoothSco(IBinder cb, int targetSdkVersion);
void startBluetoothScoVirtualCall(IBinder cb);
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 440653a..6559bc5 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -181,6 +181,27 @@
}
/**
+ * Thrown when an unrecoverable failure occurs during a MediaDrm operation.
+ * Extends java.lang.IllegalStateException with the addition of an error
+ * code that may be useful in diagnosing the failure.
+ */
+ public static final class MediaDrmStateException extends java.lang.IllegalStateException {
+ private final int mErrorCode;
+
+ public MediaDrmStateException(int errorCode, String detailMessage) {
+ super(detailMessage);
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Retrieve the associated error code
+ */
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+ }
+
+ /**
* Register a callback to be invoked when an event occurs
*
* @param listener the callback that will be run
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 1c73c05..a4a7c4e 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -379,32 +379,11 @@
onReevaluateRemote();
break;
- case MSG_RCC_NEW_PLAYBACK_INFO:
- onNewPlaybackInfoForRcc(msg.arg1 /* rccId */, msg.arg2 /* key */,
- ((Integer)msg.obj).intValue() /* value */);
- break;
-
case MSG_RCC_NEW_VOLUME_OBS:
onRegisterVolumeObserverForRcc(msg.arg1 /* rccId */,
(IRemoteVolumeObserver)msg.obj /* rvo */);
break;
- case MSG_RCC_NEW_PLAYBACK_STATE:
- onNewPlaybackStateForRcc(msg.arg1 /* rccId */,
- msg.arg2 /* state */,
- (PlayerRecord.RccPlaybackState)msg.obj /* newState */);
- break;
-
- case MSG_RCC_SEEK_REQUEST:
- onSetRemoteControlClientPlaybackPosition(
- msg.arg1 /* generationId */, ((Long)msg.obj).longValue() /* timeMs */);
- break;
-
- case MSG_RCC_UPDATE_METADATA:
- onUpdateRemoteControlClientMetadata(msg.arg1 /*genId*/, msg.arg2 /*key*/,
- (Rating) msg.obj /* value */);
- break;
-
case MSG_RCDISPLAY_INIT_INFO:
// msg.obj is guaranteed to be non null
onRcDisplayInitInfo((IRemoteControlDisplay)msg.obj /*newRcd*/,
@@ -2003,217 +1982,6 @@
}
}
- protected void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
- // ignore position change requests if invalid generation ID
- synchronized(mPRStack) {
- synchronized(mCurrentRcLock) {
- if (mCurrentRcClientGen != generationId) {
- return;
- }
- }
- }
- // discard any unprocessed seek request in the message queue, and replace with latest
- sendMsg(mEventHandler, MSG_RCC_SEEK_REQUEST, SENDMSG_REPLACE, generationId /* arg1 */,
- 0 /* arg2 ignored*/, new Long(timeMs) /* obj */, 0 /* delay */);
- }
-
- private void onSetRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
- if(DEBUG_RC) Log.d(TAG, "onSetRemoteControlClientPlaybackPosition(genId=" + generationId +
- ", timeMs=" + timeMs + ")");
- synchronized(mPRStack) {
- synchronized(mCurrentRcLock) {
- if ((mCurrentRcClient != null) && (mCurrentRcClientGen == generationId)) {
- // tell the current client to seek to the requested location
- try {
- mCurrentRcClient.seekTo(generationId, timeMs);
- } catch (RemoteException e) {
- Log.e(TAG, "Current valid remote client is dead: "+e);
- mCurrentRcClient = null;
- }
- }
- }
- }
- }
-
- protected void updateRemoteControlClientMetadata(int genId, int key, Rating value) {
- sendMsg(mEventHandler, MSG_RCC_UPDATE_METADATA, SENDMSG_QUEUE,
- genId /* arg1 */, key /* arg2 */, value /* obj */, 0 /* delay */);
- }
-
- private void onUpdateRemoteControlClientMetadata(int genId, int key, Rating value) {
- if(DEBUG_RC) Log.d(TAG, "onUpdateRemoteControlClientMetadata(genId=" + genId +
- ", what=" + key + ",rating=" + value + ")");
- synchronized(mPRStack) {
- synchronized(mCurrentRcLock) {
- if ((mCurrentRcClient != null) && (mCurrentRcClientGen == genId)) {
- try {
- switch (key) {
- case MediaMetadataEditor.RATING_KEY_BY_USER:
- mCurrentRcClient.updateMetadata(genId, key, value);
- break;
- default:
- Log.e(TAG, "unhandled metadata key " + key + " update for RCC "
- + genId);
- break;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Current valid remote client is dead", e);
- mCurrentRcClient = null;
- }
- }
- }
- }
- }
-
- protected void setPlaybackInfoForRcc(int rccId, int what, int value) {
- sendMsg(mEventHandler, MSG_RCC_NEW_PLAYBACK_INFO, SENDMSG_QUEUE,
- rccId /* arg1 */, what /* arg2 */, Integer.valueOf(value) /* obj */, 0 /* delay */);
- }
-
- // handler for MSG_RCC_NEW_PLAYBACK_INFO
- private void onNewPlaybackInfoForRcc(int rccId, int key, int value) {
- if(DEBUG_RC) Log.d(TAG, "onNewPlaybackInfoForRcc(id=" + rccId +
- ", what=" + key + ",val=" + value + ")");
- synchronized(mPRStack) {
- // iterating from top of stack as playback information changes are more likely
- // on entries at the top of the remote control stack
- try {
- for (int index = mPRStack.size()-1; index >= 0; index--) {
- final PlayerRecord prse = mPRStack.elementAt(index);
- if (prse.getRccId() == rccId) {
- switch (key) {
- case RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE:
- prse.mPlaybackType = value;
- postReevaluateRemote();
- break;
- case RemoteControlClient.PLAYBACKINFO_VOLUME:
- prse.mPlaybackVolume = value;
- synchronized (mMainRemote) {
- if (rccId == mMainRemote.mRccId) {
- mMainRemote.mVolume = value;
- mVolumeController.postHasNewRemotePlaybackInfo();
- }
- }
- break;
- case RemoteControlClient.PLAYBACKINFO_VOLUME_MAX:
- prse.mPlaybackVolumeMax = value;
- synchronized (mMainRemote) {
- if (rccId == mMainRemote.mRccId) {
- mMainRemote.mVolumeMax = value;
- mVolumeController.postHasNewRemotePlaybackInfo();
- }
- }
- break;
- case RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING:
- prse.mPlaybackVolumeHandling = value;
- synchronized (mMainRemote) {
- if (rccId == mMainRemote.mRccId) {
- mMainRemote.mVolumeHandling = value;
- mVolumeController.postHasNewRemotePlaybackInfo();
- }
- }
- break;
- case RemoteControlClient.PLAYBACKINFO_USES_STREAM:
- prse.mPlaybackStream = value;
- break;
- default:
- Log.e(TAG, "unhandled key " + key + " for RCC " + rccId);
- break;
- }
- return;
- }
- }//for
- } catch (ArrayIndexOutOfBoundsException e) {
- // not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index mPRStack on onNewPlaybackInfoForRcc, lock error? ", e);
- }
- }
- }
-
- protected void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) {
- sendMsg(mEventHandler, MSG_RCC_NEW_PLAYBACK_STATE, SENDMSG_QUEUE,
- rccId /* arg1 */, state /* arg2 */,
- new PlayerRecord.RccPlaybackState(state, timeMs, speed) /* obj */, 0 /* delay */);
- }
-
- private void onNewPlaybackStateForRcc(int rccId, int state,
- PlayerRecord.RccPlaybackState newState) {
- if(DEBUG_RC) Log.d(TAG, "onNewPlaybackStateForRcc(id=" + rccId + ", state=" + state
- + ", time=" + newState.mPositionMs + ", speed=" + newState.mSpeed + ")");
- synchronized(mPRStack) {
- if (mPRStack.empty()) {
- return;
- }
- PlayerRecord oldTopPrse = mPRStack.lastElement(); // top of the stack before any changes
- PlayerRecord prse = null;
- int lastPlayingIndex = mPRStack.size();
- int inStackIndex = -1;
- try {
- // go through the stack from the top to figure out who's playing, and the position
- // of this RemoteControlClient (note that it may not be in the stack)
- for (int index = mPRStack.size()-1; index >= 0; index--) {
- prse = mPRStack.elementAt(index);
- if (prse.getRccId() == rccId) {
- inStackIndex = index;
- prse.mPlaybackState = newState;
- }
- if (prse.isPlaybackActive()) {
- lastPlayingIndex = index;
- }
- }
-
- if (inStackIndex != -1) {
- // is in the stack
- prse = mPRStack.elementAt(inStackIndex);
- synchronized (mMainRemote) {
- if (rccId == mMainRemote.mRccId) {
- mMainRemoteIsActive = isPlaystateActive(state);
- postReevaluateRemote();
- }
- }
- if (mPRStack.size() > 1) { // no need to remove and add if stack contains only 1
- // remove it from its old location in the stack
- mPRStack.removeElementAt(inStackIndex);
- if (prse.isPlaybackActive()) {
- // and put it at the top
- mPRStack.push(prse);
- } else {
- // and put it after the ones with active playback
- if (inStackIndex > lastPlayingIndex) {
- mPRStack.add(lastPlayingIndex, prse);
- } else {
- mPRStack.add(lastPlayingIndex - 1, prse);
- }
- }
- }
-
- if (oldTopPrse != mPRStack.lastElement()) {
- // the top of the stack changed:
- final ComponentName target =
- mPRStack.lastElement().getMediaButtonReceiver();
- if (target != null) {
- // post message to persist the default media button receiver
- mEventHandler.sendMessage( mEventHandler.obtainMessage(
- MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
- }
- // reevaluate the display
- checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- // not expected to happen, indicates improper concurrent modification or bad index
- Log.e(TAG, "Wrong index (inStack=" + inStackIndex + " lastPlaying=" + lastPlayingIndex
- + " size=" + mPRStack.size()
- + "accessing PlayerRecord stack in onNewPlaybackStateForRcc", e);
- }
- }
- }
-
- protected void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
- sendMsg(mEventHandler, MSG_RCC_NEW_VOLUME_OBS, SENDMSG_QUEUE,
- rccId /* arg1 */, 0, rvo /* obj */, 0 /* delay */);
- }
-
// handler for MSG_RCC_NEW_VOLUME_OBS
private void onRegisterVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
synchronized(mPRStack) {
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index ddd5b72..3336694 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -29,7 +29,6 @@
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.session.MediaSession;
-import android.media.session.RemoteVolumeProvider;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
@@ -2204,10 +2203,10 @@
return;
}
if (mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
- int volumeControl = RemoteVolumeProvider.VOLUME_CONTROL_FIXED;
+ int volumeControl = VolumeProvider.VOLUME_CONTROL_FIXED;
switch (mVolumeHandling) {
case RemoteControlClient.PLAYBACK_VOLUME_VARIABLE:
- volumeControl = RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE;
+ volumeControl = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
break;
case RemoteControlClient.PLAYBACK_VOLUME_FIXED:
default:
@@ -2226,7 +2225,7 @@
}
}
- class SessionVolumeProvider extends RemoteVolumeProvider {
+ class SessionVolumeProvider extends VolumeProvider {
public SessionVolumeProvider(int volumeControl, int maxVolume) {
super(volumeControl, maxVolume);
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 76c7299..be96398 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -361,18 +361,10 @@
if (timeMs < 0) {
throw new IllegalArgumentException("illegal negative time value");
}
- if (USE_SESSIONS) {
- synchronized (mInfoLock) {
- if (mCurrentSession != null) {
- mCurrentSession.getTransportControls().seekTo(timeMs);
- }
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ mCurrentSession.getTransportControls().seekTo(timeMs);
}
- } else {
- final int genId;
- synchronized (mGenLock) {
- genId = mClientGenerationIdCurrent;
- }
- mAudioManager.setRemoteControlClientPlaybackPosition(genId, timeMs);
}
return true;
}
@@ -534,34 +526,15 @@
if (!mMetadataChanged) {
return;
}
- if (USE_SESSIONS) {
- synchronized (mInfoLock) {
- if (mCurrentSession != null) {
- if (mEditorMetadata.containsKey(
- String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER))) {
- Rating rating = (Rating) getObject(
- MediaMetadataEditor.RATING_KEY_BY_USER, null);
- if (rating != null) {
- mCurrentSession.getTransportControls().setRating(rating);
- }
- }
- }
- }
- } else {
- final int genId;
- synchronized(mGenLock) {
- genId = mClientGenerationIdCurrent;
- }
- synchronized(mInfoLock) {
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
if (mEditorMetadata.containsKey(
String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER))) {
Rating rating = (Rating) getObject(
MediaMetadataEditor.RATING_KEY_BY_USER, null);
- mAudioManager.updateRemoteControlClientMetadata(genId,
- MediaMetadataEditor.RATING_KEY_BY_USER,
- rating);
- } else {
- Log.e(TAG, "no metadata to apply");
+ if (rating != null) {
+ mCurrentSession.getTransportControls().setRating(rating);
+ }
}
}
}
diff --git a/media/java/android/media/session/RemoteVolumeProvider.java b/media/java/android/media/VolumeProvider.java
similarity index 92%
rename from media/java/android/media/session/RemoteVolumeProvider.java
rename to media/java/android/media/VolumeProvider.java
index 606b1d7..7d93b40 100644
--- a/media/java/android/media/session/RemoteVolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.session;
+package android.media;
+import android.media.session.MediaSession;
import android.os.RemoteException;
import android.util.Log;
@@ -24,8 +25,8 @@
* You can set a volume provider on a session by calling
* {@link MediaSession#setPlaybackToRemote}.
*/
-public abstract class RemoteVolumeProvider {
- private static final String TAG = "RemoteVolumeProvider";
+public abstract class VolumeProvider {
+ private static final String TAG = "VolumeProvider";
/**
* The volume is fixed and can not be modified. Requests to change volume
@@ -60,7 +61,7 @@
* this provider.
* @param maxVolume The maximum allowed volume.
*/
- public RemoteVolumeProvider(int volumeControl, int maxVolume) {
+ public VolumeProvider(int volumeControl, int maxVolume) {
mControlType = volumeControl;
mMaxVolume = maxVolume;
}
@@ -117,7 +118,7 @@
/**
* @hide
*/
- void setSession(MediaSession session) {
+ public void setSession(MediaSession session) {
mSession = session;
}
}
\ No newline at end of file
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 1cfc5bc..5bc0de4 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -15,6 +15,7 @@
package android.media.session;
+import android.content.ComponentName;
import android.media.MediaMetadata;
import android.media.session.ISessionController;
import android.media.session.RouteOptions;
@@ -33,6 +34,7 @@
ISessionController getController();
void setFlags(int flags);
void setActive(boolean active);
+ void setMediaButtonReceiver(in ComponentName mbr);
void destroy();
// These commands are for setting up and communicating with routes
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index f0cd785..b4c11f6 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -20,6 +20,7 @@
import android.media.Rating;
import android.media.session.ISessionControllerCallback;
import android.media.session.MediaSessionInfo;
+import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -38,6 +39,9 @@
void showRoutePicker();
MediaSessionInfo getSessionInfo();
long getFlags();
+ ParcelableVolumeInfo getVolumeAttributes();
+ void adjustVolumeBy(int delta, int flags);
+ void setVolumeTo(int value, int flags);
// These commands are for the TransportController
void play();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 87a43e4..84dad25 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,6 +18,7 @@
import android.media.MediaMetadata;
import android.media.Rating;
+import android.media.VolumeProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -183,6 +184,23 @@
}
/**
+ * Get the current volume info for this session.
+ *
+ * @return The current volume info or null.
+ */
+ public VolumeInfo getVolumeInfo() {
+ try {
+ ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
+ return new VolumeInfo(result.volumeType, result.audioStream, result.controlType,
+ result.maxVolume, result.currentVolume);
+
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling getVolumeInfo.", e);
+ }
+ return null;
+ }
+
+ /**
* Adds a callback to receive updates from the Session. Updates will be
* posted on the caller's thread.
*
@@ -509,6 +527,85 @@
}
}
+ /**
+ * Holds information about the way volume is handled for this session.
+ */
+ public static final class VolumeInfo {
+ private final int mVolumeType;
+ private final int mAudioStream;
+ private final int mVolumeControl;
+ private final int mMaxVolume;
+ private final int mCurrentVolume;
+
+ /**
+ * @hide
+ */
+ public VolumeInfo(int type, int stream, int control, int max, int current) {
+ mVolumeType = type;
+ mAudioStream = stream;
+ mVolumeControl = control;
+ mMaxVolume = max;
+ mCurrentVolume = current;
+ }
+
+ /**
+ * Get the type of volume handling, either local or remote. One of:
+ * <ul>
+ * <li>{@link MediaSession#VOLUME_TYPE_LOCAL}</li>
+ * <li>{@link MediaSession#VOLUME_TYPE_REMOTE}</li>
+ * </ul>
+ *
+ * @return The type of volume handling this session is using.
+ */
+ public int getVolumeType() {
+ return mVolumeType;
+ }
+
+ /**
+ * Get the stream this is currently controlling volume on. When the volume
+ * type is {@link MediaSession#VOLUME_TYPE_REMOTE} this value does not
+ * have meaning and should be ignored.
+ *
+ * @return The stream this session is playing on.
+ */
+ public int getAudioStream() {
+ return mAudioStream;
+ }
+
+ /**
+ * Get the type of volume control that can be used. One of:
+ * <ul>
+ * <li>{@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}</li>
+ * <li>{@link VolumeProvider#VOLUME_CONTROL_RELATIVE}</li>
+ * <li>{@link VolumeProvider#VOLUME_CONTROL_FIXED}</li>
+ * </ul>
+ *
+ * @return The type of volume control that may be used with this
+ * session.
+ */
+ public int getVolumeControl() {
+ return mVolumeControl;
+ }
+
+ /**
+ * Get the maximum volume that may be set for this session.
+ *
+ * @return The maximum allowed volume where this session is playing.
+ */
+ public int getMaxVolume() {
+ return mMaxVolume;
+ }
+
+ /**
+ * Get the current volume for this session.
+ *
+ * @return The current volume where this session is playing.
+ */
+ public int getCurrentVolume() {
+ return mCurrentVolume;
+ }
+ }
+
private final static class CallbackStub extends ISessionControllerCallback.Stub {
private final WeakReference<MediaController> mController;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 4ba1351..406b1c3 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -19,10 +19,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.content.ComponentName;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.Rating;
+import android.media.VolumeProvider;
import android.media.session.ISessionController;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
@@ -125,18 +127,12 @@
public static final int DISCONNECT_REASON_SESSION_DESTROYED = 5;
/**
- * The session uses local playback. Used for configuring volume handling
- * with the system.
- *
- * @hide
+ * The session uses local playback.
*/
public static final int VOLUME_TYPE_LOCAL = 1;
/**
- * The session uses remote playback. Used for configuring volume handling
- * with the system.
- *
- * @hide
+ * The session uses remote playback.
*/
public static final int VOLUME_TYPE_REMOTE = 2;
@@ -155,7 +151,7 @@
= new ArrayMap<String, RouteInterface.EventListener>();
private Route mRoute;
- private RemoteVolumeProvider mVolumeProvider;
+ private VolumeProvider mVolumeProvider;
private boolean mActive = false;;
@@ -232,6 +228,21 @@
}
/**
+ * Set a media button event receiver component to use to restart playback
+ * after an app has been stopped.
+ *
+ * @param mbr The receiver component to send the media button event to.
+ * @hide
+ */
+ public void setMediaButtonReceiver(ComponentName mbr) {
+ try {
+ mBinder.setMediaButtonReceiver(mbr);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
+ }
+ }
+
+ /**
* Set any flags for the session.
*
* @param flags The flags to set for this session.
@@ -272,7 +283,7 @@
* @param volumeProvider The provider that will handle volume changes. May
* not be null.
*/
- public void setPlaybackToRemote(RemoteVolumeProvider volumeProvider) {
+ public void setPlaybackToRemote(VolumeProvider volumeProvider) {
if (volumeProvider == null) {
throw new IllegalArgumentException("volumeProvider may not be null!");
}
@@ -524,12 +535,12 @@
}
/**
- * Notify the system that the remove volume changed.
+ * Notify the system that the remote volume changed.
*
* @param provider The provider that is handling volume changes.
* @hide
*/
- void notifyRemoteVolumeChanged(RemoteVolumeProvider provider) {
+ public void notifyRemoteVolumeChanged(VolumeProvider provider) {
if (provider == null || provider != mVolumeProvider) {
Log.w(TAG, "Received update from stale volume provider");
return;
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 801844f..838b857 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.MediaMetadata;
@@ -214,7 +215,7 @@
}
}
- public void addMediaButtonListener(PendingIntent pi,
+ public void addMediaButtonListener(PendingIntent pi, ComponentName mbrComponent,
Context context) {
if (pi == null) {
Log.w(TAG, "Pending intent was null, can't addMediaButtonListener.");
@@ -238,6 +239,7 @@
holder.mMediaButtonReceiver = new MediaButtonReceiver(pi, context);
holder.mSession.addCallback(holder.mMediaButtonReceiver, mHandler);
+ holder.mSession.setMediaButtonReceiver(mbrComponent);
if (DEBUG) {
Log.d(TAG, "addMediaButtonListener added " + pi);
}
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.aidl b/media/java/android/media/session/ParcelableVolumeInfo.aidl
new file mode 100644
index 0000000..c4250f0
--- /dev/null
+++ b/media/java/android/media/session/ParcelableVolumeInfo.aidl
@@ -0,0 +1,18 @@
+/* Copyright 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 android.media.session;
+
+parcelable ParcelableVolumeInfo;
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.java b/media/java/android/media/session/ParcelableVolumeInfo.java
new file mode 100644
index 0000000..166ccd3
--- /dev/null
+++ b/media/java/android/media/session/ParcelableVolumeInfo.java
@@ -0,0 +1,78 @@
+/* Copyright 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 android.media.session;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Convenience class for passing information about the audio configuration of a
+ * session. The public implementation is {@link MediaController.VolumeInfo}.
+ *
+ * @hide
+ */
+public class ParcelableVolumeInfo implements Parcelable {
+ public int volumeType;
+ public int audioStream;
+ public int controlType;
+ public int maxVolume;
+ public int currentVolume;
+
+ public ParcelableVolumeInfo(int volumeType, int audioStream, int controlType, int maxVolume,
+ int currentVolume) {
+ this.volumeType = volumeType;
+ this.audioStream = audioStream;
+ this.controlType = controlType;
+ this.maxVolume = maxVolume;
+ this.currentVolume = currentVolume;
+ }
+
+ public ParcelableVolumeInfo(Parcel from) {
+ volumeType = from.readInt();
+ audioStream = from.readInt();
+ controlType = from.readInt();
+ maxVolume = from.readInt();
+ currentVolume = from.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(volumeType);
+ dest.writeInt(audioStream);
+ dest.writeInt(controlType);
+ dest.writeInt(maxVolume);
+ dest.writeInt(currentVolume);
+ }
+
+
+ public static final Parcelable.Creator<ParcelableVolumeInfo> CREATOR
+ = new Parcelable.Creator<ParcelableVolumeInfo>() {
+ @Override
+ public ParcelableVolumeInfo createFromParcel(Parcel in) {
+ return new ParcelableVolumeInfo(in);
+ }
+
+ @Override
+ public ParcelableVolumeInfo[] newArray(int size) {
+ return new ParcelableVolumeInfo[size];
+ }
+ };
+}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 4fbd2a4..5f27b16 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -110,6 +110,11 @@
jfieldID certificateData;
};
+struct StateExceptionFields {
+ jmethodID init;
+ jclass classId;
+};
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -121,6 +126,7 @@
IteratorFields iterator;
EntryFields entry;
CertificateFields certificate;
+ StateExceptionFields stateException;
jclass certificateClassId;
jclass hashmapClassId;
jclass arraylistClassId;
@@ -212,6 +218,14 @@
}
}
+static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
+ ALOGE("Illegal state exception: %s (%d)", msg, err);
+
+ jobject exception = env->NewObject(gFields.stateException.classId,
+ gFields.stateException.init, static_cast<int>(err),
+ env->NewStringUTF(msg));
+ env->Throw(static_cast<jthrowable>(exception));
+}
static bool throwExceptionAsNecessary(
JNIEnv *env, status_t err, const char *msg = NULL) {
@@ -275,8 +289,7 @@
msg = errbuf.string();
}
}
- ALOGE("Illegal state exception: %s", msg);
- jniThrowException(env, "java/lang/IllegalStateException", msg);
+ throwStateException(env, msg, err);
return true;
}
return false;
@@ -608,6 +621,10 @@
FIND_CLASS(clazz, "java/util/ArrayList");
gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+ FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
+ GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
+ gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
}
static void android_media_MediaDrm_native_setup(
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index a4d292a..b8b6c04 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -169,15 +169,10 @@
return true;
}
-void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
+void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkColorType pref,
int width, int height) {
- bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
-}
-
-SkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig(
- SkBitmap::Config pref) {
-
- // Set the color space to ARGB_8888 for now
+ // Set the color space to ARGB_8888 for now (ignoring pref)
// because of limitation in hardware support.
- return SkBitmap::kARGB_8888_Config;
+ bm->setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType);
}
+
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
index e431e72..e487245 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
@@ -49,9 +49,7 @@
sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source);
bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source,
SkBitmap* bm);
- void configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, int width,
- int height);
- SkBitmap::Config getColorSpaceConfig(SkBitmap::Config pref);
+ void configBitmapSize(SkBitmap* bm, SkColorType, int width, int height);
OMXClient mClient;
};
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index bc2671011..637061d04 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -624,6 +624,7 @@
public void onWakeUp() {
synchronized (mLock) {
if (shouldEnableWakeGestureLp()) {
+ performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 9d61493..1264741 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -17,6 +17,8 @@
package com.android.server.media;
import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.routeprovider.RouteRequest;
@@ -25,7 +27,6 @@
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.media.session.MediaController;
-import android.media.session.RemoteVolumeProvider;
import android.media.session.RouteCommand;
import android.media.session.RouteInfo;
import android.media.session.RouteOptions;
@@ -34,9 +35,11 @@
import android.media.session.MediaSessionInfo;
import android.media.session.RouteInterface;
import android.media.session.PlaybackState;
+import android.media.session.ParcelableVolumeInfo;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.Rating;
+import android.media.VolumeProvider;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -107,6 +110,7 @@
// TODO define a RouteState class with relevant info
private int mRouteState;
private long mFlags;
+ private ComponentName mMediaButtonReceiver;
// TransportPerformer fields
@@ -117,9 +121,10 @@
// End TransportPerformer fields
// Volume handling fields
- private int mPlaybackType = MediaSession.VOLUME_TYPE_LOCAL;
+ private AudioManager mAudioManager;
+ private int mVolumeType = MediaSession.VOLUME_TYPE_LOCAL;
private int mAudioStream = AudioManager.STREAM_MUSIC;
- private int mVolumeControlType = RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE;
+ private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
private int mMaxVolume = 0;
private int mCurrentVolume = 0;
// End volume handling fields
@@ -140,6 +145,7 @@
mSessionCb = new SessionCb(cb);
mService = service;
mHandler = new MessageHandler(handler.getLooper());
+ mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
}
/**
@@ -187,6 +193,10 @@
return mSessionInfo;
}
+ public ComponentName getMediaButtonReceiver() {
+ return mMediaButtonReceiver;
+ }
+
/**
* Get this session's flags.
*
@@ -265,20 +275,42 @@
*
* @param delta The amount to adjust the volume by.
*/
- public void adjustVolumeBy(int delta) {
- if (mVolumeControlType == RemoteVolumeProvider.VOLUME_CONTROL_FIXED) {
- // Nothing to do, the volume cannot be changed
- return;
+ public void adjustVolumeBy(int delta, int flags) {
+ if (mVolumeType == MediaSession.VOLUME_TYPE_LOCAL) {
+ if (delta == 0) {
+ mAudioManager.adjustStreamVolume(mAudioStream, delta, flags);
+ } else {
+ int direction = 0;
+ int steps = delta;
+ if (delta > 0) {
+ direction = 1;
+ } else if (delta < 0) {
+ direction = -1;
+ steps = -delta;
+ }
+ for (int i = 0; i < steps; i++) {
+ mAudioManager.adjustStreamVolume(mAudioStream, direction, flags);
+ }
+ }
+ } else {
+ if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
+ // Nothing to do, the volume cannot be changed
+ return;
+ }
+ mSessionCb.adjustVolumeBy(delta);
}
- mSessionCb.adjustVolumeBy(delta);
}
- public void setVolumeTo(int value) {
- if (mVolumeControlType != RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
- // Nothing to do. The volume can't be set directly.
- return;
+ public void setVolumeTo(int value, int flags) {
+ if (mVolumeType == MediaSession.VOLUME_TYPE_LOCAL) {
+ mAudioManager.setStreamVolume(mAudioStream, value, flags);
+ } else {
+ if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
+ // Nothing to do. The volume can't be set directly.
+ return;
+ }
+ mSessionCb.setVolumeTo(value);
}
- mSessionCb.setVolumeTo(value);
}
/**
@@ -352,7 +384,7 @@
* @return The current type of playback.
*/
public int getPlaybackType() {
- return mPlaybackType;
+ return mVolumeType;
}
/**
@@ -683,6 +715,11 @@
}
@Override
+ public void setMediaButtonReceiver(ComponentName mbr) {
+ mMediaButtonReceiver = mbr;
+ }
+
+ @Override
public void setMetadata(MediaMetadata metadata) {
mMetadata = metadata;
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
@@ -754,7 +791,7 @@
public void configureVolumeHandling(int type, int arg1, int arg2) throws RemoteException {
switch(type) {
case MediaSession.VOLUME_TYPE_LOCAL:
- mPlaybackType = type;
+ mVolumeType = type;
int audioStream = arg1;
if (isValidStream(audioStream)) {
mAudioStream = audioStream;
@@ -764,7 +801,7 @@
}
break;
case MediaSession.VOLUME_TYPE_REMOTE:
- mPlaybackType = type;
+ mVolumeType = type;
mVolumeControlType = arg1;
mMaxVolume = arg2;
break;
@@ -985,6 +1022,35 @@
}
@Override
+ public ParcelableVolumeInfo getVolumeAttributes() {
+ synchronized (mLock) {
+ int type;
+ int max;
+ int current;
+ if (mVolumeType == MediaSession.VOLUME_TYPE_REMOTE) {
+ type = mVolumeControlType;
+ max = mMaxVolume;
+ current = mCurrentVolume;
+ } else {
+ type = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
+ max = mAudioManager.getStreamMaxVolume(mAudioStream);
+ current = mAudioManager.getStreamVolume(mAudioStream);
+ }
+ return new ParcelableVolumeInfo(mVolumeType, mAudioStream, type, max, current);
+ }
+ }
+
+ @Override
+ public void adjustVolumeBy(int delta, int flags) {
+ MediaSessionRecord.this.adjustVolumeBy(delta, flags);
+ }
+
+ @Override
+ public void setVolumeTo(int value, int flags) {
+ MediaSessionRecord.this.setVolumeTo(value, flags);
+ }
+
+ @Override
public void play() throws RemoteException {
mSessionCb.play();
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 67065ba..685717f 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -23,6 +23,7 @@
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -88,6 +89,7 @@
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
+ private ContentResolver mContentResolver;
private MediaSessionRecord mPrioritySession;
private int mCurrentUserId = -1;
@@ -115,6 +117,7 @@
mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
+ mContentResolver = getContext().getContentResolver();
}
private IAudioService getAudioService() {
@@ -381,8 +384,7 @@
return false;
}
if (compName != null) {
- final String enabledNotifListeners = Settings.Secure.getStringForUser(
- getContext().getContentResolver(),
+ final String enabledNotifListeners = Settings.Secure.getStringForUser(mContentResolver,
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
userId);
if (enabledNotifListeners != null) {
@@ -485,6 +487,9 @@
synchronized (mLock) {
List<MediaSessionRecord> records = mPriorityStack.getActiveSessions(userId);
int size = records.size();
+ if (size > 0) {
+ persistMediaButtonReceiverLocked(records.get(0));
+ }
ArrayList<MediaSessionToken> tokens = new ArrayList<MediaSessionToken>();
for (int i = 0; i < size; i++) {
tokens.add(new MediaSessionToken(records.get(i).getControllerBinder()));
@@ -504,6 +509,16 @@
}
}
+ private void persistMediaButtonReceiverLocked(MediaSessionRecord record) {
+ ComponentName receiver = record.getMediaButtonReceiver();
+ if (receiver != null) {
+ Settings.System.putStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER,
+ receiver == null ? "" : receiver.flattenToString(),
+ UserHandle.USER_CURRENT);
+ }
+ }
+
private MediaRouteProviderProxy.RoutesListener mRoutesCallback
= new MediaRouteProviderProxy.RoutesListener() {
@Override
@@ -881,14 +896,6 @@
private void dispatchAdjustVolumeByLocked(int suggestedStream, int delta, int flags,
MediaSessionRecord session) {
- int direction = 0;
- int steps = delta;
- if (delta > 0) {
- direction = 1;
- } else if (delta < 0) {
- direction = -1;
- steps = -delta;
- }
if (DEBUG) {
String sessionInfo = session == null ? null : session.getSessionInfo().toString();
Log.d(TAG, "Adjusting session " + sessionInfo + " by " + delta + ". flags=" + flags
@@ -901,6 +908,14 @@
mAudioService.adjustSuggestedStreamVolume(delta, suggestedStream, flags,
getContext().getOpPackageName());
} else {
+ int direction = 0;
+ int steps = delta;
+ if (delta > 0) {
+ direction = 1;
+ } else if (delta < 0) {
+ direction = -1;
+ steps = -delta;
+ }
for (int i = 0; i < steps; i++) {
mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
flags, getContext().getOpPackageName());
@@ -910,26 +925,7 @@
Log.e(TAG, "Error adjusting default volume.", e);
}
} else {
- if (session.getPlaybackType() == MediaSession.VOLUME_TYPE_LOCAL) {
- try {
- if (delta == 0) {
- mAudioService.adjustSuggestedStreamVolume(delta,
- session.getAudioStream(), flags,
- getContext().getOpPackageName());
- } else {
- for (int i = 0; i < steps; i++) {
- mAudioService.adjustSuggestedStreamVolume(direction,
- session.getAudioStream(), flags,
- getContext().getOpPackageName());
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error adjusting volume for stream "
- + session.getAudioStream(), e);
- }
- } else if (session.getPlaybackType() == MediaSession.VOLUME_TYPE_REMOTE) {
- session.adjustVolumeBy(delta);
- }
+ session.adjustVolumeBy(delta, flags);
}
}
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 9a5079d..3696e24 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -61,8 +61,7 @@
jobject canvas, jint width, jint height) {
SkBitmap* bitmap = new SkBitmap;
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap->allocPixels();
+ bitmap->allocN32Pixels(width, height);
bitmap->eraseColor(0);
INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(bitmap));