From cf47bdd8885c1436156b9a6f19a4c8c81eb71af5 Mon Sep 17 00:00:00 2001 From: Nick Moukhine Date: Wed, 19 Aug 2020 16:29:18 +0200 Subject: [PATCH] Add system service for music recognition. The client submits a RecognitionRequest via MusicRecognitionManager. System server opens an audio stream based on the request and sends it to a MusicRecognitionService (which is exposed by a system app). The result is passed back through system server to the original caller. Test: tracked in b/169662646 Bug: 169403302 Change-Id: I4c7fd9d9d72ddd5678867fd037cab6198bff2c2d --- api/system-current.txt | 54 ++++ api/test-current.txt | 51 +++ .../android/app/SystemServiceRegistry.java | 13 + core/java/android/content/Context.java | 8 + core/res/AndroidManifest.xml | 13 + core/res/res/values/config.xml | 2 + core/res/res/values/symbols.xml | 1 + .../IMusicRecognitionManager.aidl | 14 + .../IMusicRecognitionManagerCallback.aidl | 15 + .../IMusicRecognitionService.aidl | 18 ++ .../IMusicRecognitionServiceCallback.aidl | 15 + .../MusicRecognitionManager.java | 186 +++++++++++ .../MusicRecognitionService.java | 140 ++++++++ .../musicrecognition/RecognitionRequest.aidl | 18 ++ .../musicrecognition/RecognitionRequest.java | 175 ++++++++++ non-updatable-api/system-current.txt | 54 ++++ services/Android.bp | 2 + .../java/com/android/server/SystemServer.java | 13 + services/musicrecognition/Android.bp | 13 + ...MusicRecognitionManagerPerUserService.java | 300 ++++++++++++++++++ .../MusicRecognitionManagerService.java | 116 +++++++ .../RemoteMusicRecognitionService.java | 84 +++++ 22 files changed, 1305 insertions(+) create mode 100644 media/java/android/media/musicrecognition/IMusicRecognitionManager.aidl create mode 100644 media/java/android/media/musicrecognition/IMusicRecognitionManagerCallback.aidl create mode 100644 media/java/android/media/musicrecognition/IMusicRecognitionService.aidl create mode 100644 media/java/android/media/musicrecognition/IMusicRecognitionServiceCallback.aidl create mode 100644 media/java/android/media/musicrecognition/MusicRecognitionManager.java create mode 100644 media/java/android/media/musicrecognition/MusicRecognitionService.java create mode 100644 media/java/android/media/musicrecognition/RecognitionRequest.aidl create mode 100644 media/java/android/media/musicrecognition/RecognitionRequest.java create mode 100644 services/musicrecognition/Android.bp create mode 100644 services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java create mode 100644 services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java create mode 100644 services/musicrecognition/java/com/android/server/musicrecognition/RemoteMusicRecognitionService.java diff --git a/api/system-current.txt b/api/system-current.txt index 8009d0370dd8d..25d5b598973f7 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -38,6 +38,7 @@ package android { field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE"; field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; + field public static final String BIND_MUSIC_RECOGNITION_SERVICE = "android.permission.BIND_MUSIC_RECOGNITION_SERVICE"; field public static final String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; field public static final String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"; field public static final String BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE = "android.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE"; @@ -119,6 +120,7 @@ package android { field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING"; field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION"; field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; + field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION"; field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"; field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; @@ -4528,6 +4530,58 @@ package android.media.audiopolicy { } +package android.media.musicrecognition { + + public class MusicRecognitionManager { + method @RequiresPermission(android.Manifest.permission.MANAGE_MUSIC_RECOGNITION) public void beginStreamingSearch(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.musicrecognition.MusicRecognitionManager.RecognitionCallback); + field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7 + field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1 + field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2 + field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5 + field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3 + field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6 + field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff + } + + public static interface MusicRecognitionManager.RecognitionCallback { + method public void onAudioStreamClosed(); + method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int); + method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle); + } + + public abstract class MusicRecognitionService extends android.app.Service { + ctor public MusicRecognitionService(); + method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback); + } + + public static interface MusicRecognitionService.Callback { + method public void onRecognitionFailed(int); + method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle); + } + + public final class RecognitionRequest implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.media.AudioAttributes getAudioAttributes(); + method @NonNull public android.media.AudioFormat getAudioFormat(); + method public int getCaptureSession(); + method public int getIgnoreBeginningFrames(); + method public int getMaxAudioLengthSeconds(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class RecognitionRequest.Builder { + ctor public RecognitionRequest.Builder(); + method @NonNull public android.media.musicrecognition.RecognitionRequest build(); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int); + } + +} + package android.media.session { public final class MediaSessionManager { diff --git a/api/test-current.txt b/api/test-current.txt index af70562839bae..0488bc7a30889 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2006,6 +2006,57 @@ package android.media.audiopolicy { } +package android.media.musicrecognition { + + public class MusicRecognitionManager { + field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7 + field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1 + field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2 + field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5 + field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3 + field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6 + field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff + } + + public static interface MusicRecognitionManager.RecognitionCallback { + method public void onAudioStreamClosed(); + method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int); + method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle); + } + + public abstract class MusicRecognitionService extends android.app.Service { + ctor public MusicRecognitionService(); + method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback); + } + + public static interface MusicRecognitionService.Callback { + method public void onRecognitionFailed(int); + method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle); + } + + public final class RecognitionRequest implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.media.AudioAttributes getAudioAttributes(); + method @NonNull public android.media.AudioFormat getAudioFormat(); + method public int getCaptureSession(); + method public int getIgnoreBeginningFrames(); + method public int getMaxAudioLengthSeconds(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class RecognitionRequest.Builder { + ctor public RecognitionRequest.Builder(); + method @NonNull public android.media.musicrecognition.RecognitionRequest build(); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int); + method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int); + } + +} + package android.media.tv { public final class TvInputManager { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 3b11b0d80da5d..9ddc66f955912 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -106,6 +106,8 @@ import android.media.MediaRouter; import android.media.MediaTranscodeManager; import android.media.midi.IMidiManager; import android.media.midi.MidiManager; +import android.media.musicrecognition.IMusicRecognitionManager; +import android.media.musicrecognition.MusicRecognitionManager; import android.media.projection.MediaProjectionManager; import android.media.soundtrigger.SoundTriggerManager; import android.media.tv.ITvInputManager; @@ -1118,6 +1120,17 @@ public final class SystemServiceRegistry { return new AutofillManager(ctx.getOuterContext(), service); }}); + registerService(Context.MUSIC_RECOGNITION_SERVICE, MusicRecognitionManager.class, + new CachedServiceFetcher() { + @Override + public MusicRecognitionManager createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService( + Context.MUSIC_RECOGNITION_SERVICE); + return new MusicRecognitionManager( + IMusicRecognitionManager.Stub.asInterface(b)); + } + }); + registerService(Context.CONTENT_CAPTURE_MANAGER_SERVICE, ContentCaptureManager.class, new CachedServiceFetcher() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 98f78878ec153..e1c09d9c6aeba 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4480,6 +4480,14 @@ public abstract class Context { */ public static final String SOUND_TRIGGER_MIDDLEWARE_SERVICE = "soundtrigger_middleware"; + /** + * Used to access {@link MusicRecognitionManagerService}. + * + * @hide + * @see #getSystemService(String) + */ + public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition"; + /** * Official published name of the (internal) permission service. * diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cdcb24b6a2475..aab9fa7b44a41 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3442,6 +3442,14 @@ + + + + + + +