summaryrefslogtreecommitdiff
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/Android.bp9
-rw-r--r--media/OWNERS4
-rw-r--r--media/java/Android.bp9
-rw-r--r--media/java/android/media/AudioDeviceInfo.java22
-rw-r--r--media/java/android/media/AudioManager.java71
-rwxr-xr-xmedia/java/android/media/IAudioService.aidl4
-rw-r--r--media/java/android/media/MediaCodec.java61
-rw-r--r--media/java/android/media/MediaDrm.java562
-rw-r--r--media/java/android/media/MediaPlayer.java4
-rw-r--r--media/java/android/media/MediaRouter.java7
-rw-r--r--media/java/android/media/metrics/NetworkEvent.java86
-rw-r--r--media/java/android/media/metrics/PlaybackComponent.java3
-rw-r--r--media/java/android/media/metrics/PlaybackErrorEvent.java74
-rw-r--r--media/java/android/media/metrics/PlaybackMetrics.java101
-rw-r--r--media/java/android/media/metrics/PlaybackSession.java10
-rw-r--r--media/java/android/media/metrics/TrackChangeEvent.java229
-rw-r--r--media/java/android/media/session/ISessionManager.aidl6
-rw-r--r--media/java/android/media/session/MediaSessionManager.java50
-rw-r--r--media/java/android/media/tv/TvInputManager.java8
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/Android.bp9
-rw-r--r--media/jni/Android.bp18
-rw-r--r--media/jni/android_media_MediaDrm.cpp215
-rw-r--r--media/jni/android_media_MediaDrm.h40
-rw-r--r--media/jni/audioeffect/Android.bp9
-rw-r--r--media/jni/soundpool/Android.bp19
-rw-r--r--media/jni/soundpool/tests/Android.bp11
-rw-r--r--media/lib/remotedisplay/Android.bp9
-rw-r--r--media/lib/signer/Android.bp9
-rw-r--r--media/lib/tvremote/Android.bp9
-rw-r--r--media/lib/tvremote/tests/Android.bp9
-rw-r--r--media/mca/filterfw/Android.bp9
-rw-r--r--media/mca/filterfw/native/Android.bp9
-rw-r--r--media/mca/filterpacks/Android.bp9
-rw-r--r--media/mca/samples/CameraEffectsRecordingSample/Android.bp10
-rw-r--r--media/mca/tests/Android.bp9
-rw-r--r--media/native/midi/Android.bp9
-rw-r--r--media/packages/BluetoothMidiService/Android.bp9
-rw-r--r--media/packages/BluetoothMidiService/tests/unit/Android.bp9
-rw-r--r--media/tests/AudioPolicyTest/Android.bp9
-rw-r--r--media/tests/CameraBrowser/Android.bp9
-rw-r--r--media/tests/EffectsTest/Android.bp9
-rw-r--r--media/tests/MediaDump/Android.bp9
-rw-r--r--media/tests/MediaFrameworkTest/Android.bp9
-rw-r--r--media/tests/MediaRouter/Android.bp11
-rw-r--r--media/tests/MtpTests/Android.bp9
-rw-r--r--media/tests/ScoAudioTest/Android.bp9
-rw-r--r--media/tests/SoundPoolTest/Android.bp9
-rw-r--r--media/tests/TunerTest/Android.bp9
-rw-r--r--media/tests/audiotests/Android.bp9
-rw-r--r--media/tests/players/Android.bp9
50 files changed, 1529 insertions, 331 deletions
diff --git a/media/Android.bp b/media/Android.bp
index 8b06bb26fcf7..9268b22a929a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
aidl_interface {
name: "audio_common-aidl",
unstable: true,
diff --git a/media/OWNERS b/media/OWNERS
index e74149019b11..abfc8bfa976e 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -26,3 +26,7 @@ olly@google.com
# SEO
sungsoo@google.com
+
+# SEA/KIR/BVE
+jtinker@google.com
+robertshih@google.com
diff --git a/media/java/Android.bp b/media/java/Android.bp
index 0810699abf0a..aea63a073e95 100644
--- a/media/java/Android.bp
+++ b/media/java/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "IMidiDeviceServer.aidl",
srcs: ["android/media/midi/IMidiDeviceServer.aidl"],
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 205c1f4b4057..383c93d7716d 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -16,8 +16,10 @@
package android.media;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.util.SparseIntArray;
import java.lang.annotation.Retention;
@@ -161,6 +163,14 @@ public final class AudioDeviceInfo {
*/
public static final int TYPE_BLE_SPEAKER = 27;
+ /**
+ * A device type describing an Echo Canceller loopback Reference.
+ * This device is only used when capturing with MediaRecorder.AudioSource.ECHO_REFERENCE,
+ * which requires privileged permission
+ * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT}.
+ * @hide */
+ @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
+ public static final int TYPE_ECHO_REFERENCE = 28;
/** @hide */
@IntDef(flag = false, prefix = "TYPE", value = {
@@ -188,7 +198,8 @@ public final class AudioDeviceInfo {
TYPE_FM_TUNER,
TYPE_TV_TUNER,
TYPE_BLE_HEADSET,
- TYPE_BLE_SPEAKER}
+ TYPE_BLE_SPEAKER,
+ TYPE_ECHO_REFERENCE}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceType {}
@@ -211,7 +222,8 @@ public final class AudioDeviceInfo {
TYPE_LINE_DIGITAL,
TYPE_IP,
TYPE_BUS,
- TYPE_BLE_HEADSET}
+ TYPE_BLE_HEADSET,
+ TYPE_ECHO_REFERENCE}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeIn {}
@@ -297,6 +309,7 @@ public final class AudioDeviceInfo {
case TYPE_BUS:
case TYPE_REMOTE_SUBMIX:
case TYPE_BLE_HEADSET:
+ case TYPE_ECHO_REFERENCE:
return true;
default:
return false;
@@ -621,6 +634,8 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ECHO_REFERENCE, TYPE_ECHO_REFERENCE);
+
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
@@ -678,6 +693,9 @@ public final class AudioDeviceInfo {
EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_IN_REMOTE_SUBMIX);
EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_IN_BLE_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_ECHO_REFERENCE, AudioSystem.DEVICE_IN_ECHO_REFERENCE);
+
}
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d896c1fc82b5..f87f90d8e0a2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3123,52 +3123,57 @@ public class AudioManager {
/**
* @hide Home sound
- * Played by the framework when the home app becomes active if config_enableHomeSound is set to
- * true. This is currently only used on TV devices.
+ * <p>
+ * To be played by the framework when the home app becomes active if config_enableHomeSound is
+ * set to true. This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml.
* @see #playSoundEffect(int)
*/
public static final int FX_HOME = 11;
/**
- * @hide Fast scroll sound 1
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 1
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_1 = 12;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_1 = 12;
/**
- * @hide Fast scroll sound 2
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 2
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_2 = 13;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_2 = 13;
/**
- * @hide Fast scroll sound 3
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 3
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_3 = 14;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_3 = 14;
/**
- * @hide Fast scroll sound 4
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 4
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_4 = 15;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_4 = 15;
/**
* @hide Number of sound effects
@@ -3177,27 +3182,27 @@ public class AudioManager {
public static final int NUM_SOUND_EFFECTS = 16;
/**
- * @hide Number of fast scroll sound effects
+ * @hide Number of FX_FOCUS_NAVIGATION_REPEAT_* sound effects
*/
- public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4;
+ public static final int NUM_NAVIGATION_REPEAT_SOUND_EFFECTS = 4;
/**
* @hide
- * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[
- * @return The id of a fast scroll sound effect or -1 if out of bounds
+ * @param n a value in [0, {@link #NUM_NAVIGATION_REPEAT_SOUND_EFFECTS}[
+ * @return The id of a navigation repeat sound effect or -1 if out of bounds
*/
- public static int getNthFastScrollSoundEffectId(int n) {
+ public static int getNthNavigationRepeatSoundEffect(int n) {
switch (n) {
case 0:
- return FX_FAST_SCROLL_1;
+ return FX_FOCUS_NAVIGATION_REPEAT_1;
case 1:
- return FX_FAST_SCROLL_2;
+ return FX_FOCUS_NAVIGATION_REPEAT_2;
case 2:
- return FX_FAST_SCROLL_3;
+ return FX_FOCUS_NAVIGATION_REPEAT_3;
case 3:
- return FX_FAST_SCROLL_4;
+ return FX_FOCUS_NAVIGATION_REPEAT_4;
default:
- Log.w(TAG, "Invalid fast-scroll sound effect id: " + n);
+ Log.w(TAG, "Invalid navigation repeat sound effect id: " + n);
return -1;
}
}
@@ -3205,9 +3210,9 @@ public class AudioManager {
/**
* @hide
*/
- public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) {
try {
- getService().setFastScrollSoundEffectsEnabled(enabled);
+ getService().setNavigationRepeatSoundEffectsEnabled(enabled);
} catch (RemoteException e) {
}
@@ -3215,11 +3220,11 @@ public class AudioManager {
/**
* @hide
- * @return true if the fast scroll sound effects are enabled
+ * @return true if the navigation repeat sound effects are enabled
*/
- public boolean areFastScrollSoundEffectsEnabled() {
+ public boolean areNavigationRepeatSoundEffectsEnabled() {
try {
- return getService().areFastScrollSoundEffectsEnabled();
+ return getService().areNavigationRepeatSoundEffectsEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 71ee57e3d471..0073b5cc93b9 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -351,9 +351,9 @@ interface IAudioService {
oneway void unregisterCommunicationDeviceDispatcher(
ICommunicationDeviceDispatcher dispatcher);
- boolean areFastScrollSoundEffectsEnabled();
+ boolean areNavigationRepeatSoundEffectsEnabled();
- oneway void setFastScrollSoundEffectsEnabled(boolean enabled);
+ oneway void setNavigationRepeatSoundEffectsEnabled(boolean enabled);
boolean isHomeSoundEffectEnabled();
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 607c8f11e01a..cf31e4141a6d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2414,37 +2414,44 @@ final public class MediaCodec implements PlaybackComponent {
* This indicates that the requested key was not found when trying to
* perform a decrypt operation. The operation can be retried after adding
* the correct decryption key.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_NO_KEY}.
*/
- public static final int ERROR_NO_KEY = 1;
+ public static final int ERROR_NO_KEY = MediaDrm.ErrorCodes.ERROR_NO_KEY;
/**
* This indicates that the key used for decryption is no longer
* valid due to license term expiration. The operation can be retried
* after updating the expired keys.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_KEY_EXPIRED}.
*/
- public static final int ERROR_KEY_EXPIRED = 2;
+ public static final int ERROR_KEY_EXPIRED = MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED;
/**
* This indicates that a required crypto resource was not able to be
* allocated while attempting the requested operation. The operation
* can be retried if the app is able to release resources.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_RESOURCE_BUSY}
*/
- public static final int ERROR_RESOURCE_BUSY = 3;
+ public static final int ERROR_RESOURCE_BUSY = MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY;
/**
* This indicates that the output protection levels supported by the
* device are not sufficient to meet the requirements set by the
* content owner in the license policy.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_OUTPUT_PROTECTION}
*/
- public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+ public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION =
+ MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION;
/**
* This indicates that decryption was attempted on a session that is
* not opened, which could be due to a failure to open the session,
* closing the session prematurely, or the session being reclaimed
* by the resource manager.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_SESSION_NOT_OPENED}
*/
- public static final int ERROR_SESSION_NOT_OPENED = 5;
+ public static final int ERROR_SESSION_NOT_OPENED =
+ MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED;
/**
* This indicates that an operation was attempted that could not be
@@ -2453,23 +2460,28 @@ final public class MediaCodec implements PlaybackComponent {
* device security features that aren't supported by the device,
* or due to an internal error in the crypto system that prevents
* the specified security policy from being met.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_UNSUPPORTED_OPERATION}
*/
- public static final int ERROR_UNSUPPORTED_OPERATION = 6;
+ public static final int ERROR_UNSUPPORTED_OPERATION =
+ MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION;
/**
* This indicates that the security level of the device is not
* sufficient to meet the requirements set by the content owner
* in the license policy.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_INSUFFICIENT_SECURITY}
*/
- public static final int ERROR_INSUFFICIENT_SECURITY = 7;
+ public static final int ERROR_INSUFFICIENT_SECURITY =
+ MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY;
/**
* This indicates that the video frame being decrypted exceeds
* the size of the device's protected output buffers. When
* encountering this error the app should try playing content
* of a lower resolution.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_FRAME_TOO_LARGE}
*/
- public static final int ERROR_FRAME_TOO_LARGE = 8;
+ public static final int ERROR_FRAME_TOO_LARGE = MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE;
/**
* This error indicates that session state has been
@@ -2477,26 +2489,37 @@ final public class MediaCodec implements PlaybackComponent {
* of retaining crypto session state across device
* suspend/resume. The session must be closed and a new
* session opened to resume operation.
+ * @deprecated Please use {@link MediaDrm.ErrorCodes#ERROR_LOST_STATE}
*/
- public static final int ERROR_LOST_STATE = 9;
+ public static final int ERROR_LOST_STATE = MediaDrm.ErrorCodes.ERROR_LOST_STATE;
/** @hide */
@IntDef({
- ERROR_NO_KEY,
- ERROR_KEY_EXPIRED,
- ERROR_RESOURCE_BUSY,
- ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
- ERROR_SESSION_NOT_OPENED,
- ERROR_UNSUPPORTED_OPERATION,
- ERROR_INSUFFICIENT_SECURITY,
- ERROR_FRAME_TOO_LARGE,
- ERROR_LOST_STATE
+ MediaDrm.ErrorCodes.ERROR_NO_KEY,
+ MediaDrm.ErrorCodes.ERROR_KEY_EXPIRED,
+ MediaDrm.ErrorCodes.ERROR_RESOURCE_BUSY,
+ MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
+ MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED,
+ MediaDrm.ErrorCodes.ERROR_UNSUPPORTED_OPERATION,
+ MediaDrm.ErrorCodes.ERROR_INSUFFICIENT_SECURITY,
+ MediaDrm.ErrorCodes.ERROR_FRAME_TOO_LARGE,
+ MediaDrm.ErrorCodes.ERROR_LOST_STATE,
+ MediaDrm.ErrorCodes.ERROR_GENERIC_OEM,
+ MediaDrm.ErrorCodes.ERROR_GENERIC_PLUGIN,
+ MediaDrm.ErrorCodes.ERROR_LICENSE_PARSE,
+ MediaDrm.ErrorCodes.ERROR_MEDIA_FRAMEWORK,
+ MediaDrm.ErrorCodes.ERROR_ZERO_SUBSAMPLES
})
@Retention(RetentionPolicy.SOURCE)
public @interface CryptoErrorCode {}
/**
- * Retrieve the error code associated with a CryptoException
+ * Returns error code associated with this {@link CryptoException}.
+ * <p>
+ * Please refer to {@link MediaDrm.ErrorCodes} for the general error
+ * handling strategy and details about each possible return value.
+ *
+ * @return an error code defined in {@link MediaDrm.ErrorCodes}.
*/
@CryptoErrorCode
public int getErrorCode() {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 49f9d6612341..f7467a636024 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -23,7 +23,11 @@ import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.TestApi;
import android.app.ActivityThread;
+import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
import android.media.metrics.PlaybackComponent;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -38,7 +42,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
+import java.time.Instant;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -143,6 +151,7 @@ public final class MediaDrm implements AutoCloseable {
private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
private long mNativeContext;
+ private final String mAppPackageName;
/**
* Specify no certificate type
@@ -280,16 +289,371 @@ public final class MediaDrm implements AutoCloseable {
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
+ mAppPackageName = ActivityThread.currentOpPackageName();
native_setup(new WeakReference<MediaDrm>(this),
- getByteArrayFromUUID(uuid), ActivityThread.currentOpPackageName());
+ getByteArrayFromUUID(uuid), mAppPackageName);
mCloseGuard.open("release");
}
/**
- * Thrown when an unrecoverable failure occurs during a MediaDrm operation.
- * Extends java.lang.IllegalStateException with the addition of an error
+ * Error codes that may be returned from {@link
+ * MediaDrmStateException#getErrorCode()} and {@link
+ * MediaCodec.CryptoException#getErrorCode()}
+ * <p>
+ * The description of each error code includes steps that may be taken to
+ * resolve the error condition. For some errors however, a recovery action
+ * cannot be predetermined. The description of those codes refers to a
+ * general strategy for handling the error condition programmatically, which
+ * is to try the following in listed order until successful:
+ * <ol>
+ * <li> retry the operation </li>
+ * <li> if the operation is related to a session, {@link
+ * #closeSession(byte[]) close} the session, {@link #openSession() open} a
+ * new session, and retry the operation </li>
+ * <li> {@link #close() close} the {@link MediaDrm} instance and any other
+ * related components such as the {@link MediaCodec codec} and retry
+ * playback, or </li>
+ * <li> try using a different configuration of the {@link MediaDrm} plugin,
+ * such as a different {@link #openSession(int) security level}. </li>
+ * </ol>
+ * <p>
+ * If the problem still persists after all the aforementioned steps, please
+ * report the failure to the {@link MediaDrm} plugin vendor along with the
+ * {@link LogMessage log messages} returned by {@link
+ * MediaDrm#getLogMessages()}, and a bugreport if possible.
+ */
+ public final static class ErrorCodes {
+ private ErrorCodes() {}
+
+ /**
+ * ERROR_UNKNOWN is used where no other defined error code is applicable
+ * to the current failure.
+ * <p>
+ * Please see the general error handling strategy for unexpected errors
+ * described in {@link ErrorCodes}.
+ */
+ public static final int ERROR_UNKNOWN = 0;
+
+ /**
+ * The requested key was not found when trying to perform a decrypt
+ * operation.
+ * <p>
+ * The operation can be retried after adding the correct decryption key.
+ */
+ public static final int ERROR_NO_KEY = 1;
+
+ /**
+ * The key used for decryption is no longer valid due to license term
+ * expiration.
+ * <p>
+ * The operation can be retried after updating the expired keys.
+ */
+ public static final int ERROR_KEY_EXPIRED = 2;
+
+ /**
+ * A required crypto resource was not able to be allocated while
+ * attempting the requested operation.
+ * <p>
+ * The operation can be retried if the app is able to release resources.
+ */
+ public static final int ERROR_RESOURCE_BUSY = 3;
+
+ /**
+ * The output protection levels supported by the device are not
+ * sufficient to meet the requirements set by the content owner in the
+ * license policy.
+ */
+ public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+
+ /**
+ * Decryption was attempted on a session that is not opened, which could
+ * be due to a failure to open the session, closing the session
+ * prematurely, the session being reclaimed by the resource manager, or
+ * a non-existent session id.
+ */
+ public static final int ERROR_SESSION_NOT_OPENED = 5;
+
+ /**
+ * An operation was attempted that could not be supported by the crypto
+ * system of the device in its current configuration.
+ * <p>
+ * This may occur when the license policy requires device security
+ * features that aren't supported by the device, or due to an internal
+ * error in the crypto system that prevents the specified security
+ * policy from being met.
+ */
+ public static final int ERROR_UNSUPPORTED_OPERATION = 6;
+
+ /**
+ * The security level of the device is not sufficient to meet the
+ * requirements set by the content owner in the license policy.
+ */
+ public static final int ERROR_INSUFFICIENT_SECURITY = 7;
+
+ /**
+ * The video frame being decrypted exceeds the size of the device's
+ * protected output buffers.
+ * <p>
+ * When encountering this error the app should try playing content
+ * of a lower resolution or skipping the problematic frame.
+ */
+ public static final int ERROR_FRAME_TOO_LARGE = 8;
+
+ /**
+ * The session state has been invalidated. This can occur on devices
+ * that are not capable of retaining crypto session state across device
+ * suspend/resume.
+ * <p>
+ * The session must be closed and a new session opened to resume
+ * operation.
+ */
+ public static final int ERROR_LOST_STATE = 9;
+
+ /**
+ * Certificate is malformed or is of the wrong type.
+ * <p>
+ * Ensure the certificate provided by the app or returned from the
+ * license server is valid. Check with the {@link MediaDrm} plugin
+ * vendor for the expected certificate format.
+ */
+ public static final int ERROR_CERTIFICATE_MALFORMED = 10;
+
+ /**
+ * Certificate has not been set.
+ * <p>
+ * Ensure the certificate has been provided by the app. Check with the
+ * {@link MediaDrm} plugin vendor for the expected method to provide
+ * {@link MediaDrm} a certificate.
+ */
+ public static final int ERROR_CERTIFICATE_MISSING = 11;
+
+ /**
+ * An error happened within the crypto library used by the drm plugin.
+ */
+ public static final int ERROR_CRYPTO_LIBRARY = 12;
+
+ /**
+ * Unexpected error reported by the device OEM subsystem.
+ * <p>
+ * Please see the general error handling strategy for unexpected errors
+ * described in {@link ErrorCodes}.
+ */
+ public static final int ERROR_GENERIC_OEM = 13;
+
+ /**
+ * Unexpected internal failure in {@link MediaDrm}/{@link MediaCrypto}.
+ * <p>
+ * Please see the general error handling strategy for unexpected errors
+ * described in {@link ErrorCodes}.
+ */
+ public static final int ERROR_GENERIC_PLUGIN = 14;
+
+ /**
+ * The init data parameter passed to {@link MediaDrm#getKeyRequest} is
+ * empty or invalid.
+ * <p>
+ * Init data is typically obtained from {@link
+ * MediaExtractor#getPsshInfo()} or {@link
+ * MediaExtractor#getDrmInitData()}. Check with the {@link MediaDrm}
+ * plugin vendor for the expected init data format.
+ */
+ public static final int ERROR_INIT_DATA = 15;
+
+ /**
+ * Either the key was not loaded from the license before attempting the
+ * operation, or the key ID parameter provided by the app is incorrect.
+ * <p>
+ * Ensure the proper keys are in the license, and check the key ID
+ * parameter provided by the app is correct. Check with the {@link
+ * MediaDrm} plugin vendor for the expected license format.
+ */
+ public static final int ERROR_KEY_NOT_LOADED = 16;
+
+ /**
+ * The license response was empty, fields are missing or otherwise
+ * unable to be parsed or decrypted.
+ * <p>
+ * Check for mistakes such as empty or overwritten buffers. Otherwise,
+ * check with the {@link MediaDrm} plugin vendor for the expected
+ * license format.
+ */
+ public static final int ERROR_LICENSE_PARSE = 17;
+
+ /**
+ * The operation (e.g. to renew or persist a license) is prohibited by
+ * the license policy.
+ * <p>
+ * Check the license policy configuration on the license server.
+ */
+ public static final int ERROR_LICENSE_POLICY = 18;
+
+ /**
+ * Failed to generate a release request because a field in the offline
+ * license is empty or malformed.
+ * <p>
+ * The license can't be released on the server, but the app may remove
+ * the offline license explicitly using {@link
+ * MediaDrm#removeOfflineLicense}.
+ */
+ public static final int ERROR_LICENSE_RELEASE = 19;
+
+ /**
+ * The license server detected an error in the license request.
+ * <p>
+ * Check for errors on the license server.
+ */
+ public static final int ERROR_LICENSE_REQUEST_REJECTED = 20;
+
+ /**
+ * Failed to restore an offline license because a field in the offline
+ * license is empty or malformed.
+ * <p>
+ * Try requesting the license again if the device is online.
+ */
+ public static final int ERROR_LICENSE_RESTORE = 21;
+
+ /**
+ * Offline license is in an invalid state for the attempted operation.
+ * <p>
+ * Check the sequence of API calls made that can affect offline license
+ * state. For example, this could happen when the app attempts to
+ * restore a license after it has been released.
+ */
+ public static final int ERROR_LICENSE_STATE = 22;
+
+ /**
+ * Failure in the media framework.
+ * <p>
+ * Try releasing media resources (e.g. {@link MediaCodec}, {@link
+ * MediaDrm}), and restarting playback.
+ */
+ public static final int ERROR_MEDIA_FRAMEWORK = 23;
+
+ /**
+ * Error loading the provisioned certificate.
+ * <p>
+ * Re-provisioning may resolve the problem; check with the {@link
+ * MediaDrm} plugin vendor for re-provisioning instructions. Otherwise,
+ * using a different security level may resolve the issue.
+ */
+ public static final int ERROR_PROVISIONING_CERTIFICATE = 24;
+
+ /**
+ * Required steps were not performed before provisioning was attempted.
+ * <p>
+ * Ask the {@link MediaDrm} plugin vendor for situations where this
+ * error may occur.
+ */
+ public static final int ERROR_PROVISIONING_CONFIG = 25;
+
+ /**
+ * The provisioning response was empty, fields are missing or otherwise
+ * unable to be parsed.
+ * <p>
+ * Check for mistakes such as empty or overwritten buffers. Otherwise,
+ * check with the {@link MediaDrm} plugin vendor for the expected
+ * provisioning response format.
+ */
+ public static final int ERROR_PROVISIONING_PARSE = 26;
+
+ /**
+ * Provisioning failed in a way that is likely to succeed on a
+ * subsequent attempt.
+ * <p>
+ * The app should retry the operation.
+ */
+ public static final int ERROR_PROVISIONING_RETRY = 27;
+
+ /**
+ * This indicates that apps using MediaDrm sessions are
+ * temporarily exceeding the capacity of available crypto
+ * resources.
+ * <p>
+ * The app should retry the operation later.
+ */
+ public static final int ERROR_RESOURCE_CONTENTION = 28;
+
+ /**
+ * Failed to generate a secure stop request because a field in the
+ * stored license is empty or malformed.
+ * <p>
+ * The secure stop can't be released on the server, but the app may
+ * remove it explicitly using {@link MediaDrm#removeSecureStop}.
+ */
+ public static final int ERROR_SECURE_STOP_RELEASE = 29;
+
+ /**
+ * The plugin was unable to read data from the filesystem.
+ * <p>
+ * Please see the general error handling strategy for unexpected errors
+ * described in {@link ErrorCodes}.
+ */
+ public static final int ERROR_STORAGE_READ = 30;
+
+ /**
+ * The plugin was unable to write data to the filesystem.
+ * <p>
+ * Please see the general error handling strategy for unexpected errors
+ * described in {@link ErrorCodes}.
+ */
+ public static final int ERROR_STORAGE_WRITE = 31;
+
+ /**
+ * {@link MediaCodec#queueSecureInputBuffer} called with 0 subsamples.
+ * <p>
+ * Check the {@link MediaCodec.CryptoInfo} object passed to {@link
+ * MediaCodec#queueSecureInputBuffer}.
+ */
+ public static final int ERROR_ZERO_SUBSAMPLES = 32;
+
+ }
+
+ /** @hide */
+ @IntDef({
+ ErrorCodes.ERROR_NO_KEY,
+ ErrorCodes.ERROR_KEY_EXPIRED,
+ ErrorCodes.ERROR_RESOURCE_BUSY,
+ ErrorCodes.ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
+ ErrorCodes.ERROR_SESSION_NOT_OPENED,
+ ErrorCodes.ERROR_UNSUPPORTED_OPERATION,
+ ErrorCodes.ERROR_INSUFFICIENT_SECURITY,
+ ErrorCodes.ERROR_FRAME_TOO_LARGE,
+ ErrorCodes.ERROR_LOST_STATE,
+ ErrorCodes.ERROR_CERTIFICATE_MALFORMED,
+ ErrorCodes.ERROR_CERTIFICATE_MISSING,
+ ErrorCodes.ERROR_CRYPTO_LIBRARY,
+ ErrorCodes.ERROR_GENERIC_OEM,
+ ErrorCodes.ERROR_GENERIC_PLUGIN,
+ ErrorCodes.ERROR_INIT_DATA,
+ ErrorCodes.ERROR_KEY_NOT_LOADED,
+ ErrorCodes.ERROR_LICENSE_PARSE,
+ ErrorCodes.ERROR_LICENSE_POLICY,
+ ErrorCodes.ERROR_LICENSE_RELEASE,
+ ErrorCodes.ERROR_LICENSE_REQUEST_REJECTED,
+ ErrorCodes.ERROR_LICENSE_RESTORE,
+ ErrorCodes.ERROR_LICENSE_STATE,
+ ErrorCodes.ERROR_MEDIA_FRAMEWORK,
+ ErrorCodes.ERROR_PROVISIONING_CERTIFICATE,
+ ErrorCodes.ERROR_PROVISIONING_CONFIG,
+ ErrorCodes.ERROR_PROVISIONING_PARSE,
+ ErrorCodes.ERROR_PROVISIONING_RETRY,
+ ErrorCodes.ERROR_SECURE_STOP_RELEASE,
+ ErrorCodes.ERROR_STORAGE_READ,
+ ErrorCodes.ERROR_STORAGE_WRITE,
+ ErrorCodes.ERROR_ZERO_SUBSAMPLES
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MediaDrmErrorCode {}
+
+ /**
+ * Thrown when a general failure occurs during a MediaDrm operation.
+ * Extends {@link IllegalStateException} with the addition of an error
* code that may be useful in diagnosing the failure.
+ * <p>
+ * Please refer to {@link ErrorCodes} for the general error handling
+ * strategy and details about each possible return value from {@link
+ * MediaDrmStateException#getErrorCode()}.
*/
public static final class MediaDrmStateException extends java.lang.IllegalStateException {
private final int mErrorCode;
@@ -310,15 +674,30 @@ public final class MediaDrm implements AutoCloseable {
}
/**
- * Retrieve the associated error code
+ * Returns error code associated with this {@link
+ * MediaDrmStateException}.
+ * <p>
+ * Please refer to {@link ErrorCodes} for the general error handling
+ * strategy and details about each possible return value.
*
- * @hide
+ * @return an error code defined in {@link MediaDrm.ErrorCodes}.
*/
+ @MediaDrmErrorCode
public int getErrorCode() {
return mErrorCode;
}
/**
+ * Returns true if the {@link MediaDrmStateException} is a transient
+ * issue, perhaps due to resource constraints, and that the operation
+ * (e.g. provisioning) may succeed on a subsequent attempt.
+ */
+ public boolean isTransient() {
+ return mErrorCode == ErrorCodes.ERROR_PROVISIONING_RETRY
+ || mErrorCode == ErrorCodes.ERROR_RESOURCE_CONTENTION;
+ }
+
+ /**
* Retrieve a developer-readable diagnostic information string
* associated with the exception. Do not show this to end-users,
* since this string will not be localized or generally comprehensible
@@ -331,7 +710,13 @@ public final class MediaDrm implements AutoCloseable {
}
/**
- * Thrown when an error occurs in any method that has a session context.
+ * {@link SessionException} is a misnomer because it may occur in methods
+ * <b>without</b> a session context.
+ * <p>
+ * A {@link SessionException} is most likely to be thrown when an operation
+ * failed in a way that is likely to succeed on a subsequent attempt; call
+ * {@link #isTransient()} to determine whether the app should retry the
+ * failing operation.
*/
public static final class SessionException extends RuntimeException {
public SessionException(int errorCode, @Nullable String detailMessage) {
@@ -341,6 +726,7 @@ public final class MediaDrm implements AutoCloseable {
/**
* The SessionException has an unknown error code.
+ * @deprecated Unused.
*/
public static final int ERROR_UNKNOWN = 0;
@@ -348,6 +734,10 @@ public final class MediaDrm implements AutoCloseable {
* This indicates that apps using MediaDrm sessions are
* temporarily exceeding the capacity of available crypto
* resources. The app should retry the operation later.
+ *
+ * @deprecated Please use {@link #isTransient()} instead of comparing
+ * the return value of {@link #getErrorCode()} against
+ * {@link SessionException#ERROR_RESOURCE_CONTENTION}.
*/
public static final int ERROR_RESOURCE_CONTENTION = 1;
@@ -360,12 +750,26 @@ public final class MediaDrm implements AutoCloseable {
/**
* Retrieve the error code associated with the SessionException
+ *
+ * @deprecated Please use {@link #isTransient()} instead of comparing
+ * the return value of {@link #getErrorCode()} against
+ * {@link SessionException#ERROR_RESOURCE_CONTENTION}.
*/
@SessionErrorCode
public int getErrorCode() {
return mErrorCode;
}
+ /**
+ * Returns true if the {@link SessionException} is a transient
+ * issue, perhaps due to resource constraints, and that the operation
+ * (e.g. provisioning, generating requests) may succeed on a subsequent
+ * attempt.
+ */
+ public boolean isTransient() {
+ return mErrorCode == ERROR_RESOURCE_CONTENTION;
+ }
+
private final int mErrorCode;
}
@@ -1143,12 +1547,78 @@ public final class MediaDrm implements AutoCloseable {
* problem with the certifcate
*/
@NonNull
- public native KeyRequest getKeyRequest(
+ public KeyRequest getKeyRequest(
@NonNull byte[] scope, @Nullable byte[] init,
@Nullable String mimeType, @KeyType int keyType,
@Nullable HashMap<String, String> optionalParameters)
- throws NotProvisionedException;
+ throws NotProvisionedException {
+ HashMap<String, String> internalParams;
+ if (optionalParameters == null) {
+ internalParams = new HashMap<>();
+ } else {
+ internalParams = new HashMap<>(optionalParameters);
+ }
+ byte[] rawBytes = getNewestAvailablePackageCertificateRawBytes();
+ byte[] hashBytes = null;
+ if (rawBytes != null) {
+ hashBytes = getDigestBytes(rawBytes, "SHA-256");
+ }
+ if (hashBytes != null) {
+ Base64.Encoder encoderB64 = Base64.getEncoder();
+ String hashBytesB64 = encoderB64.encodeToString(hashBytes);
+ internalParams.put("package_certificate_hash_bytes", hashBytesB64);
+ }
+ return getKeyRequestNative(scope, init, mimeType, keyType, internalParams);
+ }
+ @Nullable
+ private byte[] getNewestAvailablePackageCertificateRawBytes() {
+ Application application = ActivityThread.currentApplication();
+ if (application == null) {
+ Log.w(TAG, "pkg cert: Application is null");
+ return null;
+ }
+ PackageManager pm = application.getPackageManager();
+ if (pm == null) {
+ Log.w(TAG, "pkg cert: PackageManager is null");
+ return null;
+ }
+ PackageInfo packageInfo = null;
+ try {
+ packageInfo = pm.getPackageInfo(mAppPackageName,
+ PackageManager.GET_SIGNING_CERTIFICATES);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, mAppPackageName, e);
+ }
+ if (packageInfo == null || packageInfo.signingInfo == null) {
+ Log.w(TAG, "pkg cert: PackageInfo or SigningInfo is null");
+ return null;
+ }
+ Signature[] signers = packageInfo.signingInfo.getApkContentsSigners();
+ if (signers != null && signers.length == 1) {
+ return signers[0].toByteArray();
+ }
+ Log.w(TAG, "pkg cert: " + signers.length + " signers");
+ return null;
+ }
+
+ @Nullable
+ private static byte[] getDigestBytes(@NonNull byte[] rawBytes, @NonNull String algorithm) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+ return messageDigest.digest(rawBytes);
+ } catch (NoSuchAlgorithmException e) {
+ Log.w(TAG, algorithm, e);
+ }
+ return null;
+ }
+
+ @NonNull
+ private native KeyRequest getKeyRequestNative(
+ @NonNull byte[] scope, @Nullable byte[] init,
+ @Nullable String mimeType, @KeyType int keyType,
+ @Nullable HashMap<String, String> optionalParameters)
+ throws NotProvisionedException;
/**
* A key response is received from the license server by the app, then it is
@@ -2493,4 +2963,80 @@ public final class MediaDrm implements AutoCloseable {
return mPlaybackId;
}
}
+
+ /**
+ * Returns recent {@link LogMessage LogMessages} associated with this {@link MediaDrm}
+ * instance.
+ */
+ @NonNull
+ public native List<LogMessage> getLogMessages();
+
+ /**
+ * A {@link LogMessage} records an event in the {@link MediaDrm} framework
+ * or vendor plugin.
+ */
+ public static class LogMessage {
+
+ /**
+ * Timing of the recorded event measured in milliseconds since the Epoch,
+ * 1970-01-01 00:00:00 +0000 (UTC).
+ */
+ public final long timestampMillis;
+
+ /**
+ * Priority of the recorded event.
+ * <p>
+ * Possible priority constants are defined in {@link Log}, e.g.:
+ * <ul>
+ * <li>{@link Log#ASSERT}</li>
+ * <li>{@link Log#ERROR}</li>
+ * <li>{@link Log#WARN}</li>
+ * <li>{@link Log#INFO}</li>
+ * <li>{@link Log#DEBUG}</li>
+ * <li>{@link Log#VERBOSE}</li>
+ * </ul>
+ */
+ @Log.Level
+ public final int priority;
+
+ /**
+ * Description of the recorded event.
+ */
+ @NonNull
+ public final String message;
+
+ private LogMessage(long timestampMillis, int priority, String message) {
+ this.timestampMillis = timestampMillis;
+ if (priority < Log.VERBOSE || priority > Log.ASSERT) {
+ throw new IllegalArgumentException("invalid log priority " + priority);
+ }
+ this.priority = priority;
+ this.message = message;
+ }
+
+ private char logPriorityChar() {
+ switch (priority) {
+ case Log.VERBOSE:
+ return 'V';
+ case Log.DEBUG:
+ return 'D';
+ case Log.INFO:
+ return 'I';
+ case Log.WARN:
+ return 'W';
+ case Log.ERROR:
+ return 'E';
+ case Log.ASSERT:
+ return 'F';
+ default:
+ }
+ return 'U';
+ }
+
+ @Override
+ public String toString() {
+ return String.format("LogMessage{%s %c %s}",
+ Instant.ofEpochMilli(timestampMillis), logPriorityChar(), message);
+ }
+ }
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2c45ed3cb861..c51c9dd06c24 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -921,7 +921,7 @@ public class MediaPlayer extends PlayerBase
final AudioAttributes aa = audioAttributes != null ? audioAttributes :
new AudioAttributes.Builder().build();
mp.setAudioAttributes(aa);
- mp.setAudioSessionId(audioSessionId);
+ mp.native_setAudioSessionId(audioSessionId);
mp.setDataSource(context, uri);
if (holder != null) {
mp.setDisplay(holder);
@@ -987,7 +987,7 @@ public class MediaPlayer extends PlayerBase
final AudioAttributes aa = audioAttributes != null ? audioAttributes :
new AudioAttributes.Builder().build();
mp.setAudioAttributes(aa);
- mp.setAudioSessionId(audioSessionId);
+ mp.native_setAudioSessionId(audioSessionId);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 6cf99e288f1b..dc43ad342725 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -384,7 +384,12 @@ public class MediaRouter {
}
public Display[] getAllPresentationDisplays() {
- return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+ try {
+ return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+ } catch (RuntimeException ex) {
+ Log.e(TAG, "Unable to get displays.", ex);
+ return null;
+ }
}
private void updatePresentationDisplays(int changedDisplayId) {
diff --git a/media/java/android/media/metrics/NetworkEvent.java b/media/java/android/media/metrics/NetworkEvent.java
index a330bc0b66df..029edeb93374 100644
--- a/media/java/android/media/metrics/NetworkEvent.java
+++ b/media/java/android/media/metrics/NetworkEvent.java
@@ -17,6 +17,7 @@
package android.media.metrics;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -27,22 +28,30 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
- * Playback network event.
- * @hide
+ * Media network event.
*/
-public final class NetworkEvent implements Parcelable {
+public final class NetworkEvent extends Event implements Parcelable {
+ /** Network type is not specified. Default type. */
public static final int NETWORK_TYPE_NONE = 0;
+ /** Other network type */
public static final int NETWORK_TYPE_OTHER = 1;
+ /** Wi-Fi network */
public static final int NETWORK_TYPE_WIFI = 2;
+ /** Ethernet network */
public static final int NETWORK_TYPE_ETHERNET = 3;
+ /** 2G network */
public static final int NETWORK_TYPE_2G = 4;
+ /** 3G network */
public static final int NETWORK_TYPE_3G = 5;
+ /** 4G network */
public static final int NETWORK_TYPE_4G = 6;
+ /** 5G NSA network */
public static final int NETWORK_TYPE_5G_NSA = 7;
+ /** 5G SA network */
public static final int NETWORK_TYPE_5G_SA = 8;
- private final int mType;
- private final long mTimeSincePlaybackCreatedMillis;
+ private final int mNetworkType;
+ private final long mTimeSinceCreatedMillis;
/** @hide */
@IntDef(prefix = "NETWORK_TYPE_", value = {
@@ -61,6 +70,7 @@ public final class NetworkEvent implements Parcelable {
/**
* Network type to string.
+ * @hide
*/
public static String networkTypeToString(@NetworkType int value) {
switch (value) {
@@ -92,25 +102,34 @@ public final class NetworkEvent implements Parcelable {
*
* @hide
*/
- public NetworkEvent(@NetworkType int type, long timeSincePlaybackCreatedMillis) {
- this.mType = type;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ public NetworkEvent(@NetworkType int type, long timeSinceCreatedMillis) {
+ this.mNetworkType = type;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
}
+ /**
+ * Gets network type.
+ */
@NetworkType
- public int getType() {
- return mType;
+ public int getNetworkType() {
+ return mNetworkType;
}
- public long getTimeSincePlaybackCreatedMillis() {
- return mTimeSincePlaybackCreatedMillis;
+ /**
+ * Gets timestamp since the creation in milliseconds.
+ * @return the timestamp since the creation in milliseconds, or -1 if unknown.
+ */
+ @Override
+ @IntRange(from = -1)
+ public long getTimeSinceCreatedMillis() {
+ return mTimeSinceCreatedMillis;
}
@Override
public String toString() {
return "NetworkEvent { "
- + "type = " + mType + ", "
- + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + "networkType = " + mNetworkType + ", "
+ + "timeSinceCreatedMillis = " + mTimeSinceCreatedMillis
+ " }";
}
@@ -119,19 +138,19 @@ public final class NetworkEvent implements Parcelable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NetworkEvent that = (NetworkEvent) o;
- return mType == that.mType
- && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ return mNetworkType == that.mNetworkType
+ && mTimeSinceCreatedMillis == that.mTimeSinceCreatedMillis;
}
@Override
public int hashCode() {
- return Objects.hash(mType, mTimeSincePlaybackCreatedMillis);
+ return Objects.hash(mNetworkType, mTimeSinceCreatedMillis);
}
@Override
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
- dest.writeInt(mType);
- dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ dest.writeInt(mNetworkType);
+ dest.writeLong(mTimeSinceCreatedMillis);
}
@Override
@@ -142,12 +161,15 @@ public final class NetworkEvent implements Parcelable {
/** @hide */
/* package-private */ NetworkEvent(@NonNull android.os.Parcel in) {
int type = in.readInt();
- long timeSincePlaybackCreatedMillis = in.readLong();
+ long timeSinceCreatedMillis = in.readLong();
- this.mType = type;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ this.mNetworkType = type;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
}
+ /**
+ * Used to read a NetworkEvent from a Parcel.
+ */
public static final @NonNull Parcelable.Creator<NetworkEvent> CREATOR =
new Parcelable.Creator<NetworkEvent>() {
@Override
@@ -165,13 +187,11 @@ public final class NetworkEvent implements Parcelable {
* A builder for {@link NetworkEvent}
*/
public static final class Builder {
- private int mType;
- private long mTimeSincePlaybackCreatedMillis;
+ private int mNetworkType = NETWORK_TYPE_NONE;
+ private long mTimeSinceCreatedMillis = -1;
/**
* Creates a new Builder.
- *
- * @hide
*/
public Builder() {
}
@@ -179,24 +199,24 @@ public final class NetworkEvent implements Parcelable {
/**
* Sets network type.
*/
- public @NonNull Builder setType(@NetworkType int value) {
- mType = value;
+ public @NonNull Builder setNetworkType(@NetworkType int value) {
+ mNetworkType = value;
return this;
}
/**
* Sets timestamp since the creation in milliseconds.
+ * @param value the timestamp since the creation in milliseconds.
+ * -1 indicates the value is unknown.
*/
- public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
- mTimeSincePlaybackCreatedMillis = value;
+ public @NonNull Builder setTimeSinceCreatedMillis(@IntRange(from = -1) long value) {
+ mTimeSinceCreatedMillis = value;
return this;
}
/** Builds the instance. */
public @NonNull NetworkEvent build() {
- NetworkEvent o = new NetworkEvent(
- mType,
- mTimeSincePlaybackCreatedMillis);
+ NetworkEvent o = new NetworkEvent(mNetworkType, mTimeSinceCreatedMillis);
return o;
}
}
diff --git a/media/java/android/media/metrics/PlaybackComponent.java b/media/java/android/media/metrics/PlaybackComponent.java
index 94e55b4843c1..1cadf3be38ee 100644
--- a/media/java/android/media/metrics/PlaybackComponent.java
+++ b/media/java/android/media/metrics/PlaybackComponent.java
@@ -17,13 +17,10 @@
package android.media.metrics;
import android.annotation.NonNull;
-import android.annotation.TestApi;
/**
* Interface for playback related components used by playback metrics.
- * @hide
*/
-@TestApi
public interface PlaybackComponent {
/**
diff --git a/media/java/android/media/metrics/PlaybackErrorEvent.java b/media/java/android/media/metrics/PlaybackErrorEvent.java
index db7000536299..5a0820d16cb9 100644
--- a/media/java/android/media/metrics/PlaybackErrorEvent.java
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.java
@@ -17,8 +17,10 @@
package android.media.metrics;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,17 +29,19 @@ import java.util.Objects;
/**
* Playback error event.
- * @hide
*/
-public final class PlaybackErrorEvent implements Parcelable {
+public final class PlaybackErrorEvent extends Event implements Parcelable {
+ /** Unknown error code. */
public static final int ERROR_CODE_UNKNOWN = 0;
+ /** Error code for other errors */
public static final int ERROR_CODE_OTHER = 1;
+ /** Error code for runtime errors */
public static final int ERROR_CODE_RUNTIME = 2;
private final @Nullable String mExceptionStack;
private final int mErrorCode;
private final int mSubErrorCode;
- private final long mTimeSincePlaybackCreatedMillis;
+ private final long mTimeSinceCreatedMillis;
/** @hide */
@@ -59,11 +63,11 @@ public final class PlaybackErrorEvent implements Parcelable {
@Nullable String exceptionStack,
int errorCode,
int subErrorCode,
- long timeSincePlaybackCreatedMillis) {
+ long timeSinceCreatedMillis) {
this.mExceptionStack = exceptionStack;
this.mErrorCode = errorCode;
this.mSubErrorCode = subErrorCode;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
}
/** @hide */
@@ -72,17 +76,32 @@ public final class PlaybackErrorEvent implements Parcelable {
return mExceptionStack;
}
+
+ /**
+ * Gets error code.
+ */
@ErrorCode
public int getErrorCode() {
return mErrorCode;
}
+
+ /**
+ * Gets sub error code.
+ */
+ @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE)
public int getSubErrorCode() {
return mSubErrorCode;
}
- public long getTimeSincePlaybackCreatedMillis() {
- return mTimeSincePlaybackCreatedMillis;
+ /**
+ * Gets the timestamp since creation in milliseconds.
+ * @return the timestamp since the playback is created, or -1 if unknown.
+ */
+ @Override
+ @IntRange(from = -1)
+ public long getTimeSinceCreatedMillis() {
+ return mTimeSinceCreatedMillis;
}
@Override
@@ -91,7 +110,7 @@ public final class PlaybackErrorEvent implements Parcelable {
+ "exceptionStack = " + mExceptionStack + ", "
+ "errorCode = " + mErrorCode + ", "
+ "subErrorCode = " + mSubErrorCode + ", "
- + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + "timeSinceCreatedMillis = " + mTimeSinceCreatedMillis
+ " }";
}
@@ -103,13 +122,13 @@ public final class PlaybackErrorEvent implements Parcelable {
return Objects.equals(mExceptionStack, that.mExceptionStack)
&& mErrorCode == that.mErrorCode
&& mSubErrorCode == that.mSubErrorCode
- && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ && mTimeSinceCreatedMillis == that.mTimeSinceCreatedMillis;
}
@Override
public int hashCode() {
return Objects.hash(mExceptionStack, mErrorCode, mSubErrorCode,
- mTimeSincePlaybackCreatedMillis);
+ mTimeSinceCreatedMillis);
}
@Override
@@ -120,7 +139,7 @@ public final class PlaybackErrorEvent implements Parcelable {
if (mExceptionStack != null) dest.writeString(mExceptionStack);
dest.writeInt(mErrorCode);
dest.writeInt(mSubErrorCode);
- dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ dest.writeLong(mTimeSinceCreatedMillis);
}
@Override
@@ -134,14 +153,15 @@ public final class PlaybackErrorEvent implements Parcelable {
String exceptionStack = (flg & 0x1) == 0 ? null : in.readString();
int errorCode = in.readInt();
int subErrorCode = in.readInt();
- long timeSincePlaybackCreatedMillis = in.readLong();
+ long timeSinceCreatedMillis = in.readLong();
this.mExceptionStack = exceptionStack;
this.mErrorCode = errorCode;
this.mSubErrorCode = subErrorCode;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
}
+
public static final @NonNull Parcelable.Creator<PlaybackErrorEvent> CREATOR =
new Parcelable.Creator<PlaybackErrorEvent>() {
@Override
@@ -162,27 +182,18 @@ public final class PlaybackErrorEvent implements Parcelable {
private @Nullable Exception mException;
private int mErrorCode;
private int mSubErrorCode;
- private long mTimeSincePlaybackCreatedMillis;
+ private long mTimeSinceCreatedMillis = -1;
/**
* Creates a new Builder.
- *
- * @hide
*/
- public Builder(
- @Nullable Exception exception,
- int errorCode,
- int subErrorCode,
- long timeSincePlaybackCreatedMillis) {
- mException = exception;
- mErrorCode = errorCode;
- mSubErrorCode = subErrorCode;
- mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ public Builder() {
}
/**
* Sets the {@link Exception} object.
*/
+ @SuppressLint("MissingGetterMatchingBuilder") // Exception is not parcelable.
public @NonNull Builder setException(@NonNull Exception value) {
mException = value;
return this;
@@ -199,16 +210,19 @@ public final class PlaybackErrorEvent implements Parcelable {
/**
* Sets sub error code.
*/
- public @NonNull Builder setSubErrorCode(int value) {
+ public @NonNull Builder setSubErrorCode(
+ @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE) int value) {
mSubErrorCode = value;
return this;
}
/**
- * Set the timestamp in milliseconds.
+ * Set the timestamp since creation in milliseconds.
+ * @param value the timestamp since the creation in milliseconds.
+ * -1 indicates the value is unknown.
*/
- public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
- mTimeSincePlaybackCreatedMillis = value;
+ public @NonNull Builder setTimeSinceCreatedMillis(@IntRange(from = -1) long value) {
+ mTimeSinceCreatedMillis = value;
return this;
}
@@ -227,7 +241,7 @@ public final class PlaybackErrorEvent implements Parcelable {
stack,
mErrorCode,
mSubErrorCode,
- mTimeSincePlaybackCreatedMillis);
+ mTimeSinceCreatedMillis);
return o;
}
}
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index 070b4e4aa14b..4aa61662ba52 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -17,6 +17,7 @@
package android.media.metrics;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -33,35 +34,57 @@ import java.util.Objects;
/**
* This class is used to store playback data.
- * @hide
*/
public final class PlaybackMetrics implements Parcelable {
- // TODO(b/177209128): JavaDoc for the constants.
+ /** Unknown stream source. */
public static final int STREAM_SOURCE_UNKNOWN = 0;
+ /** Stream from network. */
public static final int STREAM_SOURCE_NETWORK = 1;
+ /** Stream from device. */
public static final int STREAM_SOURCE_DEVICE = 2;
+ /** Stream from more than one sources. */
public static final int STREAM_SOURCE_MIXED = 3;
+ /** Unknown stream type. */
public static final int STREAM_TYPE_UNKNOWN = 0;
+ /** Other stream type. */
public static final int STREAM_TYPE_OTHER = 1;
+ /** Progressive stream type. */
public static final int STREAM_TYPE_PROGRESSIVE = 2;
+ /** DASH (Dynamic Adaptive Streaming over HTTP) stream type. */
public static final int STREAM_TYPE_DASH = 3;
+ /** HLS (HTTP Live Streaming) stream type. */
public static final int STREAM_TYPE_HLS = 4;
+ /** SS (HTTP Smooth Streaming) stream type. */
public static final int STREAM_TYPE_SS = 5;
+ /** VOD (Video on Demand) playback type. */
public static final int PLAYBACK_TYPE_VOD = 0;
+ /** Live playback type. */
public static final int PLAYBACK_TYPE_LIVE = 1;
+ /** Other playback type. */
public static final int PLAYBACK_TYPE_OTHER = 2;
+ /** DRM is not used. */
public static final int DRM_TYPE_NONE = 0;
+ /** Other DRM type. */
public static final int DRM_TYPE_OTHER = 1;
+ /** Play ready DRM type. */
public static final int DRM_TYPE_PLAY_READY = 2;
+ /** Widevine L1 DRM type. */
public static final int DRM_TYPE_WIDEVINE_L1 = 3;
+ /** Widevine L3 DRM type. */
public static final int DRM_TYPE_WIDEVINE_L3 = 4;
- // TODO: add DRM_TYPE_CLEARKEY
+ /** Widevine L3 fallback DRM type. */
+ public static final int DRM_TYPE_WV_L3_FALLBACK = 5;
+ /** Clear key DRM type. */
+ public static final int DRM_TYPE_CLEARKEY = 6;
+ /** Main contents. */
public static final int CONTENT_TYPE_MAIN = 0;
+ /** Advertisement contents. */
public static final int CONTENT_TYPE_AD = 1;
+ /** Other contents. */
public static final int CONTENT_TYPE_OTHER = 2;
@@ -102,7 +125,9 @@ public final class PlaybackMetrics implements Parcelable {
DRM_TYPE_OTHER,
DRM_TYPE_PLAY_READY,
DRM_TYPE_WIDEVINE_L1,
- DRM_TYPE_WIDEVINE_L3
+ DRM_TYPE_WIDEVINE_L3,
+ DRM_TYPE_WV_L3_FALLBACK,
+ DRM_TYPE_CLEARKEY
})
@Retention(RetentionPolicy.SOURCE)
public @interface DrmType {}
@@ -173,6 +198,11 @@ public final class PlaybackMetrics implements Parcelable {
this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
+ /**
+ * Gets the media duration in milliseconds.
+ * @return the media duration in milliseconds, or -1 if unknown.
+ */
+ @IntRange(from = -1)
public long getMediaDurationMillis() {
return mMediaDurationMillis;
}
@@ -241,28 +271,36 @@ public final class PlaybackMetrics implements Parcelable {
/**
* Gets video frames played.
+ * @return the video frames played, or -1 if unknown.
*/
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getVideoFramesPlayed() {
return mVideoFramesPlayed;
}
/**
* Gets video frames dropped.
+ * @return the video frames dropped, or -1 if unknown.
*/
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getVideoFramesDropped() {
return mVideoFramesDropped;
}
/**
* Gets audio underrun count.
+ * @return the audio underrun count, or -1 if unknown.
*/
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getAudioUnderrunCount() {
return mAudioUnderrunCount;
}
/**
* Gets number of network bytes read.
+ * @return the number of network bytes read, or -1 if unknown.
*/
+ @IntRange(from = -1)
public long getNetworkBytesRead() {
return mNetworkBytesRead;
}
@@ -270,6 +308,7 @@ public final class PlaybackMetrics implements Parcelable {
/**
* Gets number of local bytes read.
*/
+ @IntRange(from = -1)
public long getLocalBytesRead() {
return mLocalBytesRead;
}
@@ -277,6 +316,7 @@ public final class PlaybackMetrics implements Parcelable {
/**
* Gets network transfer duration in milliseconds.
*/
+ @IntRange(from = -1)
public long getNetworkTransferDurationMillis() {
return mNetworkTransferDurationMillis;
}
@@ -415,34 +455,33 @@ public final class PlaybackMetrics implements Parcelable {
*/
public static final class Builder {
- private long mMediaDurationMillis;
- private int mStreamSource;
- private int mStreamType;
- private int mPlaybackType;
- private int mDrmType;
- private int mContentType;
+ private long mMediaDurationMillis = -1;
+ private int mStreamSource = STREAM_SOURCE_UNKNOWN;
+ private int mStreamType = STREAM_TYPE_UNKNOWN;
+ private int mPlaybackType = PLAYBACK_TYPE_OTHER;
+ private int mDrmType = DRM_TYPE_NONE;
+ private int mContentType = CONTENT_TYPE_OTHER;
private @Nullable String mPlayerName;
private @Nullable String mPlayerVersion;
private @NonNull List<Long> mExperimentIds = new ArrayList<>();
- private int mVideoFramesPlayed;
- private int mVideoFramesDropped;
- private int mAudioUnderrunCount;
- private long mNetworkBytesRead;
- private long mLocalBytesRead;
- private long mNetworkTransferDurationMillis;
+ private int mVideoFramesPlayed = -1;
+ private int mVideoFramesDropped = -1;
+ private int mAudioUnderrunCount = -1;
+ private long mNetworkBytesRead = -1;
+ private long mLocalBytesRead = -1;
+ private long mNetworkTransferDurationMillis = -1;
/**
* Creates a new Builder.
- *
- * @hide
*/
public Builder() {
}
/**
* Sets the media duration in milliseconds.
+ * @param value the media duration in milliseconds. -1 indicates the value is unknown.
*/
- public @NonNull Builder setMediaDurationMillis(long value) {
+ public @NonNull Builder setMediaDurationMillis(@IntRange(from = -1) long value) {
mMediaDurationMillis = value;
return this;
}
@@ -474,7 +513,7 @@ public final class PlaybackMetrics implements Parcelable {
/**
* Sets the DRM type.
*/
- public @NonNull Builder setDrmType(@StreamType int value) {
+ public @NonNull Builder setDrmType(@DrmType int value) {
mDrmType = value;
return this;
}
@@ -513,48 +552,58 @@ public final class PlaybackMetrics implements Parcelable {
/**
* Sets the video frames played.
+ * @param value the video frames played. -1 indicates the value is unknown.
*/
- public @NonNull Builder setVideoFramesPlayed(int value) {
+ public @NonNull Builder setVideoFramesPlayed(
+ @IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
mVideoFramesPlayed = value;
return this;
}
/**
* Sets the video frames dropped.
+ * @param value the video frames dropped. -1 indicates the value is unknown.
*/
- public @NonNull Builder setVideoFramesDropped(int value) {
+ public @NonNull Builder setVideoFramesDropped(
+ @IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
mVideoFramesDropped = value;
return this;
}
/**
* Sets the audio underrun count.
+ * @param value the audio underrun count. -1 indicates the value is unknown.
*/
- public @NonNull Builder setAudioUnderrunCount(int value) {
+ public @NonNull Builder setAudioUnderrunCount(
+ @IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
mAudioUnderrunCount = value;
return this;
}
/**
* Sets the number of network bytes read.
+ * @param value the number of network bytes read. -1 indicates the value is unknown.
*/
- public @NonNull Builder setNetworkBytesRead(long value) {
+ public @NonNull Builder setNetworkBytesRead(@IntRange(from = -1) long value) {
mNetworkBytesRead = value;
return this;
}
/**
* Sets the number of local bytes read.
+ * @param value the number of local bytes read. -1 indicates the value is unknown.
*/
- public @NonNull Builder setLocalBytesRead(long value) {
+ public @NonNull Builder setLocalBytesRead(@IntRange(from = -1) long value) {
mLocalBytesRead = value;
return this;
}
/**
* Sets the network transfer duration in milliseconds.
+ * @param value the network transfer duration in milliseconds.
+ * -1 indicates the value is unknown.
*/
- public @NonNull Builder setNetworkTransferDurationMillis(long value) {
+ public @NonNull Builder setNetworkTransferDurationMillis(@IntRange(from = -1) long value) {
mNetworkTransferDurationMillis = value;
return this;
}
diff --git a/media/java/android/media/metrics/PlaybackSession.java b/media/java/android/media/metrics/PlaybackSession.java
index 7f3450bcd12f..4ee8a45fe196 100644
--- a/media/java/android/media/metrics/PlaybackSession.java
+++ b/media/java/android/media/metrics/PlaybackSession.java
@@ -45,7 +45,6 @@ public final class PlaybackSession implements AutoCloseable {
/**
* Reports playback metrics.
- * @hide
*/
public void reportPlaybackMetrics(@NonNull PlaybackMetrics metrics) {
mManager.reportPlaybackMetrics(mId, metrics);
@@ -53,17 +52,15 @@ public final class PlaybackSession implements AutoCloseable {
/**
* Reports error event.
- * @hide
*/
- public void reportPlaybackErrorEvent(PlaybackErrorEvent event) {
+ public void reportPlaybackErrorEvent(@NonNull PlaybackErrorEvent event) {
mManager.reportPlaybackErrorEvent(mId, event);
}
/**
* Reports network event.
- * @hide
*/
- public void reportNetworkEvent(NetworkEvent event) {
+ public void reportNetworkEvent(@NonNull NetworkEvent event) {
mManager.reportNetworkEvent(mId, event);
}
@@ -76,9 +73,8 @@ public final class PlaybackSession implements AutoCloseable {
/**
* Reports track change event.
- * @hide
*/
- public void reportTrackChangeEvent(TrackChangeEvent event) {
+ public void reportTrackChangeEvent(@NonNull TrackChangeEvent event) {
mManager.reportTrackChangeEvent(mId, event);
}
diff --git a/media/java/android/media/metrics/TrackChangeEvent.java b/media/java/android/media/metrics/TrackChangeEvent.java
index fff0e36c062a..ef25357457c5 100644
--- a/media/java/android/media/metrics/TrackChangeEvent.java
+++ b/media/java/android/media/metrics/TrackChangeEvent.java
@@ -17,6 +17,7 @@
package android.media.metrics;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -28,20 +29,29 @@ import java.util.Objects;
/**
* Playback track change event.
- * @hide
*/
-public final class TrackChangeEvent implements Parcelable {
+public final class TrackChangeEvent extends Event implements Parcelable {
+ /** The track is off. */
public static final int TRACK_STATE_OFF = 0;
+ /** The track is on. */
public static final int TRACK_STATE_ON = 1;
+ /** Unknown track change reason. */
public static final int TRACK_CHANGE_REASON_UNKNOWN = 0;
+ /** Other track change reason. */
public static final int TRACK_CHANGE_REASON_OTHER = 1;
+ /** Track change reason for initial state. */
public static final int TRACK_CHANGE_REASON_INITIAL = 2;
+ /** Track change reason for manual changes. */
public static final int TRACK_CHANGE_REASON_MANUAL = 3;
+ /** Track change reason for adaptive changes. */
public static final int TRACK_CHANGE_REASON_ADAPTIVE = 4;
+ /** Audio track. */
public static final int TRACK_TYPE_AUDIO = 0;
+ /** Video track. */
public static final int TRACK_TYPE_VIDEO = 1;
+ /** Text track. */
public static final int TRACK_TYPE_TEXT = 2;
private final int mState;
@@ -50,7 +60,7 @@ public final class TrackChangeEvent implements Parcelable {
private final @Nullable String mSampleMimeType;
private final @Nullable String mCodecName;
private final int mBitrate;
- private final long mTimeSincePlaybackCreatedMillis;
+ private final long mTimeSinceCreatedMillis;
private final int mType;
private final @Nullable String mLanguage;
private final @Nullable String mLanguageRegion;
@@ -96,7 +106,7 @@ public final class TrackChangeEvent implements Parcelable {
@Nullable String sampleMimeType,
@Nullable String codecName,
int bitrate,
- long timeSincePlaybackCreatedMillis,
+ long timeSinceCreatedMillis,
int type,
@Nullable String language,
@Nullable String languageRegion,
@@ -110,7 +120,7 @@ public final class TrackChangeEvent implements Parcelable {
this.mSampleMimeType = sampleMimeType;
this.mCodecName = codecName;
this.mBitrate = bitrate;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
this.mType = type;
this.mLanguage = language;
this.mLanguageRegion = languageRegion;
@@ -120,34 +130,60 @@ public final class TrackChangeEvent implements Parcelable {
this.mHeight = height;
}
+ /**
+ * Gets track state.
+ */
@TrackState
public int getTrackState() {
return mState;
}
+ /**
+ * Gets track change reason.
+ */
@TrackChangeReason
public int getTrackChangeReason() {
return mReason;
}
+ /**
+ * Gets container MIME type.
+ */
public @Nullable String getContainerMimeType() {
return mContainerMimeType;
}
+ /**
+ * Gets the MIME type of the video/audio/text samples.
+ */
public @Nullable String getSampleMimeType() {
return mSampleMimeType;
}
+ /**
+ * Gets codec name.
+ */
public @Nullable String getCodecName() {
return mCodecName;
}
+ /**
+ * Gets bitrate.
+ * @return the bitrate, or -1 if unknown.
+ */
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getBitrate() {
return mBitrate;
}
- public long getTimeSincePlaybackCreatedMillis() {
- return mTimeSincePlaybackCreatedMillis;
+ /**
+ * Gets timestamp since the creation in milliseconds.
+ * @return the timestamp since the creation in milliseconds, or -1 if unknown.
+ */
+ @Override
+ @IntRange(from = -1)
+ public long getTimeSinceCreatedMillis() {
+ return mTimeSinceCreatedMillis;
}
@TrackType
@@ -155,26 +191,55 @@ public final class TrackChangeEvent implements Parcelable {
return mType;
}
+ /**
+ * Gets language code.
+ * @return a two-letter ISO 639-1 language code.
+ */
public @Nullable String getLanguage() {
return mLanguage;
}
+
+ /**
+ * Gets language region code.
+ * @return an IETF BCP 47 optional language region subtag based on a two-letter country code.
+ */
public @Nullable String getLanguageRegion() {
return mLanguageRegion;
}
+ /**
+ * Gets channel count.
+ * @return the channel count, or -1 if unknown.
+ */
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getChannelCount() {
return mChannelCount;
}
+ /**
+ * Gets sample rate.
+ * @return the sample rate, or -1 if unknown.
+ */
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getSampleRate() {
return mSampleRate;
}
+ /**
+ * Gets video width.
+ * @return the video width, or -1 if unknown.
+ */
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getWidth() {
return mWidth;
}
+ /**
+ * Gets video height.
+ * @return the video height, or -1 if unknown.
+ */
+ @IntRange(from = -1, to = Integer.MAX_VALUE)
public int getHeight() {
return mHeight;
}
@@ -194,7 +259,7 @@ public final class TrackChangeEvent implements Parcelable {
if (mSampleMimeType != null) dest.writeString(mSampleMimeType);
if (mCodecName != null) dest.writeString(mCodecName);
dest.writeInt(mBitrate);
- dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ dest.writeLong(mTimeSinceCreatedMillis);
dest.writeInt(mType);
if (mLanguage != null) dest.writeString(mLanguage);
if (mLanguageRegion != null) dest.writeString(mLanguageRegion);
@@ -218,7 +283,7 @@ public final class TrackChangeEvent implements Parcelable {
String sampleMimeType = (flg & 0x8) == 0 ? null : in.readString();
String codecName = (flg & 0x10) == 0 ? null : in.readString();
int bitrate = in.readInt();
- long timeSincePlaybackCreatedMillis = in.readLong();
+ long timeSinceCreatedMillis = in.readLong();
int type = in.readInt();
String language = (flg & 0x100) == 0 ? null : in.readString();
String languageRegion = (flg & 0x200) == 0 ? null : in.readString();
@@ -233,7 +298,7 @@ public final class TrackChangeEvent implements Parcelable {
this.mSampleMimeType = sampleMimeType;
this.mCodecName = codecName;
this.mBitrate = bitrate;
- this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ this.mTimeSinceCreatedMillis = timeSinceCreatedMillis;
this.mType = type;
this.mLanguage = language;
this.mLanguageRegion = languageRegion;
@@ -256,38 +321,24 @@ public final class TrackChangeEvent implements Parcelable {
}
};
-
-
- // Code below generated by codegen v1.0.22.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/media/java/android/media/metrics/TrackChangeEvent.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
@Override
public String toString() {
- return "TrackChangeEvent { " +
- "state = " + mState + ", " +
- "reason = " + mReason + ", " +
- "containerMimeType = " + mContainerMimeType + ", " +
- "sampleMimeType = " + mSampleMimeType + ", " +
- "codecName = " + mCodecName + ", " +
- "bitrate = " + mBitrate + ", " +
- "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis + ", " +
- "type = " + mType + ", " +
- "language = " + mLanguage + ", " +
- "languageRegion = " + mLanguageRegion + ", " +
- "channelCount = " + mChannelCount + ", " +
- "sampleRate = " + mSampleRate + ", " +
- "width = " + mWidth + ", " +
- "height = " + mHeight +
- " }";
+ return "TrackChangeEvent { "
+ + "state = " + mState + ", "
+ + "reason = " + mReason + ", "
+ + "containerMimeType = " + mContainerMimeType + ", "
+ + "sampleMimeType = " + mSampleMimeType + ", "
+ + "codecName = " + mCodecName + ", "
+ + "bitrate = " + mBitrate + ", "
+ + "timeSinceCreatedMillis = " + mTimeSinceCreatedMillis + ", "
+ + "type = " + mType + ", "
+ + "language = " + mLanguage + ", "
+ + "languageRegion = " + mLanguageRegion + ", "
+ + "channelCount = " + mChannelCount + ", "
+ + "sampleRate = " + mSampleRate + ", "
+ + "width = " + mWidth + ", "
+ + "height = " + mHeight
+ + " }";
}
@Override
@@ -301,7 +352,7 @@ public final class TrackChangeEvent implements Parcelable {
&& Objects.equals(mSampleMimeType, that.mSampleMimeType)
&& Objects.equals(mCodecName, that.mCodecName)
&& mBitrate == that.mBitrate
- && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis
+ && mTimeSinceCreatedMillis == that.mTimeSinceCreatedMillis
&& mType == that.mType
&& Objects.equals(mLanguage, that.mLanguage)
&& Objects.equals(mLanguageRegion, that.mLanguageRegion)
@@ -314,7 +365,7 @@ public final class TrackChangeEvent implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(mState, mReason, mContainerMimeType, mSampleMimeType, mCodecName,
- mBitrate, mTimeSincePlaybackCreatedMillis, mType, mLanguage, mLanguageRegion,
+ mBitrate, mTimeSinceCreatedMillis, mType, mLanguage, mLanguageRegion,
mChannelCount, mSampleRate, mWidth, mHeight);
}
@@ -323,32 +374,33 @@ public final class TrackChangeEvent implements Parcelable {
*/
public static final class Builder {
// TODO: check track type for the setters.
- private int mState;
- private int mReason;
+ private int mState = TRACK_STATE_OFF;
+ private int mReason = TRACK_CHANGE_REASON_UNKNOWN;
private @Nullable String mContainerMimeType;
private @Nullable String mSampleMimeType;
private @Nullable String mCodecName;
- private int mBitrate;
- private long mTimeSincePlaybackCreatedMillis;
- private int mType;
+ private int mBitrate = -1;
+ private long mTimeSinceCreatedMillis = -1;
+ private final int mType;
private @Nullable String mLanguage;
private @Nullable String mLanguageRegion;
- private int mChannelCount;
- private int mSampleRate;
- private int mWidth;
- private int mHeight;
+ private int mChannelCount = -1;
+ private int mSampleRate = -1;
+ private int mWidth = -1;
+ private int mHeight = -1;
private long mBuilderFieldsSet = 0L;
/**
* Creates a new Builder.
- *
- * @hide
*/
public Builder(int type) {
mType = type;
}
+ /**
+ * Sets track state.
+ */
public @NonNull Builder setTrackState(@TrackState int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1;
@@ -356,6 +408,9 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
+ /**
+ * Sets track change reason.
+ */
public @NonNull Builder setTrackChangeReason(@TrackChangeReason int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
@@ -363,6 +418,9 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
+ /**
+ * Sets container MIME type.
+ */
public @NonNull Builder setContainerMimeType(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
@@ -370,6 +428,9 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
+ /**
+ * Sets the MIME type of the video/audio/text samples.
+ */
public @NonNull Builder setSampleMimeType(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x8;
@@ -377,6 +438,9 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
+ /**
+ * Sets codec name.
+ */
public @NonNull Builder setCodecName(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x10;
@@ -384,27 +448,33 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
- public @NonNull Builder setBitrate(int value) {
+ /**
+ * Sets bitrate in bits per second.
+ * @param value the bitrate in bits per second. -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setBitrate(@IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x20;
mBitrate = value;
return this;
}
- public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
+ /**
+ * Sets timestamp since the creation in milliseconds.
+ * @param value the timestamp since the creation in milliseconds.
+ * -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setTimeSinceCreatedMillis(@IntRange(from = -1) long value) {
checkNotUsed();
mBuilderFieldsSet |= 0x40;
- mTimeSincePlaybackCreatedMillis = value;
- return this;
- }
-
- public @NonNull Builder setTrackType(@TrackType int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x80;
- mType = value;
+ mTimeSinceCreatedMillis = value;
return this;
}
+ /**
+ * Sets language code.
+ * @param value a two-letter ISO 639-1 language code.
+ */
public @NonNull Builder setLanguage(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x100;
@@ -412,6 +482,11 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
+ /**
+ * Sets language region code.
+ * @param value an IETF BCP 47 optional language region subtag based on a two-letter country
+ * code.
+ */
public @NonNull Builder setLanguageRegion(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x200;
@@ -419,28 +494,46 @@ public final class TrackChangeEvent implements Parcelable {
return this;
}
- public @NonNull Builder setChannelCount(int value) {
+ /**
+ * Sets channel count.
+ * @param value the channel count. -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setChannelCount(
+ @IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x400;
mChannelCount = value;
return this;
}
- public @NonNull Builder setSampleRate(int value) {
+ /**
+ * Sets sample rate.
+ * @param value the sample rate. -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setSampleRate(
+ @IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x800;
mSampleRate = value;
return this;
}
- public @NonNull Builder setWidth(int value) {
+ /**
+ * Sets video width.
+ * @param value the video width. -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setWidth(@IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1000;
mWidth = value;
return this;
}
- public @NonNull Builder setHeight(int value) {
+ /**
+ * Sets video height.
+ * @param value the video height. -1 indicates the value is unknown.
+ */
+ public @NonNull Builder setHeight(@IntRange(from = -1, to = Integer.MAX_VALUE) int value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2000;
mHeight = value;
@@ -459,7 +552,7 @@ public final class TrackChangeEvent implements Parcelable {
mSampleMimeType,
mCodecName,
mBitrate,
- mTimeSincePlaybackCreatedMillis,
+ mTimeSinceCreatedMillis,
mType,
mLanguage,
mLanguageRegion,
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 66d579408db0..dc476b873786 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -73,8 +73,10 @@ interface ISessionManager {
void setOnMediaKeyListener(in IOnMediaKeyListener listener);
boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
- void setCustomMediaKeyDispatcherForTesting(String name);
- void setCustomSessionPolicyProviderForTesting(String name);
+ void setCustomMediaKeyDispatcher(String name);
+ void setCustomMediaSessionPolicyProvider(String name);
+ boolean hasCustomMediaKeyDispatcher(String componentName);
+ boolean hasCustomMediaSessionPolicyProvider(String componentName);
int getSessionPolicies(in MediaSession.Token token);
void setSessionPolicies(in MediaSession.Token token, int policies);
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 13a3436569aa..8de5e42e93b2 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -958,9 +958,9 @@ public final class MediaSessionManager {
* @hide
*/
@VisibleForTesting
- public void setCustomMediaKeyDispatcherForTesting(@Nullable String name) {
+ public void setCustomMediaKeyDispatcher(@Nullable String name) {
try {
- mService.setCustomMediaKeyDispatcherForTesting(name);
+ mService.setCustomMediaKeyDispatcher(name);
} catch (RemoteException e) {
Log.e(TAG, "Failed to set custom media key dispatcher name", e);
}
@@ -968,22 +968,58 @@ public final class MediaSessionManager {
/**
* Set the component name for the custom
- * {@link com.android.server.media.SessionPolicyProvider} class. Set to null to restore to the
- * custom {@link com.android.server.media.SessionPolicyProvider} class name retrieved from the
- * config value.
+ * {@link com.android.server.media.MediaSessionPolicyProvider} class. Set to null to restore to
+ * the custom {@link com.android.server.media.MediaSessionPolicyProvider} class name retrieved
+ * from the config value.
*
* @hide
*/
@VisibleForTesting
- public void setCustomSessionPolicyProviderForTesting(@Nullable String name) {
+ public void setCustomMediaSessionPolicyProvider(@Nullable String name) {
try {
- mService.setCustomSessionPolicyProviderForTesting(name);
+ mService.setCustomMediaSessionPolicyProvider(name);
} catch (RemoteException e) {
Log.e(TAG, "Failed to set custom session policy provider name", e);
}
}
/**
+ * Get the component name for the custom {@link com.android.server.media.MediaKeyDispatcher}
+ * class.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean hasCustomMediaKeyDispatcher(@NonNull String componentName) {
+ Objects.requireNonNull(componentName, "componentName shouldn't be null");
+ try {
+ return mService.hasCustomMediaKeyDispatcher(componentName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to check if custom media key dispatcher with given component"
+ + " name exists", e);
+ }
+ return false;
+ }
+
+ /**
+ * Get the component name for the custom
+ * {@link com.android.server.media.MediaSessionPolicyProvider} class.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean hasCustomMediaSessionPolicyProvider(@NonNull String componentName) {
+ Objects.requireNonNull(componentName, "componentName shouldn't be null");
+ try {
+ return mService.hasCustomMediaSessionPolicyProvider(componentName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to check if custom media session policy provider with given"
+ + " component name exists", e);
+ }
+ return false;
+ }
+
+ /**
* Get session policies of the specified {@link MediaSession.Token}.
*
* @hide
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 740bc2dbeb43..c0185dcc4539 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2525,7 +2525,9 @@ public final class TvInputManager {
/**
* Pauses TV program recording in the current recording session.
*
- * @param params A set of extra parameters which might be handled with this event.
+ * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+ * name, i.e. prefixed with a package name you own, so that different developers
+ * will not create conflicting keys.
* {@link TvRecordingClient#pauseRecording(Bundle)}.
*/
void pauseRecording(@NonNull Bundle params) {
@@ -2543,7 +2545,9 @@ public final class TvInputManager {
/**
* Resumes TV program recording in the current recording session.
*
- * @param params A set of extra parameters which might be handled with this event.
+ * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+ * name, i.e. prefixed with a package name you own, so that different developers
+ * will not create conflicting keys.
* {@link TvRecordingClient#resumeRecording(Bundle)}.
*/
void resumeRecording(@NonNull Bundle params) {
diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp
index c38d9194df44..c904ca2be00c 100644
--- a/media/java/android/media/tv/tunerresourcemanager/Android.bp
+++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "framework-media-tv-tunerresourcemanager-sources-aidl",
srcs: [
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 4972529eb705..ce4550492740 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_base_media_jni_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_base_media_jni_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_shared {
name: "libmedia_jni",
@@ -64,6 +81,7 @@ cc_library_shared {
"android.hardware.cas@1.0",
"android.hardware.cas.native@1.0",
"android.hardware.drm@1.3",
+ "android.hardware.drm@1.4",
"android.hidl.memory@1.0",
"android.hidl.token@1.0-utils",
],
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 0e8719eeb79c..73e1f7df89a1 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -37,6 +37,7 @@
#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrmMetricsConsumer.h>
#include <mediadrm/IDrm.h>
+#include <utils/Vector.h>
using ::android::os::PersistableBundle;
namespace drm = ::android::hardware::drm;
@@ -187,6 +188,11 @@ struct KeyStatusFields {
jclass classId;
};
+struct LogMessageFields {
+ jmethodID init;
+ jclass classId;
+};
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -208,6 +214,7 @@ struct fields_t {
jmethodID createFromParcelId;
jclass parcelCreatorClassId;
KeyStatusFields keyStatus;
+ LogMessageFields logMessage;
};
static fields_t gFields;
@@ -224,6 +231,19 @@ jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
return result;
}
+jobject hidlLogMessagesToJavaList(JNIEnv *env, const Vector<drm::V1_4::LogMessage> &logs) {
+ jclass clazz = gFields.arraylistClassId;
+ jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
+ clazz = gFields.logMessage.classId;
+ for (auto log: logs) {
+ jobject jLog = env->NewObject(clazz, gFields.logMessage.init,
+ static_cast<jlong>(log.timeMs),
+ static_cast<jint>(log.priority),
+ env->NewStringUTF(log.message.c_str()));
+ env->CallBooleanMethod(arrayList, gFields.arraylist.add, jLog);
+ }
+ return arrayList;
+}
} // namespace anonymous
// ----------------------------------------------------------------------------
@@ -323,11 +343,56 @@ void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
}
}
+jint MediaErrorToJavaError(status_t err) {
+#define STATUS_CASE(status) \
+ case status: \
+ return J##status
+
+ switch (err) {
+ STATUS_CASE(ERROR_DRM_UNKNOWN);
+ STATUS_CASE(ERROR_DRM_NO_LICENSE);
+ STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
+ STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
+ STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+ STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
+ STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
+ STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
+ STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
+ STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
+ STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
+ STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
+ STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
+ STATUS_CASE(ERROR_DRM_GENERIC_OEM);
+ STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
+ STATUS_CASE(ERROR_DRM_INIT_DATA);
+ STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
+ STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
+ STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
+ STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
+ STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
+ STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
+ STATUS_CASE(ERROR_DRM_LICENSE_STATE);
+ STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
+ STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
+ STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
+ STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
+ STATUS_CASE(ERROR_DRM_STORAGE_READ);
+ STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
+ STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+#undef STATUS_CASE
+ }
+ return static_cast<jint>(err);
+}
+
static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
ALOGE("Illegal state exception: %s (%d)", msg, err);
+ jint jerr = MediaErrorToJavaError(err);
jobject exception = env->NewObject(gFields.stateException.classId,
- gFields.stateException.init, static_cast<int>(err),
+ gFields.stateException.init, static_cast<int>(jerr),
env->NewStringUTF(msg));
env->Throw(static_cast<jthrowable>(exception));
}
@@ -357,43 +422,11 @@ static bool isSessionException(status_t err) {
}
static bool throwExceptionAsNecessary(
- JNIEnv *env, status_t err, const char *msg = NULL) {
-
- const char *drmMessage = NULL;
-
- switch (err) {
- case ERROR_DRM_UNKNOWN:
- drmMessage = "General DRM error";
- break;
- case ERROR_DRM_NO_LICENSE:
- drmMessage = "No license";
- break;
- case ERROR_DRM_LICENSE_EXPIRED:
- drmMessage = "License expired";
- break;
- case ERROR_DRM_SESSION_NOT_OPENED:
- drmMessage = "Session not opened";
- break;
- case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
- drmMessage = "Not initialized";
- break;
- case ERROR_DRM_DECRYPT:
- drmMessage = "Decrypt error";
- break;
- case ERROR_DRM_CANNOT_HANDLE:
- drmMessage = "Invalid parameter or data format";
- break;
- case ERROR_DRM_INVALID_STATE:
- drmMessage = "Invalid state";
- break;
- default:
- break;
- }
-
- String8 vendorMessage;
- if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
- vendorMessage = String8::format("DRM vendor-defined error: %d", err);
- drmMessage = vendorMessage.string();
+ JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
+ std::string msgStr;
+ if (drm != NULL) {
+ msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
+ msg = msgStr.c_str();
}
if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
@@ -419,15 +452,6 @@ static bool throwExceptionAsNecessary(
throwSessionException(env, msg, err);
return true;
} else if (err != OK) {
- String8 errbuf;
- if (drmMessage != NULL) {
- if (msg == NULL) {
- msg = drmMessage;
- } else {
- errbuf = String8::format("%s: %s", msg, drmMessage);
- msg = errbuf.string();
- }
- }
throwStateException(env, msg, err);
return true;
}
@@ -907,6 +931,10 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
+
+ FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage");
+ gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+ GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V");
}
static void android_media_MediaDrm_native_setup(
@@ -1021,7 +1049,7 @@ static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
securityLevel, &isSupported);
- if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
+ if (throwExceptionAsNecessary(env, NULL, err, "Failed to query crypto scheme support")) {
return false;
}
return isSupported;
@@ -1044,7 +1072,7 @@ static jbyteArray android_media_MediaDrm_openSession(
status_t err = drm->openSession(level, sessionId);
- if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
return NULL;
}
@@ -1063,7 +1091,7 @@ static void android_media_MediaDrm_closeSession(
status_t err = drm->closeSession(sessionId);
- throwExceptionAsNecessary(env, err, "Failed to close session");
+ throwExceptionAsNecessary(env, drm, err, "Failed to close session");
}
static jobject android_media_MediaDrm_getKeyRequest(
@@ -1116,7 +1144,7 @@ static jobject android_media_MediaDrm_getKeyRequest(
status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
keyType, optParams, request, defaultUrl, &keyRequestType);
- if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get key request")) {
return NULL;
}
@@ -1186,7 +1214,7 @@ static jbyteArray android_media_MediaDrm_provideKeyResponse(
status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
- if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to handle key response")) {
return NULL;
}
return VectorToJByteArray(env, keySetId);
@@ -1210,7 +1238,7 @@ static void android_media_MediaDrm_removeKeys(
status_t err = drm->removeKeys(keySetId);
- throwExceptionAsNecessary(env, err, "Failed to remove keys");
+ throwExceptionAsNecessary(env, drm, err, "Failed to remove keys");
}
static void android_media_MediaDrm_restoreKeys(
@@ -1233,7 +1261,7 @@ static void android_media_MediaDrm_restoreKeys(
status_t err = drm->restoreKeys(sessionId, keySetId);
- throwExceptionAsNecessary(env, err, "Failed to restore keys");
+ throwExceptionAsNecessary(env, drm, err, "Failed to restore keys");
}
static jobject android_media_MediaDrm_queryKeyStatus(
@@ -1249,7 +1277,7 @@ static jobject android_media_MediaDrm_queryKeyStatus(
status_t err = drm->queryKeyStatus(sessionId, infoMap);
- if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to query key status")) {
return NULL;
}
@@ -1279,7 +1307,7 @@ static jobject android_media_MediaDrm_getProvisionRequestNative(
String8 certAuthority = JStringToString8(env, jcertAuthority);
status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
- if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get provision request")) {
return NULL;
}
@@ -1334,7 +1362,7 @@ static jobject android_media_MediaDrm_provideProvisionResponseNative(
env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
}
- throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+ throwExceptionAsNecessary(env, drm, err, "Failed to handle provision response");
return certificateObj;
}
@@ -1350,7 +1378,7 @@ static jobject android_media_MediaDrm_getSecureStops(
status_t err = drm->getSecureStops(secureStops);
- if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stops")) {
return NULL;
}
@@ -1369,7 +1397,7 @@ static jobject android_media_MediaDrm_getSecureStopIds(
status_t err = drm->getSecureStopIds(secureStopIds);
- if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop Ids")) {
return NULL;
}
@@ -1388,7 +1416,7 @@ static jbyteArray android_media_MediaDrm_getSecureStop(
status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
- if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get secure stop")) {
return NULL;
}
@@ -1407,7 +1435,7 @@ static void android_media_MediaDrm_releaseSecureStops(
status_t err = drm->releaseSecureStops(ssRelease);
- throwExceptionAsNecessary(env, err, "Failed to release secure stops");
+ throwExceptionAsNecessary(env, drm, err, "Failed to release secure stops");
}
static void android_media_MediaDrm_removeSecureStop(
@@ -1420,7 +1448,7 @@ static void android_media_MediaDrm_removeSecureStop(
status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
- throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
+ throwExceptionAsNecessary(env, drm, err, "Failed to remove secure stop");
}
static void android_media_MediaDrm_removeAllSecureStops(
@@ -1433,7 +1461,7 @@ static void android_media_MediaDrm_removeAllSecureStops(
status_t err = drm->removeAllSecureStops();
- throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
+ throwExceptionAsNecessary(env, drm, err, "Failed to remove all secure stops");
}
@@ -1472,7 +1500,7 @@ static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
status_t err = drm->getHdcpLevels(&connected, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
return gHdcpLevels.kHdcpLevelUnknown;
}
return HdcpLevelTojint(connected);
@@ -1491,7 +1519,7 @@ static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
status_t err = drm->getHdcpLevels(&connected, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get HDCP levels")) {
return gHdcpLevels.kHdcpLevelUnknown;
}
return HdcpLevelTojint(max);
@@ -1508,7 +1536,7 @@ static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
uint32_t open = 0, max = 0;
status_t err = drm->getNumberOfSessions(&open, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
return 0;
}
return open;
@@ -1525,7 +1553,7 @@ static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
uint32_t open = 0, max = 0;
status_t err = drm->getNumberOfSessions(&open, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get number of sessions")) {
return 0;
}
return max;
@@ -1545,7 +1573,7 @@ static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
status_t err = drm->getSecurityLevel(sessionId, &level);
- if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get security level")) {
return gSecurityLevels.kSecurityLevelUnknown;
}
@@ -1577,7 +1605,7 @@ static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
- if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline key set Ids")) {
return NULL;
}
@@ -1594,7 +1622,7 @@ static void android_media_MediaDrm_removeOfflineLicense(
status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
- throwExceptionAsNecessary(env, err, "Failed to remove offline license");
+ throwExceptionAsNecessary(env, drm, err, "Failed to remove offline license");
}
static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
@@ -1611,7 +1639,7 @@ static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
status_t err = drm->getOfflineLicenseState(keySetId, &state);
- if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get offline license state")) {
return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
}
@@ -1644,7 +1672,7 @@ static jstring android_media_MediaDrm_getPropertyString(
status_t err = drm->getPropertyString(name, value);
- if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
return NULL;
}
@@ -1670,7 +1698,7 @@ static jbyteArray android_media_MediaDrm_getPropertyByteArray(
status_t err = drm->getPropertyByteArray(name, value);
- if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get property")) {
return NULL;
}
@@ -1702,7 +1730,7 @@ static void android_media_MediaDrm_setPropertyString(
status_t err = drm->setPropertyString(name, value);
- throwExceptionAsNecessary(env, err, "Failed to set property");
+ throwExceptionAsNecessary(env, drm, err, "Failed to set property");
}
static void android_media_MediaDrm_setPropertyByteArray(
@@ -1730,7 +1758,7 @@ static void android_media_MediaDrm_setPropertyByteArray(
status_t err = drm->setPropertyByteArray(name, value);
- throwExceptionAsNecessary(env, err, "Failed to set property");
+ throwExceptionAsNecessary(env, drm, err, "Failed to set property");
}
static void android_media_MediaDrm_setCipherAlgorithmNative(
@@ -1754,7 +1782,7 @@ static void android_media_MediaDrm_setCipherAlgorithmNative(
status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
- throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
+ throwExceptionAsNecessary(env, drm, err, "Failed to set cipher algorithm");
}
static void android_media_MediaDrm_setMacAlgorithmNative(
@@ -1778,7 +1806,7 @@ static void android_media_MediaDrm_setMacAlgorithmNative(
status_t err = drm->setMacAlgorithm(sessionId, algorithm);
- throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
+ throwExceptionAsNecessary(env, drm, err, "Failed to set mac algorithm");
}
@@ -1806,7 +1834,7 @@ static jbyteArray android_media_MediaDrm_encryptNative(
status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
- if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to encrypt")) {
return NULL;
}
@@ -1836,7 +1864,7 @@ static jbyteArray android_media_MediaDrm_decryptNative(
Vector<uint8_t> output;
status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
- if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to decrypt")) {
return NULL;
}
@@ -1866,7 +1894,7 @@ static jbyteArray android_media_MediaDrm_signNative(
status_t err = drm->sign(sessionId, keyId, message, signature);
- if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
return NULL;
}
@@ -1897,7 +1925,7 @@ static jboolean android_media_MediaDrm_verifyNative(
status_t err = drm->verify(sessionId, keyId, message, signature, match);
- throwExceptionAsNecessary(env, err, "Failed to verify");
+ throwExceptionAsNecessary(env, drm, err, "Failed to verify");
return match;
}
@@ -1946,7 +1974,7 @@ static jbyteArray android_media_MediaDrm_signRSANative(
status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
- if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to sign")) {
return NULL;
}
@@ -1993,7 +2021,23 @@ static void android_media_MediaDrm_setPlaybackId(
playbackId = JStringToString8(env, jplaybackId);
}
status_t err = drm->setPlaybackId(sessionId, playbackId.c_str());
- throwExceptionAsNecessary(env, err, "Failed to set playbackId");
+ throwExceptionAsNecessary(env, drm, err, "Failed to set playbackId");
+}
+
+static jobject android_media_MediaDrm_getLogMessages(
+ JNIEnv *env, jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+ if (!CheckDrm(env, drm)) {
+ return NULL;
+ }
+
+ Vector<drm::V1_4::LogMessage> logs;
+ status_t err = drm->getLogMessages(logs);
+ ALOGI("drm->getLogMessages %zu logs", logs.size());
+ if (throwExceptionAsNecessary(env, drm, err, "Failed to get log messages")) {
+ return NULL;
+ }
+ return hidlLogMessagesToJavaList(env, logs);
}
static const JNINativeMethod gMethods[] = {
@@ -2016,7 +2060,7 @@ static const JNINativeMethod gMethods[] = {
{ "closeSessionNative", "([B)V",
(void *)android_media_MediaDrm_closeSession },
- { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
+ { "getKeyRequestNative", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
"Landroid/media/MediaDrm$KeyRequest;",
(void *)android_media_MediaDrm_getKeyRequest },
@@ -2123,6 +2167,9 @@ static const JNINativeMethod gMethods[] = {
{ "setPlaybackId", "([BLjava/lang/String;)V",
(void *)android_media_MediaDrm_setPlaybackId },
+
+ { "getLogMessages", "()Ljava/util/List;",
+ (void *)android_media_MediaDrm_getLogMessages },
};
int register_android_media_Drm(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index b1f544cb2dbe..dc0793af2d17 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -28,6 +28,44 @@
namespace {
+enum {
+ // TODO(b/180483929): use reverse jni e.g. android_media_MediaDrm_native_init
+ // KEEP IN SYNC with MediaDrm$ErrorCodes in MediaDrm.java!
+ JERROR_DRM_UNKNOWN = 0,
+ JERROR_DRM_NO_LICENSE = 1,
+ JERROR_DRM_LICENSE_EXPIRED = 2,
+ JERROR_DRM_RESOURCE_BUSY = 3,
+ JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+ JERROR_DRM_SESSION_NOT_OPENED = 5,
+ JERROR_DRM_CANNOT_HANDLE = 6,
+ JERROR_DRM_INSUFFICIENT_SECURITY = 7,
+ JERROR_DRM_FRAME_TOO_LARGE = 8,
+ JERROR_DRM_SESSION_LOST_STATE = 9,
+ JERROR_DRM_CERTIFICATE_MALFORMED = 10,
+ JERROR_DRM_CERTIFICATE_MISSING = 11,
+ JERROR_DRM_CRYPTO_LIBRARY = 12,
+ JERROR_DRM_GENERIC_OEM = 13,
+ JERROR_DRM_GENERIC_PLUGIN = 14,
+ JERROR_DRM_INIT_DATA = 15,
+ JERROR_DRM_KEY_NOT_LOADED = 16,
+ JERROR_DRM_LICENSE_PARSE = 17,
+ JERROR_DRM_LICENSE_POLICY = 18,
+ JERROR_DRM_LICENSE_RELEASE = 19,
+ JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
+ JERROR_DRM_LICENSE_RESTORE = 21,
+ JERROR_DRM_LICENSE_STATE = 22,
+ JERROR_DRM_MEDIA_FRAMEWORK = 23,
+ JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
+ JERROR_DRM_PROVISIONING_CONFIG = 25,
+ JERROR_DRM_PROVISIONING_PARSE = 26,
+ JERROR_DRM_PROVISIONING_RETRY = 27,
+ JERROR_DRM_RESOURCE_CONTENTION = 28,
+ JERROR_DRM_SECURE_STOP_RELEASE = 29,
+ JERROR_DRM_STORAGE_READ = 30,
+ JERROR_DRM_STORAGE_WRITE = 31,
+ JERROR_DRM_ZERO_SUBSAMPLES = 32,
+};
+
struct ListenerArgs {
jbyteArray jSessionId;
jbyteArray jData;
@@ -98,6 +136,8 @@ private:
DISALLOW_EVIL_CONSTRUCTORS(JDrm);
};
+jint MediaErrorToJavaError(status_t err);
+
} // namespace android
#endif // _ANDROID_MEDIA_DRM_H_
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index 40e4c54c2921..c2fc91d5cfea 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_media_jni_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_media_jni_license"],
+}
+
cc_library_shared {
name: "libaudioeffect_jni",
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 6141308a8fdb..7b498e027d1c 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -1,3 +1,22 @@
+package {
+ default_applicable_licenses: [
+ "frameworks_base_media_jni_soundpool_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_base_media_jni_soundpool_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
tidy_errors = [
// https://clang.llvm.org/extra/clang-tidy/checks/list.html
// For many categories, the checks are too many to specify individually.
diff --git a/media/jni/soundpool/tests/Android.bp b/media/jni/soundpool/tests/Android.bp
index 52f59ed69503..7d31c106f9c4 100644
--- a/media/jni/soundpool/tests/Android.bp
+++ b/media/jni/soundpool/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_media_jni_soundpool_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_base_media_jni_soundpool_license",
+ ],
+}
+
cc_binary {
name: "soundpool_stress",
host_supported: false,
diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp
index 5f4b930f350e..bfb0cb854be3 100644
--- a/media/lib/remotedisplay/Android.bp
+++ b/media/lib/remotedisplay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_sdk_library {
name: "com.android.media.remotedisplay",
srcs: ["java/**/*.java"],
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 3b2578754087..6504176eb6f1 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_sdk_library {
name: "com.android.mediadrm.signer",
srcs: ["java/**/*.java"],
diff --git a/media/lib/tvremote/Android.bp b/media/lib/tvremote/Android.bp
index c5d14191c6c8..a58f677c3c30 100644
--- a/media/lib/tvremote/Android.bp
+++ b/media/lib/tvremote/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_sdk_library {
name: "com.android.media.tv.remoteprovider",
srcs: ["java/**/*.java"],
diff --git a/media/lib/tvremote/tests/Android.bp b/media/lib/tvremote/tests/Android.bp
index f00eed070798..f02cfc393c81 100644
--- a/media/lib/tvremote/tests/Android.bp
+++ b/media/lib/tvremote/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "TvRemoteTests",
srcs: ["src/**/*.java"],
diff --git a/media/mca/filterfw/Android.bp b/media/mca/filterfw/Android.bp
index 0e0ecf331afc..ef3583f1a77f 100644
--- a/media/mca/filterfw/Android.bp
+++ b/media/mca/filterfw/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_shared {
name: "libfilterfw",
diff --git a/media/mca/filterfw/native/Android.bp b/media/mca/filterfw/native/Android.bp
index 7a8a6a18664e..7e4a34e8d934 100644
--- a/media/mca/filterfw/native/Android.bp
+++ b/media/mca/filterfw/native/Android.bp
@@ -16,6 +16,15 @@
//####################
// Build module libfilterfw_static
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_static {
name: "libfilterfw_native",
diff --git a/media/mca/filterpacks/Android.bp b/media/mca/filterpacks/Android.bp
index 34fb27dd1663..b50df6eb572c 100644
--- a/media/mca/filterpacks/Android.bp
+++ b/media/mca/filterpacks/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_static {
name: "libfilterpack_base",
srcs: [
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.bp b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
index 96e81ab9b9cc..541660c1e4a2 100644
--- a/media/mca/samples/CameraEffectsRecordingSample/Android.bp
+++ b/media/mca/samples/CameraEffectsRecordingSample/Android.bp
@@ -15,6 +15,15 @@
// Build activity
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "CameraEffectsRecordingSample",
srcs: ["**/*.java"],
@@ -23,4 +32,3 @@ android_test {
enabled: false,
},
}
-
diff --git a/media/mca/tests/Android.bp b/media/mca/tests/Android.bp
index 6b11dd9db7ba..f02b4c0a4bfb 100644
--- a/media/mca/tests/Android.bp
+++ b/media/mca/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "CameraEffectsTests",
libs: [
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index 2da45b6a78be..7acb8c744ba7 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_shared {
name: "libamidi",
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
index 25c34c3631dc..94a7a17638a5 100644
--- a/media/packages/BluetoothMidiService/Android.bp
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "BluetoothMidiLib",
srcs: [
diff --git a/media/packages/BluetoothMidiService/tests/unit/Android.bp b/media/packages/BluetoothMidiService/tests/unit/Android.bp
index fa4612bc22e7..67c7e4230f30 100644
--- a/media/packages/BluetoothMidiService/tests/unit/Android.bp
+++ b/media/packages/BluetoothMidiService/tests/unit/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "BluetoothMidiTests",
srcs: ["src/**/*.java"],
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index ed3383752695..95d1c6ccb67c 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "audiopolicytest",
srcs: ["**/*.java"],
diff --git a/media/tests/CameraBrowser/Android.bp b/media/tests/CameraBrowser/Android.bp
index 8e3ca1943b17..1408640a6b0d 100644
--- a/media/tests/CameraBrowser/Android.bp
+++ b/media/tests/CameraBrowser/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "CameraBrowser",
srcs: ["**/*.java"],
diff --git a/media/tests/EffectsTest/Android.bp b/media/tests/EffectsTest/Android.bp
index 214e8c02f742..644e453b8956 100644
--- a/media/tests/EffectsTest/Android.bp
+++ b/media/tests/EffectsTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "EffectsTest",
srcs: ["**/*.java"],
diff --git a/media/tests/MediaDump/Android.bp b/media/tests/MediaDump/Android.bp
index 0eba8b24f6cd..f54b97a06558 100644
--- a/media/tests/MediaDump/Android.bp
+++ b/media/tests/MediaDump/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_app {
name: "MediaDump",
// Only compile source java files in this apk.
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index 3f1954a0874a..48d56d898138 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "mediaframeworktest",
srcs: ["**/*.java"],
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index a439b79fa2f0..d41bc02906ab 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "mediaroutertest",
@@ -17,4 +26,4 @@ android_test {
platform_apis: true,
certificate: "platform",
-} \ No newline at end of file
+}
diff --git a/media/tests/MtpTests/Android.bp b/media/tests/MtpTests/Android.bp
index 7d2c7c693fa5..3016873e1de8 100644
--- a/media/tests/MtpTests/Android.bp
+++ b/media/tests/MtpTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "MtpTests",
srcs: ["**/*.java"],
diff --git a/media/tests/ScoAudioTest/Android.bp b/media/tests/ScoAudioTest/Android.bp
index ad2b91716145..f8a893bf7f2c 100644
--- a/media/tests/ScoAudioTest/Android.bp
+++ b/media/tests/ScoAudioTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "scoaudiotest",
platform_apis: true,
diff --git a/media/tests/SoundPoolTest/Android.bp b/media/tests/SoundPoolTest/Android.bp
index 473f531f675b..0a50106d52c8 100644
--- a/media/tests/SoundPoolTest/Android.bp
+++ b/media/tests/SoundPoolTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "SoundPoolTest",
srcs: ["**/*.java"],
diff --git a/media/tests/TunerTest/Android.bp b/media/tests/TunerTest/Android.bp
index 5c3e9ab9812f..8e8816cee876 100644
--- a/media/tests/TunerTest/Android.bp
+++ b/media/tests/TunerTest/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "mediatunertest",
diff --git a/media/tests/audiotests/Android.bp b/media/tests/audiotests/Android.bp
index 5db0ab0cde6d..c52c0336979c 100644
--- a/media/tests/audiotests/Android.bp
+++ b/media/tests/audiotests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_test {
name: "shared_mem_test",
gtest: false,
diff --git a/media/tests/players/Android.bp b/media/tests/players/Android.bp
index 23c5f04c93a6..3b6df707badb 100644
--- a/media/tests/players/Android.bp
+++ b/media/tests/players/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_test_library {
name: "invoke_mock_media_player",
srcs: ["invoke_mock_media_player.cpp"],