summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt44
-rw-r--r--api/test-lint-baseline.txt400
-rw-r--r--media/Android.bp5
-rw-r--r--media/apex/java/android/media/MediaParser.java743
4 files changed, 878 insertions, 314 deletions
diff --git a/api/current.txt b/api/current.txt
index b4be9e19da10..34b1235fc32f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25591,6 +25591,50 @@ package android.media {
field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
}
+ public final class MediaParser {
+ method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException, java.lang.InterruptedException;
+ method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
+ method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
+ method @Nullable public String getExtractorName();
+ method @NonNull public static java.util.List<java.lang.String> getExtractorNames(@NonNull android.media.MediaFormat);
+ method public void release();
+ method public void seek(@NonNull android.media.MediaParser.SeekPoint);
+ }
+
+ public static interface MediaParser.InputReader {
+ method public long getLength();
+ method public long getPosition();
+ method public int read(@NonNull byte[], int, int) throws java.io.IOException, java.lang.InterruptedException;
+ }
+
+ public static interface MediaParser.OutputConsumer {
+ method public void onFormat(int, @NonNull android.media.MediaFormat);
+ method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
+ method public void onSampleData(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException, java.lang.InterruptedException;
+ method public void onSeekMap(@NonNull android.media.MediaParser.SeekMap);
+ method public void onTracksFound(int);
+ }
+
+ public static interface MediaParser.SeekMap {
+ method public long getDurationUs();
+ method @NonNull public android.util.Pair<android.media.MediaParser.SeekPoint,android.media.MediaParser.SeekPoint> getSeekPoints(long);
+ method public boolean isSeekable();
+ field public static final int UNKNOWN_DURATION = -2147483648; // 0x80000000
+ }
+
+ public static final class MediaParser.SeekPoint {
+ field @NonNull public static final android.media.MediaParser.SeekPoint START;
+ field public final long position;
+ field public final long timeUs;
+ }
+
+ public static interface MediaParser.SeekableInputReader extends android.media.MediaParser.InputReader {
+ method public void seekToPosition(long);
+ }
+
+ public static final class MediaParser.UnrecognizedInputFormatException extends java.io.IOException {
+ }
+
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
ctor public MediaPlayer();
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index ba85ae66cd1a..c8fdf506c793 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -8,35 +8,35 @@ AcronymName: android.app.NotificationChannel#setImportanceLockedByOEM(boolean):
ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION:
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO:
- Inconsistent extra value; expected `android.telephony.ims.extra.ADDITIONAL_CALL_INFO`, was `AdditionalCallInfo`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE:
- Inconsistent extra value; expected `android.telephony.ims.extra.CALL_RAT_TYPE`, was `CallRadioTech`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CHILD_NUMBER:
- Inconsistent extra value; expected `android.telephony.ims.extra.CHILD_NUMBER`, was `ChildNum`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNA:
- Inconsistent extra value; expected `android.telephony.ims.extra.CNA`, was `cna`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNAP:
- Inconsistent extra value; expected `android.telephony.ims.extra.CNAP`, was `cnap`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CODEC:
- Inconsistent extra value; expected `android.telephony.ims.extra.CODEC`, was `Codec`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DIALSTRING:
- Inconsistent extra value; expected `android.telephony.ims.extra.DIALSTRING`, was `dialstring`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DISPLAY_TEXT:
- Inconsistent extra value; expected `android.telephony.ims.extra.DISPLAY_TEXT`, was `DisplayText`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_EMERGENCY_CALL:
- Inconsistent extra value; expected `android.telephony.ims.extra.EMERGENCY_CALL`, was `e_call`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_IS_CALL_PULL:
- Inconsistent extra value; expected `android.telephony.ims.extra.IS_CALL_PULL`, was `CallPull`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OI:
- Inconsistent extra value; expected `android.telephony.ims.extra.OI`, was `oi`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OIR:
- Inconsistent extra value; expected `android.telephony.ims.extra.OIR`, was `oir`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_REMOTE_URI:
- Inconsistent extra value; expected `android.telephony.ims.extra.REMOTE_URI`, was `remote_uri`
+
ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_USSD:
- Inconsistent extra value; expected `android.telephony.ims.extra.USSD`, was `ussd`
+
ActionValue: android.telephony.ims.ImsReasonInfo#EXTRA_MSG_SERVICE_NOT_AUTHORIZED:
- Inconsistent extra value; expected `android.telephony.ims.extra.MSG_SERVICE_NOT_AUTHORIZED`, was `Forbidden. Not Authorized for Service`
+
ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_CLEANUP:
ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL:
@@ -100,13 +100,13 @@ ArrayReturn: android.os.NativeHandle#getFileDescriptors():
ArrayReturn: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]):
ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
- Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+
ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
- Method parameter should be Collection<ImsCallForwardInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsCallForwardInfo[]`
+
ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
- Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+
ArrayReturn: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
- Method parameter should be Collection<Uri> (or subclass) instead of raw array; was `android.net.Uri[]`
+
ArrayReturn: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
@@ -268,7 +268,7 @@ ConcreteCollection: android.service.autofill.InternalTransformation#batchApply(a
ConcreteCollection: android.service.autofill.UserData#getFieldClassificationAlgorithms():
ConcreteCollection: android.telephony.ims.ImsConferenceState#mParticipants:
- Field type is concrete collection (`java.util.HashMap`); must be higher-level interface
+
ContextFirst: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
@@ -338,9 +338,9 @@ ExecutorRegistration: android.os.RemoteCallback#RemoteCallback(android.os.Remote
ExecutorRegistration: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
ExecutorRegistration: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener):
- Registration methods should have overload that accepts delivery Executor: `setListener`
+
ExecutorRegistration: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener):
- Registration methods should have overload that accepts delivery Executor: `setListener`
+
ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
@@ -458,11 +458,13 @@ InterfaceConstant: android.telecom.PhoneAccountSuggestionService#SERVICE_INTERFA
InternalField: android.telephony.ims.ImsConferenceState#mParticipants:
- Internal field mParticipants must not be exposed
+
KotlinOperator: android.os.WorkSource#get(int):
+KotlinOperator: android.util.SparseArrayMap#get(int, String):
+ Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener:
@@ -472,9 +474,9 @@ ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListen
ListenerInterface: android.os.IncidentManager.AuthListener:
ListenerInterface: android.telephony.ims.ImsCallSessionListener:
- Listeners should be an interface, or otherwise renamed Callback: ImsCallSessionListener
+
ListenerInterface: android.telephony.ims.ImsUtListener:
- Listeners should be an interface, or otherwise renamed Callback: ImsUtListener
+
ListenerLast: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #4:
@@ -494,17 +496,17 @@ ManagerConstructor: android.content.pm.ShortcutManager#ShortcutManager(android.c
ManagerLookup: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
- Managers must always be obtained from Context (`createForSubscriptionId`)
+
ManagerLookup: android.telephony.ims.ProvisioningManager#createForSubscriptionId(int):
- Managers must always be obtained from Context (`createForSubscriptionId`)
+
MethodNameTense: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
- Unexpected tense; probably meant `enabled`, was `getCapabilitiesToEnable`
+
MethodNameUnits: android.telephony.ims.ImsCallForwardInfo#getTimeSeconds():
- Returned time values must be in milliseconds, was `getTimeSeconds`
+
MinMaxConstant: android.os.UserHandle#MIN_SECONDARY_USER_ID:
@@ -1458,7 +1460,7 @@ MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android
MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent) parameter #0:
MissingNullability: android.telephony.CallQuality#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `dest` in method `writeToParcel`
+
MissingNullability: android.telephony.DataSpecificRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
MissingNullability: android.telephony.LteVopsSupportInfo#writeToParcel(android.os.Parcel, int) parameter #0:
@@ -1476,9 +1478,9 @@ MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(St
MissingNullability: android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage(String) parameter #0:
MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent):
- Missing nullability on method `getCarrierPackageNamesForIntent` return
+
MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent) parameter #0:
- Missing nullability on parameter `intent` in method `getCarrierPackageNamesForIntent`
+
MissingNullability: android.telephony.TelephonyManager#getLine1AlphaTag():
MissingNullability: android.telephony.TelephonyManager#getRadioHalVersion():
@@ -1516,315 +1518,315 @@ MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(St
MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #8:
MissingNullability: android.telephony.ims.ImsCallForwardInfo#getNumber():
- Missing nullability on method `getNumber` return
+
MissingNullability: android.telephony.ims.ImsCallForwardInfo#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #2:
- Missing nullability on parameter `callExtras` in method `ImsCallProfile`
+
MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #3:
- Missing nullability on parameter `mediaProfile` in method `ImsCallProfile`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String):
- Missing nullability on method `getCallExtra` return
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtra`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String):
- Missing nullability on method `getCallExtra` return
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtra`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #1:
- Missing nullability on parameter `defaultValue` in method `getCallExtra`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtraBoolean`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String, boolean) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtraBoolean`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtraInt`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String, int) parameter #0:
- Missing nullability on parameter `name` in method `getCallExtraInt`
+
MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtras():
- Missing nullability on method `getCallExtras` return
+
MissingNullability: android.telephony.ims.ImsCallProfile#getMediaProfile():
- Missing nullability on method `getMediaProfile` return
+
MissingNullability: android.telephony.ims.ImsCallProfile#getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `callProfile` in method `getVideoStateFromImsCallProfile`
+
MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #0:
- Missing nullability on parameter `name` in method `setCallExtra`
+
MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #1:
- Missing nullability on parameter `value` in method `setCallExtra`
+
MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraBoolean(String, boolean) parameter #0:
- Missing nullability on parameter `name` in method `setCallExtraBoolean`
+
MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraInt(String, int) parameter #0:
- Missing nullability on parameter `name` in method `setCallExtraInt`
+
MissingNullability: android.telephony.ims.ImsCallProfile#updateCallExtras(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `updateCallExtras`
+
MissingNullability: android.telephony.ims.ImsCallProfile#updateCallType(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `updateCallType`
+
MissingNullability: android.telephony.ims.ImsCallProfile#updateMediaProfile(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `updateMediaProfile`
+
MissingNullability: android.telephony.ims.ImsCallProfile#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionConferenceExtendFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `newSession` in method `callSessionConferenceExtendReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
- Missing nullability on parameter `profile` in method `callSessionConferenceExtendReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `newSession` in method `callSessionConferenceExtended`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
- Missing nullability on parameter `profile` in method `callSessionConferenceExtended`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState) parameter #0:
- Missing nullability on parameter `state` in method `callSessionConferenceStateUpdated`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
- Missing nullability on parameter `reasonInfo` in method `callSessionHandover`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
- Missing nullability on parameter `reasonInfo` in method `callSessionHandoverFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHeld(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionHeld`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionHoldFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldReceived(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionHoldReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiated(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionInitiated`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionInitiatedFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionInviteParticipantsRequestFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase) parameter #0:
- Missing nullability on parameter `newSession` in method `callSessionMergeComplete`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionMergeFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `newSession` in method `callSessionMergeStarted`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
- Missing nullability on parameter `profile` in method `callSessionMergeStarted`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionProgressing`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionRemoveParticipantsRequestFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionResumeFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeReceived(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionResumeReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumed(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionResumed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttMessageReceived(String) parameter #0:
- Missing nullability on parameter `rttMessage` in method `callSessionRttMessageReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `callProfile` in method `callSessionRttModifyRequestReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification) parameter #0:
- Missing nullability on parameter `suppSrvNotification` in method `callSessionSuppServiceReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionTerminated(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionTerminated`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `reasonInfo` in method `callSessionUpdateFailed`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateReceived(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionUpdateReceived`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdated(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `profile` in method `callSessionUpdated`
+
MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUssdMessageReceived(int, String) parameter #1:
- Missing nullability on parameter `ussdMessage` in method `callSessionUssdMessageReceived`
+
MissingNullability: android.telephony.ims.ImsConferenceState#getConnectionStateForStatus(String) parameter #0:
- Missing nullability on parameter `status` in method `getConnectionStateForStatus`
+
MissingNullability: android.telephony.ims.ImsConferenceState#mParticipants:
- Missing nullability on field `mParticipants` in class `class android.telephony.ims.ImsConferenceState`
+
MissingNullability: android.telephony.ims.ImsConferenceState#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsExternalCallState#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsReasonInfo#ImsReasonInfo(int, int, String) parameter #2:
- Missing nullability on parameter `extraMessage` in method `ImsReasonInfo`
+
MissingNullability: android.telephony.ims.ImsReasonInfo#getExtraMessage():
- Missing nullability on method `getExtraMessage` return
+
MissingNullability: android.telephony.ims.ImsReasonInfo#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsService#createMmTelFeature(int):
- Missing nullability on method `createMmTelFeature` return
+
MissingNullability: android.telephony.ims.ImsService#createRcsFeature(int):
- Missing nullability on method `createRcsFeature` return
+
MissingNullability: android.telephony.ims.ImsService#getConfig(int):
- Missing nullability on method `getConfig` return
+
MissingNullability: android.telephony.ims.ImsService#getRegistration(int):
- Missing nullability on method `getRegistration` return
+
MissingNullability: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) parameter #0:
- Missing nullability on parameter `c` in method `onUpdateSupportedImsFeatures`
+
MissingNullability: android.telephony.ims.ImsService#querySupportedImsFeatures():
- Missing nullability on method `querySupportedImsFeatures` return
+
MissingNullability: android.telephony.ims.ImsSsData#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsSsInfo#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsStreamMediaProfile#copyFrom(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
- Missing nullability on parameter `profile` in method `copyFrom`
+
MissingNullability: android.telephony.ims.ImsStreamMediaProfile#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #4:
- Missing nullability on parameter `number` in method `ImsSuppServiceNotification`
+
MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #5:
- Missing nullability on parameter `history` in method `ImsSuppServiceNotification`
+
MissingNullability: android.telephony.ims.ImsSuppServiceNotification#history:
- Missing nullability on field `history` in class `class android.telephony.ims.ImsSuppServiceNotification`
+
MissingNullability: android.telephony.ims.ImsSuppServiceNotification#number:
- Missing nullability on field `number` in class `class android.telephony.ims.ImsSuppServiceNotification`
+
MissingNullability: android.telephony.ims.ImsSuppServiceNotification#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `out` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.ImsUtListener#onSupplementaryServiceIndication(android.telephony.ims.ImsSsData) parameter #0:
- Missing nullability on parameter `ssData` in method `onSupplementaryServiceIndication`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
- Missing nullability on parameter `cbInfo` in method `onUtConfigurationCallBarringQueried`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
- Missing nullability on parameter `cfInfo` in method `onUtConfigurationCallForwardQueried`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
- Missing nullability on parameter `cwInfo` in method `onUtConfigurationCallWaitingQueried`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueried(int, android.os.Bundle) parameter #1:
- Missing nullability on parameter `configuration` in method `onUtConfigurationQueried`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
- Missing nullability on parameter `error` in method `onUtConfigurationQueryFailed`
+
MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
- Missing nullability on parameter `error` in method `onUtConfigurationUpdateFailed`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities) parameter #0:
- Missing nullability on parameter `CameraCapabilities` in method `changeCameraCapabilities`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #0:
- Missing nullability on parameter `fromProfile` in method `onSendSessionModifyRequest`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
- Missing nullability on parameter `toProfile` in method `onSendSessionModifyRequest`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyResponse(android.telecom.VideoProfile) parameter #0:
- Missing nullability on parameter `responseProfile` in method `onSendSessionModifyResponse`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String) parameter #0:
- Missing nullability on parameter `cameraId` in method `onSetCamera`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String, int) parameter #0:
- Missing nullability on parameter `cameraId` in method `onSetCamera`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetDisplaySurface(android.view.Surface) parameter #0:
- Missing nullability on parameter `surface` in method `onSetDisplaySurface`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPauseImage(android.net.Uri) parameter #0:
- Missing nullability on parameter `uri` in method `onSetPauseImage`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPreviewSurface(android.view.Surface) parameter #0:
- Missing nullability on parameter `surface` in method `onSetPreviewSurface`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyRequest(android.telecom.VideoProfile) parameter #0:
- Missing nullability on parameter `VideoProfile` in method `receiveSessionModifyRequest`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
- Missing nullability on parameter `requestedProfile` in method `receiveSessionModifyResponse`
+
MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #2:
- Missing nullability on parameter `responseProfile` in method `receiveSessionModifyResponse`
+
MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToDisable():
- Missing nullability on method `getCapabilitiesToDisable` return
+
MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
- Missing nullability on method `getCapabilitiesToEnable` return
+
MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `dest` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #0:
- Missing nullability on parameter `request` in method `changeEnabledCapabilities`
+
MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #1:
- Missing nullability on parameter `c` in method `changeEnabledCapabilities`
+
MissingNullability: android.telephony.ims.feature.MmTelFeature#queryCapabilityStatus():
- Missing nullability on method `queryCapabilityStatus` return
+
MissingNullability: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities) parameter #0:
- Missing nullability on parameter `c` in method `MmTelCapabilities`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#accept(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
- Missing nullability on parameter `profile` in method `accept`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#deflect(String) parameter #0:
- Missing nullability on parameter `deflectNumber` in method `deflect`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#extendToConference(String[]) parameter #0:
- Missing nullability on parameter `participants` in method `extendToConference`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallId():
- Missing nullability on method `getCallId` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallProfile():
- Missing nullability on method `getCallProfile` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getImsVideoCallProvider():
- Missing nullability on method `getImsVideoCallProvider` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getLocalCallProfile():
- Missing nullability on method `getLocalCallProfile` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String):
- Missing nullability on method `getProperty` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String) parameter #0:
- Missing nullability on parameter `name` in method `getProperty`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getRemoteCallProfile():
- Missing nullability on method `getRemoteCallProfile` return
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#hold(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
- Missing nullability on parameter `profile` in method `hold`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#inviteParticipants(String[]) parameter #0:
- Missing nullability on parameter `participants` in method `inviteParticipants`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#removeParticipants(String[]) parameter #0:
- Missing nullability on parameter `participants` in method `removeParticipants`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#resume(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
- Missing nullability on parameter `profile` in method `resume`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendDtmf(char, android.os.Message) parameter #1:
- Missing nullability on parameter `result` in method `sendDtmf`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttMessage(String) parameter #0:
- Missing nullability on parameter `rttMessage` in method `sendRttMessage`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttModifyRequest(android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `toProfile` in method `sendRttModifyRequest`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendUssd(String) parameter #0:
- Missing nullability on parameter `ussdMessage` in method `sendUssd`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener) parameter #0:
- Missing nullability on parameter `listener` in method `setListener`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `callee` in method `start`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #1:
- Missing nullability on parameter `profile` in method `start`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #0:
- Missing nullability on parameter `participants` in method `startConference`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #1:
- Missing nullability on parameter `profile` in method `startConference`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#update(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
- Missing nullability on parameter `profile` in method `update`
+
MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase.State#toString(int):
- Missing nullability on method `toString` return
+
MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#getConfigString(int):
- Missing nullability on method `getConfigString` return
+
MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#notifyProvisionedValueChanged(int, String) parameter #1:
- Missing nullability on parameter `value` in method `notifyProvisionedValueChanged`
+
MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#setConfig(int, String) parameter #1:
- Missing nullability on parameter `value` in method `setConfig`
+
MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#getServiceFeatures():
- Missing nullability on method `getServiceFeatures` return
+
MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
- Missing nullability on parameter `dest` in method `writeToParcel`
+
MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int):
- Missing nullability on method `addFeature` return
+
MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#build():
- Missing nullability on method `build` return
+
MissingNullability: android.telephony.ims.stub.ImsMultiEndpointImplBase#onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>) parameter #0:
- Missing nullability on parameter `externalCallDialogs` in method `onImsExternalCallStateUpdate`
+
MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onDeregistered(android.telephony.ims.ImsReasonInfo) parameter #0:
- Missing nullability on parameter `info` in method `onDeregistered`
+
MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
- Missing nullability on parameter `uris` in method `onSubscriberAssociatedUriChanged`
+
MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
- Missing nullability on parameter `info` in method `onTechnologyChangeFailed`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#getSmsFormat():
- Missing nullability on method `getSmsFormat` return
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #1:
- Missing nullability on parameter `format` in method `onSmsReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #2:
- Missing nullability on parameter `pdu` in method `onSmsReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1:
- Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2:
- Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #2:
- Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #3:
- Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #2:
- Missing nullability on parameter `format` in method `sendSms`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #3:
- Missing nullability on parameter `smsc` in method `sendSms`
+
MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #5:
- Missing nullability on parameter `pdu` in method `sendSms`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1:
- Missing nullability on parameter `number` in method `queryCallForward`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0:
- Missing nullability on parameter `listener` in method `setListener`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0:
- Missing nullability on parameter `ssInfo` in method `transact`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarring(int, int, String[]) parameter #2:
- Missing nullability on parameter `barrList` in method `updateCallBarring`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarringForServiceClass(int, int, String[], int) parameter #2:
- Missing nullability on parameter `barrList` in method `updateCallBarringForServiceClass`
+
MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallForward(int, int, String, int, int) parameter #2:
- Missing nullability on parameter `number` in method `updateCallForward`
+
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
@@ -2276,7 +2278,7 @@ NotCloseable: android.app.prediction.AppPredictor:
NotCloseable: android.os.HwParcel:
NotCloseable: android.telephony.ims.stub.ImsUtImplBase:
- Classes that release resources (close()) should implement AutoClosable and CloseGuard: class android.telephony.ims.stub.ImsUtImplBase
+
OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
@@ -2290,21 +2292,21 @@ OnNameExpected: android.service.notification.NotificationAssistantService#attach
OnNameExpected: android.service.quicksettings.TileService#isQuickSettingsSupported():
OnNameExpected: android.telephony.ims.ImsService#createMmTelFeature(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#createRcsFeature(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#disableIms(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#enableIms(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#getConfig(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#getRegistration(int):
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#querySupportedImsFeatures():
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.ims.ImsService#readyForFeatureCreation():
- If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+
OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
@@ -2444,7 +2446,7 @@ RethrowRemoteException: android.os.HwBinder#transact(int, android.os.HwParcel, a
RethrowRemoteException: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
RethrowRemoteException: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration):
- Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
+
RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
@@ -2524,7 +2526,7 @@ SamShouldBeLast: android.service.autofill.ImageTransformation#apply(android.serv
SamShouldBeLast: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>):
SamShouldBeLast: android.telephony.ims.ImsMmTelManager#getFeatureState(java.util.function.Consumer<java.lang.Integer>, java.util.concurrent.Executor):
- SAM-compatible parameters (such as parameter 1, "callback", in android.telephony.ims.ImsMmTelManager.getFeatureState) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+
SamShouldBeLast: android.view.Choreographer#postCallback(int, Runnable, Object):
SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long):
@@ -2597,6 +2599,8 @@ UserHandle: android.app.role.RoleManager#removeOnRoleHoldersChangedListenerAsUse
UserHandle: android.app.role.RoleManager#removeRoleHolderAsUser(String, String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+UserHandle: android.companion.CompanionDeviceManager#isDeviceAssociated(String, android.net.MacAddress, android.os.UserHandle):
+ When a method overload is needed to target a specific UserHandle, callers should be directed to use Context.createPackageContextAsUser() and re-obtain the relevant Manager, and no new API should be added
UserHandle: android.content.pm.PackageManager#getInstallReason(String, android.os.UserHandle):
UserHandle: android.content.pm.PackageManager#getPermissionFlags(String, String, android.os.UserHandle):
diff --git a/media/Android.bp b/media/Android.bp
index 022fa9b7bb9e..1912930f2081 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -45,8 +45,8 @@ java_library {
filegroup {
name: "updatable-media-srcs",
srcs: [
- ":mediasession2-srcs",
":mediaparser-srcs",
+ ":mediasession2-srcs",
],
}
@@ -73,7 +73,8 @@ filegroup {
name: "mediaparser-srcs",
srcs: [
"apex/java/android/media/MediaParser.java"
- ]
+ ],
+ path: "apex/java"
}
metalava_updatable_media_args = " --error UnhiddenSystemApi " +
diff --git a/media/apex/java/android/media/MediaParser.java b/media/apex/java/android/media/MediaParser.java
index c06e2837bcdc..8824269ea0c0 100644
--- a/media/apex/java/android/media/MediaParser.java
+++ b/media/apex/java/android/media/MediaParser.java
@@ -15,10 +15,47 @@
*/
package android.media;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.Uri;
+import android.text.TextUtils;
import android.util.Pair;
-
+import android.util.SparseArray;
+
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
+import com.google.android.exoplayer2.extractor.Extractor;
+import com.google.android.exoplayer2.extractor.ExtractorInput;
+import com.google.android.exoplayer2.extractor.ExtractorOutput;
+import com.google.android.exoplayer2.extractor.PositionHolder;
+import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints;
+import com.google.android.exoplayer2.extractor.TrackOutput;
+import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
+import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
+import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
+import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
+import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
+import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
+import com.google.android.exoplayer2.extractor.ogg.OggExtractor;
+import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
+import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
+import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
+import com.google.android.exoplayer2.extractor.ts.PsExtractor;
+import com.google.android.exoplayer2.extractor.ts.TsExtractor;
+import com.google.android.exoplayer2.extractor.wav.WavExtractor;
+import com.google.android.exoplayer2.upstream.DataSource;
+import com.google.android.exoplayer2.upstream.DataSpec;
+import com.google.android.exoplayer2.upstream.TransferListener;
+import com.google.android.exoplayer2.util.ParsableByteArray;
+
+import java.io.EOFException;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
* Parses media container formats and extracts contained media samples and metadata.
@@ -32,16 +69,93 @@ import java.util.List;
* <p>Users must implement the following to use this class.
*
* <ul>
- * <li>{@link Input}: Provides the media containers bytes to parse.
- * <li>{@link OutputCallback}: Provides a sink for all extracted data and metadata.
+ * <li>{@link InputReader}: Provides the media container's bytes to parse.
+ * <li>{@link OutputConsumer}: Provides a sink for all extracted data and metadata.
* </ul>
*
- * TODO: Add usage example here.
+ * <p>The following code snippet includes a usage example:
+ *
+ * <pre>
+ * MyOutputConsumer myOutputConsumer = new MyOutputConsumer();
+ * MyInputReader myInputReader = new MyInputReader("www.example.com");
+ * MediaParser mediaParser = MediaParser.create(myOutputConsumer);
+ *
+ * while (mediaParser.advance(myInputReader)) {}
+ *
+ * mediaParser.release();
+ * mediaParser = null;
+ * </pre>
+ *
+ * <p>The following code snippet provides a rudimentary {@link OutputConsumer} sample implementation
+ * which extracts and publishes all video samples:
+ *
+ * <pre>
+ *
+ * class VideoOutputConsumer implements MediaParser.OutputConsumer {
+ *
+ * private static final int MAXIMUM_SAMPLE_SIZE = ...;
+ * private byte[] sampleDataBuffer = new byte[MAXIMUM_SAMPLE_SIZE];
+ * private int videoTrackIndex = -1;
+ * private int bytesWrittenCount = 0;
+ *
+ * \@Override
+ * public void onSeekMap(int i, @NonNull MediaFormat mediaFormat) { \/* Do nothing. *\/ }
+ *
+ * \@Override
+ * public void onFormat(int i, @NonNull MediaFormat mediaFormat) {
+ * if (videoTrackIndex == -1 && mediaFormat
+ * .getString(MediaFormat.KEY_MIME, \/* defaultValue= *\/ "").startsWith("video/")) {
+ * videoTrackIndex = i;
+ * }
+ * }
+ *
+ * \@Override
+ * public void onSampleData(int trackIndex, @NonNull InputReader inputReader)
+ * throws IOException, InterruptedException {
+ * int numberOfBytesToRead = (int) inputReader.getLength();
+ * if (videoTrackIndex != trackIndex) {
+ * // Discard contents.
+ * inputReader.read(\/* bytes= *\/ null, \/* offset= *\/ 0, numberOfBytesToRead);
+ * }
+ * int bytesRead = inputReader.read(sampleDataBuffer, bytesWrittenCount, numberOfBytesToRead);
+ * bytesWrittenCount += bytesRead;
+ * }
+ *
+ * \@Override
+ * public void onSampleCompleted(
+ * int trackIndex,
+ * long timeUs,
+ * int flags,
+ * int size,
+ * int offset,
+ * \@Nullable CryptoInfo cryptoData) {
+ * if (videoTrackIndex != trackIndex) {
+ * return; // It's not the video track. Ignore.
+ * }
+ * byte[] sampleData = new byte[size];
+ * System.arraycopy(sampleDataBuffer, bytesWrittenCount - size - offset, sampleData, \/*
+ * destPos= *\/ 0, size);
+ * // Place trailing bytes at the start of the buffer.
+ * System.arraycopy(
+ * sampleDataBuffer,
+ * bytesWrittenCount - offset,
+ * sampleDataBuffer,
+ * \/* destPos= *\/ 0,
+ * \/* size= *\/ offset);
+ * publishSample(sampleData, timeUs, flags);
+ * }
+ * }
+ *
+ * </pre>
*/
-// @HiddenApi
public final class MediaParser {
- /** Maps seek positions to corresponding positions in the stream. */
+ /**
+ * Maps seek positions to {@link SeekPoint SeekPoints} in the stream.
+ *
+ * <p>A {@link SeekPoint} is a position in the stream from which a player may successfully start
+ * playing media samples.
+ */
public interface SeekMap {
/** Returned by {@link #getDurationUs()} when the duration is unknown. */
@@ -62,13 +176,14 @@ public final class MediaParser {
* <p>{@code getSeekPoints(timeUs).first} contains the latest seek point for samples with
* timestamp equal to or smaller than {@code timeUs}.
*
- * <p>{@code getSeekPoints(timeUs).second} contains the earlies seek point for samples with
+ * <p>{@code getSeekPoints(timeUs).second} contains the earliest seek point for samples with
* timestamp equal to or greater than {@code timeUs}. If a seek point exists for {@code
* timeUs}, the returned pair will contain the same {@link SeekPoint} twice.
*
* @param timeUs A seek time in microseconds.
* @return The corresponding {@link SeekPoint SeekPoints}.
*/
+ @NonNull
Pair<SeekPoint, SeekPoint> getSeekPoints(long timeUs);
}
@@ -76,30 +191,30 @@ public final class MediaParser {
public static final class SeekPoint {
/** A {@link SeekPoint} whose time and byte offset are both set to 0. */
- public static final SeekPoint START = new SeekPoint(0, 0);
+ public static final @NonNull SeekPoint START = new SeekPoint(0, 0);
/** The time of the seek point, in microseconds. */
- public final long mTimeUs;
+ public final long timeUs;
/** The byte offset of the seek point. */
- public final long mPosition;
+ public final long position;
/**
* @param timeUs The time of the seek point, in microseconds.
* @param position The byte offset of the seek point.
*/
- public SeekPoint(long timeUs, long position) {
- this.mTimeUs = timeUs;
- this.mPosition = position;
+ private SeekPoint(long timeUs, long position) {
+ this.timeUs = timeUs;
+ this.position = position;
}
@Override
- public String toString() {
- return "[timeUs=" + mTimeUs + ", position=" + mPosition + "]";
+ public @NonNull String toString() {
+ return "[timeUs=" + timeUs + ", position=" + position + "]";
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
@@ -107,25 +222,26 @@ public final class MediaParser {
return false;
}
SeekPoint other = (SeekPoint) obj;
- return mTimeUs == other.mTimeUs && mPosition == other.mPosition;
+ return timeUs == other.timeUs && position == other.position;
}
@Override
public int hashCode() {
- int result = (int) mTimeUs;
- result = 31 * result + (int) mPosition;
+ int result = (int) timeUs;
+ result = 31 * result + (int) position;
return result;
}
}
/** Provides input data to {@link MediaParser}. */
- public interface Input {
+ public interface InputReader {
/**
* Reads up to {@code readLength} bytes of data and stores them into {@code buffer},
* starting at index {@code offset}.
*
- * <p>The call will block until at least one byte of data has been read.
+ * <p>This method blocks until at least one byte is read, the end of input is detected, or
+ * an exception is thrown. The read position advances to the first unread byte.
*
* @param buffer The buffer into which the read data should be stored.
* @param offset The start offset into {@code buffer} at which data should be written.
@@ -134,7 +250,7 @@ public final class MediaParser {
* of the input has been reached.
* @throws java.io.IOException If an error occurs reading from the source.
*/
- int read(byte[] buffer, int offset, int readLength)
+ int read(@NonNull byte[] buffer, int offset, int readLength)
throws IOException, InterruptedException;
/** Returns the current read position (byte offset) in the stream. */
@@ -144,22 +260,39 @@ public final class MediaParser {
long getLength();
}
- /** Receives extracted media sample data and metadata from {@link MediaParser}. */
- public interface OutputCallback {
+ /** {@link InputReader} that allows setting the read position. */
+ public interface SeekableInputReader extends InputReader {
/**
- * Called when the number of tracks is defined.
+ * Sets the read position at the given {@code position}.
*
- * @param numberOfTracks The number of tracks in the stream.
+ * <p>{@link #advance} will immediately return after calling this method.
+ *
+ * @param position The position to seek to, in bytes.
*/
- void onTracksFound(int numberOfTracks);
+ void seekToPosition(long position);
+ }
+
+ /** Receives extracted media sample data and metadata from {@link MediaParser}. */
+ public interface OutputConsumer {
/**
* Called when a {@link SeekMap} has been extracted from the stream.
*
+ * <p>This method is called at least once before any samples are {@link #onSampleCompleted
+ * complete}. May be called multiple times after that in order to add {@link SeekPoint
+ * SeekPoints}.
+ *
* @param seekMap The extracted {@link SeekMap}.
*/
- void onSeekMap(SeekMap seekMap);
+ void onSeekMap(@NonNull SeekMap seekMap);
+
+ /**
+ * Called when the number of tracks is found.
+ *
+ * @param numberOfTracks The number of tracks in the stream.
+ */
+ void onTracksFound(int numberOfTracks);
/**
* Called when the {@link MediaFormat} of the track is extracted from the stream.
@@ -167,7 +300,7 @@ public final class MediaParser {
* @param trackIndex The index of the track for which the {@link MediaFormat} was found.
* @param format The extracted {@link MediaFormat}.
*/
- void onFormat(int trackIndex, MediaFormat format);
+ void onFormat(int trackIndex, @NonNull MediaFormat format);
/**
* Called to write sample data to the output.
@@ -176,16 +309,15 @@ public final class MediaParser {
* thrown {@link IOException} caused by reading from {@code input}.
*
* @param trackIndex The index of the track to which the sample data corresponds.
- * @param input The {@link Input} from which to read the data.
- * @return
+ * @param inputReader The {@link InputReader} from which to read the data.
*/
- int onSampleData(int trackIndex, Input input) throws IOException, InterruptedException;
+ void onSampleData(int trackIndex, @NonNull InputReader inputReader)
+ throws IOException, InterruptedException;
/**
- * Defines the boundaries and metadata of an extracted sample.
+ * Called once all the data of a sample has been passed to {@link #onSampleData}.
*
- * <p>The corresponding sample data will have already been passed to the output via calls to
- * {@link #onSampleData}.
+ * <p>Also includes sample metadata, like presentation timestamp and flags.
*
* @param trackIndex The index of the track to which the sample corresponds.
* @param timeUs The media timestamp associated with the sample, in microseconds.
@@ -203,57 +335,22 @@ public final class MediaParser {
int flags,
int size,
int offset,
- MediaCodec.CryptoInfo cryptoData);
- }
-
- /**
- * Controls the behavior of extractors' implementations.
- *
- * <p>DESIGN NOTE: For setting flags like workarounds and special behaviors for adaptive
- * streaming.
- */
- public static final class Parameters {
-
- // TODO: Implement.
-
- }
-
- /** Holds the result of an {@link #advance} invocation. */
- public static final class ResultHolder {
-
- /** Creates a new instance with {@link #result} holding {@link #ADVANCE_RESULT_CONTINUE}. */
- public ResultHolder() {
- result = ADVANCE_RESULT_CONTINUE;
- }
-
- /**
- * May hold {@link #ADVANCE_RESULT_END_OF_INPUT}, {@link #ADVANCE_RESULT_CONTINUE}, {@link
- * #ADVANCE_RESULT_SEEK}.
- */
- public int result;
-
- /**
- * If {@link #result} holds {@link #ADVANCE_RESULT_SEEK}, holds the stream position required
- * from the passed {@link Input} to the next {@link #advance} call. If {@link #result} does
- * not hold {@link #ADVANCE_RESULT_SEEK}, the value of this variable is undefined and should
- * be ignored.
- */
- public long seekPosition;
+ @Nullable MediaCodec.CryptoInfo cryptoData);
}
/**
* Thrown if all extractors implementations provided to {@link #create} failed to sniff the
* input content.
*/
- // @HiddenApi
public static final class UnrecognizedInputFormatException extends IOException {
/**
* Creates a new instance which signals that the extractors with the given names failed to
* parse the input.
*/
- public static UnrecognizedInputFormatException createForExtractors(
- String... extractorNames) {
+ @NonNull
+ private static UnrecognizedInputFormatException createForExtractors(
+ @NonNull String... extractorNames) {
StringBuilder builder = new StringBuilder();
builder.append("None of the available extractors ( ");
builder.append(extractorNames[0]);
@@ -270,21 +367,9 @@ public final class MediaParser {
}
}
- // Public constants.
+ // Private constants.
- /**
- * Returned by {@link #advance} if the {@link Input} passed to the next {@link #advance} is
- * required to provide data continuing from the position in the stream reached by the returning
- * call.
- */
- public static final int ADVANCE_RESULT_CONTINUE = -1;
- /** Returned by {@link #advance} if the end of the {@link Input} was reached. */
- public static final int ADVANCE_RESULT_END_OF_INPUT = -2;
- /**
- * Returned by {@link #advance} when its next call expects a specific stream position, which
- * will be held by {@link ResultHolder#seekPosition}.
- */
- public static final int ADVANCE_RESULT_SEEK = -3;
+ private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
// Instance creation methods.
@@ -293,13 +378,15 @@ public final class MediaParser {
* instance will attempt extraction without sniffing the content.
*
* @param name The name of the extractor that will be associated with the created instance.
- * @param outputCallback The {@link OutputCallback} to which track data and samples are pushed.
- * @param parameters Parameters that control specific aspects of the behavior of the extractors.
+ * @param outputConsumer The {@link OutputConsumer} to which track data and samples are pushed.
* @return A new instance.
+ * @throws IllegalArgumentException If an invalid name is provided.
*/
- public static MediaParser createByName(
- String name, OutputCallback outputCallback, Parameters parameters) {
- throw new UnsupportedOperationException();
+ public static @NonNull MediaParser createByName(
+ @NonNull String name, @NonNull OutputConsumer outputConsumer) {
+ String[] nameAsArray = new String[] {name};
+ assertValidNames(nameAsArray);
+ return new MediaParser(outputConsumer, /* sniff= */ false, name);
}
/**
@@ -307,30 +394,46 @@ public final class MediaParser {
* the first {@link #advance} call. Extractor implementations will sniff the content in order of
* appearance in {@code extractorNames}.
*
- * @param outputCallback The {@link OutputCallback} to track data and samples are obtained.
- * @param parameters Parameters that control specific aspects of the behavior of the extractors.
+ * @param outputConsumer The {@link OutputConsumer} to which extracted data is output.
* @param extractorNames The names of the extractors to sniff the content with. If empty, a
* default array of names is used.
* @return A new instance.
*/
- public static MediaParser create(
- OutputCallback outputCallback, Parameters parameters, String... extractorNames) {
- throw new UnsupportedOperationException();
+ public static @NonNull MediaParser create(
+ @NonNull OutputConsumer outputConsumer, @NonNull String... extractorNames) {
+ assertValidNames(extractorNames);
+ if (extractorNames.length == 0) {
+ extractorNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
+ }
+ return new MediaParser(outputConsumer, /* sniff= */ true, extractorNames);
}
// Misc static methods.
/**
* Returns an immutable list with the names of the extractors that are suitable for container
- * formats with the given {@code mimeTypes}. If an empty string is passed, all available
- * extractors' names are returned.
+ * formats with the given {@link MediaFormat}.
*
- * <p>TODO: Replace string with media type object.
+ * <p>TODO: List which properties are taken into account. E.g. MimeType.
*/
- public static List<String> getExtractorNames(String mimeTypes) {
+ public static @NonNull List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
throw new UnsupportedOperationException();
}
+ // Private fields.
+
+ private final OutputConsumer mOutputConsumer;
+ private final String[] mExtractorNamesPool;
+ private final PositionHolder mPositionHolder;
+ private final InputReadingDataSource mDataSource;
+ private final ExtractorInputAdapter mScratchExtractorInputAdapter;
+ private final ParsableByteArrayAdapter mScratchParsableByteArrayAdapter;
+ private String mExtractorName;
+ private Extractor mExtractor;
+ private ExtractorInput mExtractorInput;
+ private long mPendingSeekPosition;
+ private long mPendingSeekTimeUs;
+
// Public methods.
/**
@@ -344,8 +447,8 @@ public final class MediaParser {
* @return The name of the backing extractor implementation, or null if the backing extractor
* implementation has not yet been selected.
*/
- public String getExtractorName() {
- throw new UnsupportedOperationException();
+ public @Nullable String getExtractorName() {
+ return mExtractorName;
}
/**
@@ -357,26 +460,85 @@ public final class MediaParser {
* <p>If this instance was created using {@link #create}. the first call to this method will
* sniff the content with the extractors with the provided names.
*
- * @param input The {@link Input} from which to obtain the media container data.
- * @param resultHolder The {@link ResultHolder} into which the result of the operation will be
- * written.
+ * @param seekableInputReader The {@link SeekableInputReader} from which to obtain the media
+ * container data.
+ * @return Whether there is any data left to extract. Returns false if the end of input has been
+ * reached.
* @throws UnrecognizedInputFormatException
*/
- public void advance(Input input, ResultHolder resultHolder)
+ public boolean advance(@NonNull SeekableInputReader seekableInputReader)
throws IOException, InterruptedException {
- throw new UnsupportedOperationException();
+ if (mExtractorInput == null) {
+ // TODO: For efficiency, the same implementation should be used, by providing a
+ // clearBuffers() method, or similar.
+ mExtractorInput =
+ new DefaultExtractorInput(
+ mDataSource,
+ seekableInputReader.getPosition(),
+ seekableInputReader.getLength());
+ }
+ mDataSource.mInputReader = seekableInputReader;
+
+ if (mExtractor == null) {
+ for (String extractorName : mExtractorNamesPool) {
+ Extractor extractor =
+ EXTRACTOR_FACTORIES_BY_NAME.get(extractorName).createInstance();
+ try {
+ if (extractor.sniff(mExtractorInput)) {
+ mExtractorName = extractorName;
+ mExtractor = extractor;
+ mExtractor.init(new ExtractorOutputAdapter());
+ break;
+ }
+ } catch (EOFException e) {
+ // Do nothing.
+ } catch (IOException | InterruptedException e) {
+ throw new IllegalStateException(e);
+ } finally {
+ mExtractorInput.resetPeekPosition();
+ }
+ }
+ if (mExtractor == null) {
+ UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool);
+ }
+ return true;
+ }
+
+ if (isPendingSeek()) {
+ mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeUs);
+ removePendingSeek();
+ }
+
+ mPositionHolder.position = seekableInputReader.getPosition();
+ int result = mExtractor.read(mExtractorInput, mPositionHolder);
+ if (result == Extractor.RESULT_END_OF_INPUT) {
+ return false;
+ }
+ if (result == Extractor.RESULT_SEEK) {
+ mExtractorInput = null;
+ seekableInputReader.seekToPosition(mPositionHolder.position);
+ }
+ return true;
}
/**
* Seeks within the media container being extracted.
*
- * <p>Following a call to this method, the {@link Input} passed to the next invocation of {@link
- * #advance} must provide data starting from {@link SeekPoint#mPosition} in the stream.
+ * <p>{@link SeekPoint SeekPoints} can be obtained from the {@link SeekMap} passed to {@link
+ * OutputConsumer#onSeekMap(SeekMap)}.
+ *
+ * <p>Following a call to this method, the {@link InputReader} passed to the next invocation of
+ * {@link #advance} must provide data starting from {@link SeekPoint#position} in the stream.
*
* @param seekPoint The {@link SeekPoint} to seek to.
*/
- public void seek(SeekPoint seekPoint) {
- throw new UnsupportedOperationException();
+ public void seek(@NonNull SeekPoint seekPoint) {
+ if (mExtractor == null) {
+ mPendingSeekPosition = seekPoint.position;
+ mPendingSeekTimeUs = seekPoint.timeUs;
+ } else {
+ mExtractor.seek(seekPoint.position, seekPoint.timeUs);
+ }
}
/**
@@ -386,6 +548,359 @@ public final class MediaParser {
* invoked. DESIGN NOTE: Should be removed. There shouldn't be any resource for releasing.
*/
public void release() {
- throw new UnsupportedOperationException();
+ mExtractorInput = null;
+ mExtractor = null;
+ }
+
+ // Private methods.
+
+ private MediaParser(
+ OutputConsumer outputConsumer, boolean sniff, String... extractorNamesPool) {
+ mOutputConsumer = outputConsumer;
+ mExtractorNamesPool = extractorNamesPool;
+ if (!sniff) {
+ mExtractorName = extractorNamesPool[0];
+ mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
+ }
+ mPositionHolder = new PositionHolder();
+ mDataSource = new InputReadingDataSource();
+ removePendingSeek();
+ mScratchExtractorInputAdapter = new ExtractorInputAdapter();
+ mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
+ }
+
+ private boolean isPendingSeek() {
+ return mPendingSeekPosition >= 0;
+ }
+
+ private void removePendingSeek() {
+ mPendingSeekPosition = -1;
+ mPendingSeekTimeUs = -1;
+ }
+
+ // Private classes.
+
+ private static final class InputReadingDataSource implements DataSource {
+
+ public InputReader mInputReader;
+
+ @Override
+ public void addTransferListener(TransferListener transferListener) {
+ // Do nothing.
+ }
+
+ @Override
+ public long open(DataSpec dataSpec) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int read(byte[] buffer, int offset, int readLength) throws IOException {
+ // TODO: Reevaluate interruption in Input.
+ try {
+ return mInputReader.read(buffer, offset, readLength);
+ } catch (InterruptedException e) {
+ // TODO: Remove.
+ throw new RuntimeException();
+ }
+ }
+
+ @Override
+ public Uri getUri() {
+ return null;
+ }
+
+ @Override
+ public Map<String, List<String>> getResponseHeaders() {
+ return null;
+ }
+
+ @Override
+ public void close() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private final class ExtractorOutputAdapter implements ExtractorOutput {
+
+ private final SparseArray<TrackOutput> mTrackOutputAdapters;
+ private boolean mTracksEnded;
+
+ private ExtractorOutputAdapter() {
+ mTrackOutputAdapters = new SparseArray<>();
+ }
+
+ @Override
+ public TrackOutput track(int id, int type) {
+ TrackOutput trackOutput = mTrackOutputAdapters.get(id);
+ if (trackOutput == null) {
+ trackOutput = new TrackOutputAdapter(mTrackOutputAdapters.size());
+ mTrackOutputAdapters.put(id, trackOutput);
+ }
+ return trackOutput;
+ }
+
+ @Override
+ public void endTracks() {
+ mOutputConsumer.onTracksFound(mTrackOutputAdapters.size());
+ }
+
+ @Override
+ public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
+ mOutputConsumer.onSeekMap(new ExoToMediaParserSeekMapAdapter(exoplayerSeekMap));
+ }
+ }
+
+ private class TrackOutputAdapter implements TrackOutput {
+
+ private final int mTrackIndex;
+
+ private TrackOutputAdapter(int trackIndex) {
+ mTrackIndex = trackIndex;
+ }
+
+ @Override
+ public void format(Format format) {
+ mOutputConsumer.onFormat(mTrackIndex, toMediaFormat(format));
+ }
+
+ @Override
+ public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
+ throws IOException, InterruptedException {
+ mScratchExtractorInputAdapter.setExtractorInput(input, length);
+ long positionBeforeReading = mScratchExtractorInputAdapter.getPosition();
+ mOutputConsumer.onSampleData(mTrackIndex, mScratchExtractorInputAdapter);
+ return (int) (mScratchExtractorInputAdapter.getPosition() - positionBeforeReading);
+ }
+
+ @Override
+ public void sampleData(ParsableByteArray data, int length) {
+ mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
+ try {
+ mOutputConsumer.onSampleData(mTrackIndex, mScratchParsableByteArrayAdapter);
+ } catch (IOException | InterruptedException e) {
+ // Unexpected.
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void sampleMetadata(
+ long timeUs, int flags, int size, int offset, CryptoData encryptionData) {
+ mOutputConsumer.onSampleCompleted(
+ mTrackIndex, timeUs, flags, size, offset, toCryptoInfo(encryptionData));
+ }
+ }
+
+ private static final class ExtractorInputAdapter implements InputReader {
+
+ private ExtractorInput mExtractorInput;
+ private int mCurrentPosition;
+ private long mLength;
+
+ public void setExtractorInput(ExtractorInput extractorInput, long length) {
+ mExtractorInput = extractorInput;
+ mCurrentPosition = 0;
+ mLength = length;
+ }
+
+ // Input implementation.
+
+ @Override
+ public int read(byte[] buffer, int offset, int readLength)
+ throws IOException, InterruptedException {
+ int readBytes = mExtractorInput.read(buffer, offset, readLength);
+ mCurrentPosition += readBytes;
+ return readBytes;
+ }
+
+ @Override
+ public long getPosition() {
+ return mCurrentPosition;
+ }
+
+ @Override
+ public long getLength() {
+ return mLength - mCurrentPosition;
+ }
+ }
+
+ private static final class ParsableByteArrayAdapter implements InputReader {
+
+ private ParsableByteArray mByteArray;
+ private long mLength;
+ private int mCurrentPosition;
+
+ public void resetWithByteArray(ParsableByteArray byteArray, long length) {
+ mByteArray = byteArray;
+ mCurrentPosition = 0;
+ mLength = length;
+ }
+
+ // Input implementation.
+
+ @Override
+ public int read(byte[] buffer, int offset, int readLength) {
+ mByteArray.readBytes(buffer, offset, readLength);
+ mCurrentPosition += readLength;
+ return readLength;
+ }
+
+ @Override
+ public long getPosition() {
+ return mCurrentPosition;
+ }
+
+ @Override
+ public long getLength() {
+ return mLength - mCurrentPosition;
+ }
+ }
+
+ /** Creates extractor instances. */
+ private interface ExtractorFactory {
+
+ /** Returns a new extractor instance. */
+ Extractor createInstance();
+ }
+
+ private static class ExoToMediaParserSeekMapAdapter implements SeekMap {
+
+ private final com.google.android.exoplayer2.extractor.SeekMap mExoPlayerSeekMap;
+
+ private ExoToMediaParserSeekMapAdapter(
+ com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
+ mExoPlayerSeekMap = exoplayerSeekMap;
+ }
+
+ @Override
+ public boolean isSeekable() {
+ return mExoPlayerSeekMap.isSeekable();
+ }
+
+ @Override
+ public long getDurationUs() {
+ return mExoPlayerSeekMap.getDurationUs();
+ }
+
+ @Override
+ public Pair<SeekPoint, SeekPoint> getSeekPoints(long timeUs) {
+ SeekPoints seekPoints = mExoPlayerSeekMap.getSeekPoints(timeUs);
+ return new Pair<>(toSeekPoint(seekPoints.first), toSeekPoint(seekPoints.second));
+ }
+ }
+
+ // Private static methods.
+
+ private static MediaFormat toMediaFormat(Format format) {
+
+ // TODO: Add if (value != Format.NO_VALUE);
+
+ MediaFormat result = new MediaFormat();
+ result.setInteger(MediaFormat.KEY_BIT_RATE, format.bitrate);
+ result.setInteger(MediaFormat.KEY_CHANNEL_COUNT, format.channelCount);
+ if (format.colorInfo != null) {
+ result.setInteger(MediaFormat.KEY_COLOR_TRANSFER, format.colorInfo.colorTransfer);
+ result.setInteger(MediaFormat.KEY_COLOR_RANGE, format.colorInfo.colorRange);
+ result.setInteger(MediaFormat.KEY_COLOR_STANDARD, format.colorInfo.colorSpace);
+ if (format.colorInfo.hdrStaticInfo != null) {
+ result.setByteBuffer(
+ MediaFormat.KEY_HDR_STATIC_INFO,
+ ByteBuffer.wrap(format.colorInfo.hdrStaticInfo));
+ }
+ }
+ result.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
+ result.setFloat(MediaFormat.KEY_FRAME_RATE, format.frameRate);
+ result.setInteger(MediaFormat.KEY_WIDTH, format.width);
+ result.setInteger(MediaFormat.KEY_HEIGHT, format.height);
+ List<byte[]> initData = format.initializationData;
+ if (initData != null) {
+ for (int i = 0; i < initData.size(); i++) {
+ result.setByteBuffer("csd-" + i, ByteBuffer.wrap(initData.get(i)));
+ }
+ }
+ result.setString(MediaFormat.KEY_LANGUAGE, format.language);
+ result.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
+ result.setInteger(MediaFormat.KEY_PCM_ENCODING, format.pcmEncoding);
+ result.setInteger(MediaFormat.KEY_ROTATION, format.rotationDegrees);
+ result.setInteger(MediaFormat.KEY_SAMPLE_RATE, format.sampleRate);
+
+ int selectionFlags = format.selectionFlags;
+ // We avoid setting selection flags in the MediaFormat, unless explicitly signaled by the
+ // extractor.
+ if ((selectionFlags & C.SELECTION_FLAG_AUTOSELECT) != 0) {
+ result.setInteger(MediaFormat.KEY_IS_AUTOSELECT, 1);
+ }
+ if ((selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0) {
+ result.setInteger(MediaFormat.KEY_IS_DEFAULT, 1);
+ }
+ if ((selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
+ result.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, 1);
+ }
+
+ // LACK OF SUPPORT FOR:
+ // format.accessibilityChannel;
+ // format.codecs;
+ // format.containerMimeType;
+ // format.drmInitData;
+ // format.encoderDelay;
+ // format.encoderPadding;
+ // format.id;
+ // format.metadata;
+ // format.pixelWidthHeightRatio;
+ // format.roleFlags;
+ // format.stereoMode;
+ // format.subsampleOffsetUs;
+ return result;
+ }
+
+ private static int toFrameworkFlags(int flags) {
+ // TODO: Implement.
+ return 0;
+ }
+
+ private static MediaCodec.CryptoInfo toCryptoInfo(TrackOutput.CryptoData encryptionData) {
+ // TODO: Implement.
+ return null;
+ }
+
+ /** Returns a new {@link SeekPoint} equivalent to the given {@code exoPlayerSeekPoint}. */
+ private static SeekPoint toSeekPoint(
+ com.google.android.exoplayer2.extractor.SeekPoint exoPlayerSeekPoint) {
+ return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
+ }
+
+ private static void assertValidNames(@NonNull String[] names) {
+ for (String name : names) {
+ if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
+ throw new IllegalArgumentException(
+ "Invalid extractor name: "
+ + name
+ + ". Supported extractors are: "
+ + TextUtils.join(", ", EXTRACTOR_FACTORIES_BY_NAME.keySet())
+ + ".");
+ }
+ }
+ }
+
+ // Static initialization.
+
+ static {
+ // Using a LinkedHashMap to keep the insertion order when iterating over the keys.
+ LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
+ extractorFactoriesByName.put("exo.Ac3Extractor", Ac3Extractor::new);
+ extractorFactoriesByName.put("exo.Ac4Extractor", Ac4Extractor::new);
+ extractorFactoriesByName.put("exo.AdtsExtractor", AdtsExtractor::new);
+ extractorFactoriesByName.put("exo.AmrExtractor", AmrExtractor::new);
+ extractorFactoriesByName.put("exo.FlvExtractor", FlvExtractor::new);
+ extractorFactoriesByName.put("exo.FragmentedMp4Extractor", FragmentedMp4Extractor::new);
+ extractorFactoriesByName.put("exo.MatroskaExtractor", MatroskaExtractor::new);
+ extractorFactoriesByName.put("exo.Mp3Extractor", Mp3Extractor::new);
+ extractorFactoriesByName.put("exo.Mp4Extractor", Mp4Extractor::new);
+ extractorFactoriesByName.put("exo.OggExtractor", OggExtractor::new);
+ extractorFactoriesByName.put("exo.PsExtractor", PsExtractor::new);
+ extractorFactoriesByName.put("exo.TsExtractor", TsExtractor::new);
+ extractorFactoriesByName.put("exo.WavExtractor", WavExtractor::new);
+ EXTRACTOR_FACTORIES_BY_NAME = Collections.unmodifiableMap(extractorFactoriesByName);
}
}