diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl new file mode 100644 index 0000000000000..3d50d14e1b83f --- /dev/null +++ b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl @@ -0,0 +1,21 @@ +/** + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media; + +/** {@hide} */ +interface IMediaCommunicationService { +} + diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index 60dea079a36be..5773e4de3f4eb 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -38,6 +38,7 @@ java_library { static_libs: [ "exoplayer2-extractor", "mediatranscoding_aidl_interface-java", + "modules-utils-build", ], jarjar_rules: "jarjar_rules.txt", @@ -52,6 +53,7 @@ java_library { visibility: [ "//frameworks/av/apex:__subpackages__", "//frameworks/base", // For framework-all + "//frameworks/base/apex/media/service", ], } @@ -80,6 +82,7 @@ filegroup { "java/android/media/Session2CommandGroup.java", "java/android/media/Session2Link.java", "java/android/media/Session2Token.java", + "java/android/media/MediaCommunicationManager.java", ], path: "java", } diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt index 2543a9cad576f..8b9990f9e833d 100644 --- a/apex/media/framework/api/current.txt +++ b/apex/media/framework/api/current.txt @@ -28,6 +28,9 @@ package android.media { ctor public ApplicationMediaCapabilities.FormatNotFoundException(@NonNull String); } + public class MediaCommunicationManager { + } + public class MediaController2 implements java.lang.AutoCloseable { method public void cancelSessionCommand(@NonNull Object); method public void close(); diff --git a/apex/media/framework/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt index d89d9d3343d11..eb71fddc05cb8 100644 --- a/apex/media/framework/jarjar_rules.txt +++ b/apex/media/framework/jarjar_rules.txt @@ -1 +1,2 @@ +rule com.android.modules.utils.** android.media.internal.utils.@1 rule com.google.android.exoplayer2.** android.media.internal.exo.@1 diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java new file mode 100644 index 0000000000000..b8065ef8c597e --- /dev/null +++ b/apex/media/framework/java/android/media/MediaCommunicationManager.java @@ -0,0 +1,49 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media; + +import android.annotation.NonNull; +import android.annotation.SystemService; +import android.content.Context; + +import com.android.modules.utils.build.SdkLevel; + +/** + * Provides support for interacting with {@link android.media.MediaSession2 MediaSession2s} + * that applications have published to express their ongoing media playback state. + */ +// TODO: Add notifySession2Created() and sendMessage(). +@SystemService(Context.MEDIA_COMMUNICATION_SERVICE) +public class MediaCommunicationManager { + private static final String TAG = "MediaCommunicationManager"; + + private final Context mContext; + private final IMediaCommunicationService mService; + + /** + * @hide + */ + public MediaCommunicationManager(@NonNull Context context) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException("Android version must be S or greater."); + } + mContext = context; + mService = IMediaCommunicationService.Stub.asInterface( + MediaFrameworkInitializer.getMediaServiceManager() + .getMediaCommunicationServiceRegisterer() + .get()); + } +} diff --git a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java index 813ad7b439329..93328355026e4 100644 --- a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java +++ b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java @@ -19,10 +19,11 @@ package android.media; import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.SystemApi.Client; -import android.media.MediaTranscodeManager; import android.app.SystemServiceRegistry; import android.content.Context; +import com.android.modules.utils.build.SdkLevel; + /** * Class for performing registration for all media services on com.android.media apex. * @@ -74,5 +75,12 @@ public class MediaFrameworkInitializer { MediaTranscodeManager.class, context -> new MediaTranscodeManager(context) ); + if (SdkLevel.isAtLeastS()) { + SystemServiceRegistry.registerContextAwareService( + Context.MEDIA_COMMUNICATION_SERVICE, + MediaCommunicationManager.class, + context -> new MediaCommunicationManager(context) + ); + } } } diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp new file mode 100644 index 0000000000000..5b24cfa4219b7 --- /dev/null +++ b/apex/media/service/Android.bp @@ -0,0 +1,41 @@ +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +filegroup { + name: "service-media-s-sources", + srcs: [ + "java/**/*.java", + ], + path: "java", + visibility: ["//frameworks/base/services"], // TODO(b/177640454): Should be private. +} + +java_sdk_library { + name: "service-media-s", + permitted_packages: [ + "com.android.server.media", + ], + defaults: ["framework-system-server-module-defaults"], + srcs: [ + ":service-media-s-sources", + ], + libs: [ + "updatable-media", + ], + sdk_version: "system_server_current", + min_sdk_version: "29", // TODO: We may need to bump this at some point. + apex_available: [ + "com.android.media", + ], +} + diff --git a/apex/media/service/api/current.txt b/apex/media/service/api/current.txt new file mode 100644 index 0000000000000..d802177e249b3 --- /dev/null +++ b/apex/media/service/api/current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/removed.txt b/apex/media/service/api/removed.txt new file mode 100644 index 0000000000000..d802177e249b3 --- /dev/null +++ b/apex/media/service/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/system-server-current.txt b/apex/media/service/api/system-server-current.txt new file mode 100644 index 0000000000000..d802177e249b3 --- /dev/null +++ b/apex/media/service/api/system-server-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/system-server-removed.txt b/apex/media/service/api/system-server-removed.txt new file mode 100644 index 0000000000000..d802177e249b3 --- /dev/null +++ b/apex/media/service/api/system-server-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java new file mode 100644 index 0000000000000..0468fdf30ba87 --- /dev/null +++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.media; + +import android.content.Context; +import android.media.IMediaCommunicationService; + +import com.android.server.SystemService; + +/** + * A system service that managers {@link android.media.MediaSession2} creations + * and their ongoing media playback state. + * @hide + */ +public class MediaCommunicationService extends SystemService { + + public MediaCommunicationService(Context context) { + super(context); + } + + @Override + public void onStart() { + publishBinderService(Context.MEDIA_COMMUNICATION_SERVICE, new Stub()); + } + + private class Stub extends IMediaCommunicationService.Stub { + } +} diff --git a/core/api/current.txt b/core/api/current.txt index b49e7247708c1..c4c522950e1b3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10374,6 +10374,7 @@ package android.content { field public static final String LAUNCHER_APPS_SERVICE = "launcherapps"; field public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final String LOCATION_SERVICE = "location"; + field public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; field public static final String MEDIA_METRICS_SERVICE = "media_metrics"; field public static final String MEDIA_PROJECTION_SERVICE = "media_projection"; field public static final String MEDIA_ROUTER_SERVICE = "media_router"; diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 2b9f1712bd879..0f49dc5800610 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -103,6 +103,7 @@ package android.media { } public class MediaServiceManager { + method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaCommunicationServiceRegisterer(); method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaSessionServiceRegisterer(); method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaTranscodingServiceRegisterer(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6a2329e5235f5..125b5ff625b2e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4370,6 +4370,16 @@ public abstract class Context { */ public static final String BIOMETRIC_SERVICE = "biometric"; + /** + * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.media.MediaCommunicationManager} + * for managing {@link android.media.MediaSession2}. + * + * @see #getSystemService(String) + * @see android.media.MediaCommunicationManager + */ + public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; + /** * Use with {@link #getSystemService} to retrieve a * {@link android.media.MediaRouter} for controlling and managing diff --git a/media/java/android/media/MediaServiceManager.java b/media/java/android/media/MediaServiceManager.java index 96bff4f926684..b899559d2e50a 100644 --- a/media/java/android/media/MediaServiceManager.java +++ b/media/java/android/media/MediaServiceManager.java @@ -33,6 +33,7 @@ import android.os.ServiceManager; public class MediaServiceManager { private static final String MEDIA_SESSION_SERVICE = "media_session"; private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding"; + private static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; /** * @hide @@ -79,4 +80,12 @@ public class MediaServiceManager { public ServiceRegisterer getMediaTranscodingServiceRegisterer() { return new ServiceRegisterer(MEDIA_TRANSCODING_SERVICE); } + + /** + * Returns {@link ServiceRegisterer} for MEDIA_COMMUNICATION_SERVICE. + */ + @NonNull + public ServiceRegisterer getMediaCommunicationServiceRegisterer() { + return new ServiceRegisterer(MEDIA_COMMUNICATION_SERVICE); + } } diff --git a/services/Android.bp b/services/Android.bp index f6bb72a46b876..1970b7d7b0dd3 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -36,6 +36,7 @@ filegroup { ":services.usb-sources", ":services.voiceinteraction-sources", ":services.wifi-sources", + ":service-media-s-sources", // TODO (b/177640454) ":service-permission-sources", ":service-statsd-sources", ], diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 544eedf99c9e4..05d6e5593f174 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -359,6 +359,9 @@ public final class SystemServer implements Dumpable { "com.android.server.ConnectivityServiceInitializer"; private static final String IP_CONNECTIVITY_METRICS_CLASS = "com.android.server.connectivity.IpConnectivityMetrics"; + private static final String MEDIA_COMMUNICATION_SERVICE_CLASS = + "com.android.server.media.MediaCommunicationService"; + private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService"; private static final String GAME_MANAGER_SERVICE_CLASS = "com.android.server.graphics.GameManagerService$Lifecycle"; @@ -2528,6 +2531,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS); t.traceEnd(); + t.traceBegin("StartMediaCommunicationService"); + mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS); + t.traceEnd(); + ConcurrentUtils.waitForFutureNoInterrupt(mBlobStoreServiceStart, START_BLOB_STORE_SERVICE);