Merge "Expose remote volume controller-related APIs"
This commit is contained in:
committed by
Android (Google) Code Review
commit
ed942b0cd9
229
api/module-lib-current.txt
Normal file
229
api/module-lib-current.txt
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
// Signature format: 2.0
|
||||||
|
package android.app {
|
||||||
|
|
||||||
|
public class ActivityManager {
|
||||||
|
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
|
||||||
|
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppOpsManager {
|
||||||
|
field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class HomeVisibilityListener {
|
||||||
|
ctor public HomeVisibilityListener();
|
||||||
|
method public abstract void onHomeVisibilityChanged(boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotificationManager {
|
||||||
|
method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle);
|
||||||
|
field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatusBarManager {
|
||||||
|
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.app.role {
|
||||||
|
|
||||||
|
public final class RoleManager {
|
||||||
|
method @Nullable public String getSmsRoleHolder(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.content.rollback {
|
||||||
|
|
||||||
|
public class RollbackManagerFrameworkInitializer {
|
||||||
|
method public static void initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.graphics {
|
||||||
|
|
||||||
|
public final class Compatibility {
|
||||||
|
method public static void setTargetSdkVersion(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class ImageDecoder implements java.lang.AutoCloseable {
|
||||||
|
method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @Nullable android.content.res.Resources);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.media {
|
||||||
|
|
||||||
|
public class AudioManager {
|
||||||
|
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
||||||
|
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
||||||
|
method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
|
||||||
|
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MediaMetadataRetriever implements java.lang.AutoCloseable {
|
||||||
|
field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
|
||||||
|
ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
|
||||||
|
method @Deprecated public int describeContents();
|
||||||
|
method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
|
||||||
|
method @Deprecated public java.util.List<T> getList();
|
||||||
|
method @Deprecated public void setInlineCountLimit(int);
|
||||||
|
method @Deprecated public void writeToParcel(android.os.Parcel, int);
|
||||||
|
field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.media.session {
|
||||||
|
|
||||||
|
public static final class MediaController.PlaybackInfo implements android.os.Parcelable {
|
||||||
|
ctor public MediaController.PlaybackInfo(int, int, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.media.AudioAttributes, @Nullable String);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class MediaSession {
|
||||||
|
field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class MediaSession.Token implements android.os.Parcelable {
|
||||||
|
method public int getUid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class MediaSessionManager {
|
||||||
|
method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, int, @Nullable android.os.Handler);
|
||||||
|
method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
|
||||||
|
method public boolean dispatchMediaKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
||||||
|
method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int);
|
||||||
|
method public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
||||||
|
method public void registerRemoteVolumeControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.RemoteVolumeControllerCallback);
|
||||||
|
method public void unregisterRemoteVolumeControllerCallback(@NonNull android.media.session.MediaSessionManager.RemoteVolumeControllerCallback);
|
||||||
|
field public static final int RESULT_MEDIA_KEY_HANDLED = 1; // 0x1
|
||||||
|
field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface MediaSessionManager.RemoteVolumeControllerCallback {
|
||||||
|
method public void onSessionChanged(@Nullable android.media.session.MediaSession.Token);
|
||||||
|
method public void onVolumeChanged(@NonNull android.media.session.MediaSession.Token, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class PlaybackState implements android.os.Parcelable {
|
||||||
|
method public boolean isActiveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.net {
|
||||||
|
|
||||||
|
public final class TetheringConstants {
|
||||||
|
field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
|
||||||
|
field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
|
||||||
|
field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
|
||||||
|
field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
|
||||||
|
field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TetheringManager {
|
||||||
|
ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
|
||||||
|
method public int getLastTetherError(@NonNull String);
|
||||||
|
method @NonNull public String[] getTetherableBluetoothRegexs();
|
||||||
|
method @NonNull public String[] getTetherableIfaces();
|
||||||
|
method @NonNull public String[] getTetherableUsbRegexs();
|
||||||
|
method @NonNull public String[] getTetherableWifiRegexs();
|
||||||
|
method @NonNull public String[] getTetheredIfaces();
|
||||||
|
method @NonNull public String[] getTetheringErroredIfaces();
|
||||||
|
method public boolean isTetheringSupported();
|
||||||
|
method public boolean isTetheringSupported(@NonNull String);
|
||||||
|
method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
|
||||||
|
method @Deprecated public int setUsbTethering(boolean);
|
||||||
|
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
|
||||||
|
method @Deprecated public int tether(@NonNull String);
|
||||||
|
method @Deprecated public int untether(@NonNull String);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface TetheringManager.TetheringEventCallback {
|
||||||
|
method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TetheringManager.TetheringInterfaceRegexps {
|
||||||
|
method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
|
||||||
|
method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
|
||||||
|
method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.os {
|
||||||
|
|
||||||
|
public class Binder implements android.os.IBinder {
|
||||||
|
method public final void markVintfStability();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Parcelable {
|
||||||
|
method public default int getStability();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatsFrameworkInitializer {
|
||||||
|
method public static void registerServiceWrappers();
|
||||||
|
method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatsServiceManager {
|
||||||
|
method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer();
|
||||||
|
method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer();
|
||||||
|
method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsdServiceRegisterer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StatsServiceManager.ServiceNotFoundException extends java.lang.Exception {
|
||||||
|
ctor public StatsServiceManager.ServiceNotFoundException(@NonNull String);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class StatsServiceManager.ServiceRegisterer {
|
||||||
|
method @Nullable public android.os.IBinder get();
|
||||||
|
method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.provider {
|
||||||
|
|
||||||
|
public final class DeviceConfig {
|
||||||
|
field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
|
||||||
|
field public static final String NAMESPACE_APP_STANDBY = "app_standby";
|
||||||
|
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.telephony {
|
||||||
|
|
||||||
|
public abstract class CellSignalStrength {
|
||||||
|
method public static int getNumSignalStrengthLevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TelephonyManager {
|
||||||
|
method @NonNull public static int[] getAllNetworkTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
package android.util {
|
||||||
|
|
||||||
|
public class AtomicFile {
|
||||||
|
ctor public AtomicFile(@NonNull java.io.File, @Nullable android.util.SystemConfigFileCommitEventLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Log {
|
||||||
|
method public static int logToRadioBuffer(int, @Nullable String, @Nullable String);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SystemConfigFileCommitEventLogger {
|
||||||
|
ctor public SystemConfigFileCommitEventLogger(@NonNull String);
|
||||||
|
method public void setStartTime(long);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -89,10 +89,17 @@ package android.media.session {
|
|||||||
method public boolean dispatchMediaKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
method public boolean dispatchMediaKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
||||||
method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int);
|
method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int);
|
||||||
method public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
method public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
|
||||||
|
method public void registerRemoteVolumeControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.RemoteVolumeControllerCallback);
|
||||||
|
method public void unregisterRemoteVolumeControllerCallback(@NonNull android.media.session.MediaSessionManager.RemoteVolumeControllerCallback);
|
||||||
field public static final int RESULT_MEDIA_KEY_HANDLED = 1; // 0x1
|
field public static final int RESULT_MEDIA_KEY_HANDLED = 1; // 0x1
|
||||||
field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
|
field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static interface MediaSessionManager.RemoteVolumeControllerCallback {
|
||||||
|
method public void onSessionChanged(@Nullable android.media.session.MediaSession.Token);
|
||||||
|
method public void onVolumeChanged(@NonNull android.media.session.MediaSession.Token, int);
|
||||||
|
}
|
||||||
|
|
||||||
public final class PlaybackState implements android.os.Parcelable {
|
public final class PlaybackState implements android.os.Parcelable {
|
||||||
method public boolean isActiveState();
|
method public boolean isActiveState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ import android.media.session.MediaSession;
|
|||||||
* TODO add in better support for multiple remote sessions.
|
* TODO add in better support for multiple remote sessions.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
oneway interface IRemoteVolumeController {
|
oneway interface IRemoteVolumeControllerCallback {
|
||||||
void remoteVolumeChanged(in MediaSession.Token sessionToken, int flags);
|
void onVolumeChanged(in MediaSession.Token sessionToken, int flags);
|
||||||
// sets the default session to use with the slider, replaces remoteSliderVisibility
|
// sets the default session to use with the slider, replaces remoteSliderVisibility
|
||||||
// on IVolumeController
|
// on IVolumeController
|
||||||
void updateRemoteController(in MediaSession.Token sessionToken);
|
void onSessionChanged(in MediaSession.Token sessionToken);
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ package android.media.session;
|
|||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
import android.media.IRemoteVolumeController;
|
import android.media.IRemoteVolumeControllerCallback;
|
||||||
import android.media.Session2Token;
|
import android.media.Session2Token;
|
||||||
import android.media.session.IActiveSessionsListener;
|
import android.media.session.IActiveSessionsListener;
|
||||||
import android.media.session.IOnMediaKeyEventDispatchedListener;
|
import android.media.session.IOnMediaKeyEventDispatchedListener;
|
||||||
@@ -57,8 +57,8 @@ interface ISessionManager {
|
|||||||
void addSession2TokensListener(in ISession2TokensListener listener, int userId);
|
void addSession2TokensListener(in ISession2TokensListener listener, int userId);
|
||||||
void removeSession2TokensListener(in ISession2TokensListener listener);
|
void removeSession2TokensListener(in ISession2TokensListener listener);
|
||||||
|
|
||||||
void registerRemoteVolumeController(in IRemoteVolumeController rvc);
|
void registerRemoteVolumeControllerCallback(in IRemoteVolumeControllerCallback rvc);
|
||||||
void unregisterRemoteVolumeController(in IRemoteVolumeController rvc);
|
void unregisterRemoteVolumeControllerCallback(in IRemoteVolumeControllerCallback rvc);
|
||||||
|
|
||||||
// For PhoneWindowManager to precheck media keys
|
// For PhoneWindowManager to precheck media keys
|
||||||
boolean isGlobalPriorityActive();
|
boolean isGlobalPriorityActive();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.IRemoteVolumeController;
|
import android.media.IRemoteVolumeControllerCallback;
|
||||||
import android.media.MediaFrameworkInitializer;
|
import android.media.MediaFrameworkInitializer;
|
||||||
import android.media.MediaSession2;
|
import android.media.MediaSession2;
|
||||||
import android.media.Session2Token;
|
import android.media.Session2Token;
|
||||||
@@ -88,6 +88,8 @@ public final class MediaSessionManager {
|
|||||||
private final OnMediaKeyEventSessionChangedListenerStub
|
private final OnMediaKeyEventSessionChangedListenerStub
|
||||||
mOnMediaKeyEventSessionChangedListenerStub =
|
mOnMediaKeyEventSessionChangedListenerStub =
|
||||||
new OnMediaKeyEventSessionChangedListenerStub();
|
new OnMediaKeyEventSessionChangedListenerStub();
|
||||||
|
private final RemoteVolumeControllerCallbackStub mRemoteVolumeControllerCallbackStub =
|
||||||
|
new RemoteVolumeControllerCallbackStub();
|
||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -106,6 +108,9 @@ public final class MediaSessionManager {
|
|||||||
private String mCurMediaKeyEventSessionPackage;
|
private String mCurMediaKeyEventSessionPackage;
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private MediaSession.Token mCurMediaKeyEventSession;
|
private MediaSession.Token mCurMediaKeyEventSession;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final Map<RemoteVolumeControllerCallback, Executor>
|
||||||
|
mRemoteVolumeControllerCallbacks = new ArrayMap<>();
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
|
private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
|
||||||
@@ -462,33 +467,62 @@ public final class MediaSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the remote volume controller to receive volume updates on.
|
* Set the remote volume controller callback to receive volume updates on.
|
||||||
* Only for use by System UI and Settings application.
|
* Only for use by System UI and Settings application.
|
||||||
*
|
*
|
||||||
* @param rvc The volume controller to receive updates on.
|
* @param callback The volume controller callback to receive updates on.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
try {
|
public void registerRemoteVolumeControllerCallback(
|
||||||
mService.registerRemoteVolumeController(rvc);
|
@NonNull @CallbackExecutor Executor executor,
|
||||||
} catch (RemoteException e) {
|
@NonNull RemoteVolumeControllerCallback callback) {
|
||||||
Log.e(TAG, "Error in registerRemoteVolumeController.", e);
|
Objects.requireNonNull(executor, "executor shouldn't be null");
|
||||||
|
Objects.requireNonNull(callback, "callback shouldn't be null");
|
||||||
|
boolean shouldRegisterCallback = false;
|
||||||
|
synchronized (mLock) {
|
||||||
|
int prevCallbackCount = mRemoteVolumeControllerCallbacks.size();
|
||||||
|
mRemoteVolumeControllerCallbacks.put(callback, executor);
|
||||||
|
if (prevCallbackCount == 0 && mRemoteVolumeControllerCallbacks.size() == 1) {
|
||||||
|
shouldRegisterCallback = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldRegisterCallback) {
|
||||||
|
try {
|
||||||
|
mService.registerRemoteVolumeControllerCallback(
|
||||||
|
mRemoteVolumeControllerCallbackStub);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Failed to register remote volume controller callback", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters the remote volume controller which was previously registered with
|
* Unregisters the remote volume controller callback which was previously registered with
|
||||||
* {@link #registerRemoteVolumeController(IRemoteVolumeController)}.
|
* {@link #registerRemoteVolumeControllerCallback(Executor, RemoteVolumeControllerCallback)}.
|
||||||
* Only for use by System UI and Settings application.
|
* Only for use by System UI and Settings application.
|
||||||
*
|
*
|
||||||
* @param rvc The volume controller which was registered.
|
* @param callback The volume controller callback to receive updates on.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
|
public void unregisterRemoteVolumeControllerCallback(
|
||||||
|
@NonNull RemoteVolumeControllerCallback callback) {
|
||||||
|
Objects.requireNonNull(callback, "callback shouldn't be null");
|
||||||
|
boolean shouldUnregisterCallback = false;
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mRemoteVolumeControllerCallbacks.remove(callback) != null
|
||||||
|
&& mRemoteVolumeControllerCallbacks.size() == 0) {
|
||||||
|
shouldUnregisterCallback = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
mService.unregisterRemoteVolumeController(rvc);
|
if (shouldUnregisterCallback) {
|
||||||
|
mService.unregisterRemoteVolumeControllerCallback(
|
||||||
|
mRemoteVolumeControllerCallbackStub);
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error in unregisterRemoteVolumeController.", e);
|
Log.e(TAG, "Failed to unregister remote volume controller callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,6 +1092,29 @@ public final class MediaSessionManager {
|
|||||||
@Nullable MediaSession.Token sessionToken);
|
@Nullable MediaSession.Token sessionToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to receive changes in the remote volume controller.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
|
public interface RemoteVolumeControllerCallback {
|
||||||
|
/**
|
||||||
|
* Called when the volume is changed.
|
||||||
|
*
|
||||||
|
* @param sessionToken the remote media session token
|
||||||
|
* @param flags any of the flags from {@link AudioManager}
|
||||||
|
*/
|
||||||
|
void onVolumeChanged(@NonNull MediaSession.Token sessionToken, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the session for the default remote controller is changed.
|
||||||
|
*
|
||||||
|
* @param sessionToken the remote media session token
|
||||||
|
*/
|
||||||
|
void onSessionChanged(@Nullable MediaSession.Token sessionToken);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information of a remote user of {@link MediaSession} or {@link MediaBrowserService}.
|
* Information of a remote user of {@link MediaSession} or {@link MediaBrowserService}.
|
||||||
* This can be used to decide whether the remote user is trusted app, and also differentiate
|
* This can be used to decide whether the remote user is trusted app, and also differentiate
|
||||||
@@ -1290,4 +1347,29 @@ public final class MediaSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class RemoteVolumeControllerCallbackStub
|
||||||
|
extends IRemoteVolumeControllerCallback.Stub {
|
||||||
|
@Override
|
||||||
|
public void onVolumeChanged(MediaSession.Token sessionToken, int flags) {
|
||||||
|
Map<RemoteVolumeControllerCallback, Executor> callbacks = new ArrayMap<>();
|
||||||
|
synchronized (mLock) {
|
||||||
|
callbacks.putAll(mRemoteVolumeControllerCallbacks);
|
||||||
|
}
|
||||||
|
for (Map.Entry<RemoteVolumeControllerCallback, Executor> e : callbacks.entrySet()) {
|
||||||
|
e.getValue().execute(() -> e.getKey().onVolumeChanged(sessionToken, flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSessionChanged(MediaSession.Token sessionToken) {
|
||||||
|
Map<RemoteVolumeControllerCallback, Executor> callbacks = new ArrayMap<>();
|
||||||
|
synchronized (mLock) {
|
||||||
|
callbacks.putAll(mRemoteVolumeControllerCallbacks);
|
||||||
|
}
|
||||||
|
for (Map.Entry<RemoteVolumeControllerCallback, Executor> e : callbacks.entrySet()) {
|
||||||
|
e.getValue().execute(() -> e.getKey().onSessionChanged(sessionToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settingslib.volume;
|
package com.android.settingslib.volume;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -23,20 +25,21 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.media.IRemoteVolumeController;
|
|
||||||
import android.media.MediaMetadata;
|
import android.media.MediaMetadata;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.media.session.MediaController.PlaybackInfo;
|
import android.media.session.MediaController.PlaybackInfo;
|
||||||
|
import android.media.session.MediaSession;
|
||||||
import android.media.session.MediaSession.QueueItem;
|
import android.media.session.MediaSession.QueueItem;
|
||||||
import android.media.session.MediaSession.Token;
|
import android.media.session.MediaSession.Token;
|
||||||
import android.media.session.MediaSessionManager;
|
import android.media.session.MediaSessionManager;
|
||||||
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
|
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
|
||||||
|
import android.media.session.MediaSessionManager.RemoteVolumeControllerCallback;
|
||||||
import android.media.session.PlaybackState;
|
import android.media.session.PlaybackState;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerExecutor;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -58,6 +61,7 @@ public class MediaSessions {
|
|||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final H mHandler;
|
private final H mHandler;
|
||||||
|
private final HandlerExecutor mHandlerExecutor;
|
||||||
private final MediaSessionManager mMgr;
|
private final MediaSessionManager mMgr;
|
||||||
private final Map<Token, MediaControllerRecord> mRecords = new HashMap<>();
|
private final Map<Token, MediaControllerRecord> mRecords = new HashMap<>();
|
||||||
private final Callbacks mCallbacks;
|
private final Callbacks mCallbacks;
|
||||||
@@ -67,6 +71,7 @@ public class MediaSessions {
|
|||||||
public MediaSessions(Context context, Looper looper, Callbacks callbacks) {
|
public MediaSessions(Context context, Looper looper, Callbacks callbacks) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mHandler = new H(looper);
|
mHandler = new H(looper);
|
||||||
|
mHandlerExecutor = new HandlerExecutor(mHandler);
|
||||||
mMgr = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
mMgr = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||||
mCallbacks = callbacks;
|
mCallbacks = callbacks;
|
||||||
}
|
}
|
||||||
@@ -95,7 +100,8 @@ public class MediaSessions {
|
|||||||
mMgr.addOnActiveSessionsChangedListener(mSessionsListener, null, mHandler);
|
mMgr.addOnActiveSessionsChangedListener(mSessionsListener, null, mHandler);
|
||||||
mInit = true;
|
mInit = true;
|
||||||
postUpdateSessions();
|
postUpdateSessions();
|
||||||
mMgr.registerRemoteVolumeController(mRvc);
|
mMgr.registerRemoteVolumeControllerCallback(mHandlerExecutor,
|
||||||
|
mRemoteVolumeControllerCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postUpdateSessions() {
|
protected void postUpdateSessions() {
|
||||||
@@ -110,7 +116,7 @@ public class MediaSessions {
|
|||||||
if (D.BUG) Log.d(TAG, "destroy");
|
if (D.BUG) Log.d(TAG, "destroy");
|
||||||
mInit = false;
|
mInit = false;
|
||||||
mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
|
mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
|
||||||
mMgr.unregisterRemoteVolumeController(mRvc);
|
mMgr.unregisterRemoteVolumeControllerCallback(mRemoteVolumeControllerCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -330,19 +336,19 @@ public class MediaSessions {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final IRemoteVolumeController mRvc = new IRemoteVolumeController.Stub() {
|
private final RemoteVolumeControllerCallback mRemoteVolumeControllerCallback =
|
||||||
@Override
|
new RemoteVolumeControllerCallback() {
|
||||||
public void remoteVolumeChanged(Token sessionToken, int flags)
|
@Override
|
||||||
throws RemoteException {
|
public void onVolumeChanged(@NonNull MediaSession.Token sessionToken,
|
||||||
mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0,
|
int flags) {
|
||||||
sessionToken).sendToTarget();
|
mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0,
|
||||||
}
|
sessionToken).sendToTarget();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateRemoteController(final Token sessionToken)
|
public void onSessionChanged(@Nullable MediaSession.Token sessionToken) {
|
||||||
throws RemoteException {
|
mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, sessionToken).sendToTarget();
|
||||||
mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, sessionToken).sendToTarget();
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private final class H extends Handler {
|
private final class H extends Handler {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import android.content.pm.UserInfo;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.AudioPlaybackConfiguration;
|
import android.media.AudioPlaybackConfiguration;
|
||||||
import android.media.AudioSystem;
|
import android.media.AudioSystem;
|
||||||
import android.media.IRemoteVolumeController;
|
import android.media.IRemoteVolumeControllerCallback;
|
||||||
import android.media.Session2Token;
|
import android.media.Session2Token;
|
||||||
import android.media.session.IActiveSessionsListener;
|
import android.media.session.IActiveSessionsListener;
|
||||||
import android.media.session.IOnMediaKeyEventDispatchedListener;
|
import android.media.session.IOnMediaKeyEventDispatchedListener;
|
||||||
@@ -146,7 +146,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
|
|
||||||
// Used to notify System UI and Settings when remote volume was changed.
|
// Used to notify System UI and Settings when remote volume was changed.
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
|
final RemoteCallbackList<IRemoteVolumeControllerCallback> mRemoteVolumeControllers =
|
||||||
new RemoteCallbackList<>();
|
new RemoteCallbackList<>();
|
||||||
|
|
||||||
private SessionPolicyProvider mCustomSessionPolicyProvider;
|
private SessionPolicyProvider mCustomSessionPolicyProvider;
|
||||||
@@ -309,8 +309,9 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
MediaSession.Token token = session.getSessionToken();
|
MediaSession.Token token = session.getSessionToken();
|
||||||
for (int i = size - 1; i >= 0; i--) {
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
try {
|
try {
|
||||||
IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
|
IRemoteVolumeControllerCallback cb =
|
||||||
cb.remoteVolumeChanged(token, flags);
|
mRemoteVolumeControllers.getBroadcastItem(i);
|
||||||
|
cb.onVolumeChanged(token, flags);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error sending volume change.", e);
|
Log.w(TAG, "Error sending volume change.", e);
|
||||||
}
|
}
|
||||||
@@ -715,8 +716,9 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
|
|
||||||
for (int i = size - 1; i >= 0; i--) {
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
try {
|
try {
|
||||||
IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
|
IRemoteVolumeControllerCallback cb =
|
||||||
cb.updateRemoteController(token);
|
mRemoteVolumeControllers.getBroadcastItem(i);
|
||||||
|
cb.onSessionChanged(token);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Error sending default remote volume.", e);
|
Log.w(TAG, "Error sending default remote volume.", e);
|
||||||
}
|
}
|
||||||
@@ -1843,7 +1845,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerRemoteVolumeController(IRemoteVolumeController rvc) {
|
public void registerRemoteVolumeControllerCallback(IRemoteVolumeControllerCallback rvc) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
@@ -1858,7 +1860,7 @@ public class MediaSessionService extends SystemService implements Monitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterRemoteVolumeController(IRemoteVolumeController rvc) {
|
public void unregisterRemoteVolumeControllerCallback(IRemoteVolumeControllerCallback rvc) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
|||||||
Reference in New Issue
Block a user