Merge "[Media ML] Add volume-related system APIs in AudioManager"

This commit is contained in:
Jin Seok Park
2020-09-09 01:51:08 +00:00
committed by Android (Google) Code Review
8 changed files with 219 additions and 65 deletions

View File

@@ -35,6 +35,9 @@ package android.graphics {
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
}

View File

@@ -6649,6 +6649,132 @@ public class AudioManager {
}
}
/**
* Adjusts the volume of the most relevant stream, or the given fallback
* stream.
* <p>
* This method should only be used by applications that replace the
* platform-wide management of audio settings or the main telephony
* application.
* <p>
* This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>This API checks if the caller has the necessary permissions based on the provided
* component name, uid, and pid values.
* See {@link #adjustSuggestedStreamVolume(int, int, int)}.
*
* @param suggestedStreamType The stream type that will be used if there
* isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is
* valid here.
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE},
* {@link #ADJUST_SAME}, {@link #ADJUST_MUTE},
* {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}.
* @param flags One or more flags.
* @param packageName the package name of client application
* @param uid the uid of client application
* @param pid the pid of client application
* @param targetSdkVersion the target sdk version of client application
* @see #adjustVolume(int, int)
* @see #adjustStreamVolume(int, int, int)
* @see #setStreamVolume(int, int, int)
* @see #isVolumeFixed()
*
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void adjustSuggestedStreamVolumeForUid(int suggestedStreamType, int direction, int flags,
@NonNull String packageName, int uid, int pid, int targetSdkVersion) {
try {
getService().adjustSuggestedStreamVolumeForUid(suggestedStreamType, direction, flags,
packageName, uid, pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Adjusts the volume of a particular stream by one step in a direction.
* <p>
* This method should only be used by applications that replace the platform-wide
* management of audio settings or the main telephony application.
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
* unless the app has been granted Do Not Disturb Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>This API checks if the caller has the necessary permissions based on the provided
* component name, uid, and pid values.
* See {@link #adjustStreamVolume(int, int, int)}.
*
* @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
* {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC},
* {@link #STREAM_ALARM} or {@link #STREAM_ACCESSIBILITY}.
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
* {@link #ADJUST_SAME}.
* @param flags One or more flags.
* @param packageName the package name of client application
* @param uid the uid of client application
* @param pid the pid of client application
* @param targetSdkVersion the target sdk version of client application
* @see #adjustVolume(int, int)
* @see #setStreamVolume(int, int, int)
* @throws SecurityException if the adjustment triggers a Do Not Disturb change
* and the caller is not granted notification policy access.
*
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
@NonNull String packageName, int uid, int pid, int targetSdkVersion) {
try {
getService().adjustStreamVolumeForUid(streamType, direction, flags, packageName, uid,
pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the volume index for a particular stream.
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
* the app has been granted Do Not Disturb Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>This API checks if the caller has the necessary permissions based on the provided
* component name, uid, and pid values.
* See {@link #setStreamVolume(int, int, int)}.
*
* @param streamType The stream whose volume index should be set.
* @param index The volume index to set. See
* {@link #getStreamMaxVolume(int)} for the largest valid value.
* @param flags One or more flags.
* @param packageName the package name of client application
* @param uid the uid of client application
* @param pid the pid of client application
* @param targetSdkVersion the target sdk version of client application
* @see #getStreamMaxVolume(int)
* @see #getStreamVolume(int)
* @see #isVolumeFixed()
* @throws SecurityException if the volume change triggers a Do Not Disturb change
* and the caller is not granted notification policy access.
*
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void setStreamVolumeForUid(int streamType, int index, int flags,
@NonNull String packageName, int uid, int pid, int targetSdkVersion) {
try {
getService().setStreamVolumeForUid(streamType, index, flags, packageName, uid, pid,
UserHandle.getUserHandleForUid(uid), targetSdkVersion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide
* TODO: make this a @SystemApi */
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)

View File

@@ -28,15 +28,6 @@ import com.android.server.LocalServices;
*/
public abstract class AudioManagerInternal {
public abstract void adjustSuggestedStreamVolumeForUid(int streamType, int direction,
int flags, String callingPackage, int uid, int pid);
public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid, int pid);
public abstract void setStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid, int pid);
public abstract void setRingerModeDelegate(RingerModeDelegate delegate);
public abstract int getRingerModeInternal();

View File

@@ -17,6 +17,7 @@
package android.media;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioFocusInfo;
@@ -41,6 +42,7 @@ import android.media.audiopolicy.AudioVolumeGroup;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.media.projection.IMediaProjection;
import android.net.Uri;
import android.os.UserHandle;
import android.view.KeyEvent;
/**
@@ -320,4 +322,16 @@ interface IAudioService {
oneway void unregisterCapturePresetDevicesRoleDispatcher(
ICapturePresetDevicesRoleDispatcher dispatcher);
oneway void adjustStreamVolumeForUid(int streamType, int direction, int flags,
in String packageName, int uid, int pid, in UserHandle userHandle,
int targetSdkVersion);
oneway void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
in String packageName, int uid, int pid, in UserHandle userHandle,
int targetSdkVersion);
oneway void setStreamVolumeForUid(int streamType, int direction, int flags,
in String packageName, int uid, int pid, in UserHandle userHandle,
int targetSdkVersion);
}

View File

@@ -35,6 +35,9 @@ package android.graphics {
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
}

View File

@@ -4186,6 +4186,62 @@ public class AudioService extends IAudioService.Stub
}
}
/** @see AudioManager#adjustSuggestedStreamVolumeForUid(int, int, int, String, int, int, int) */
@Override
public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
@NonNull String packageName, int uid, int pid, UserHandle userHandle,
int targetSdkVersion) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Should only be called from system process");
}
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
// direction and stream type swap here because the public
// adjustSuggested has a different order than the other methods.
adjustSuggestedStreamVolume(direction, streamType, flags, packageName, packageName, uid,
hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
/** @see AudioManager#adjustStreamVolumeForUid(int, int, int, String, int, int, int) */
@Override
public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
@NonNull String packageName, int uid, int pid, UserHandle userHandle,
int targetSdkVersion) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Should only be called from system process");
}
if (direction != AudioManager.ADJUST_SAME) {
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType,
direction/*val1*/, flags/*val2*/,
new StringBuilder(packageName).append(" uid:").append(uid)
.toString()));
}
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
adjustStreamVolume(streamType, direction, flags, packageName, packageName, uid,
hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
/** @see AudioManager#setStreamVolumeForUid(int, int, int, String, int, int, int) */
@Override
public void setStreamVolumeForUid(int streamType, int index, int flags,
@NonNull String packageName, int uid, int pid, UserHandle userHandle,
int targetSdkVersion) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Should only be called from system process");
}
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
setStreamVolume(streamType, index, flags, packageName, packageName, uid,
hasModifyAudioSettings);
}
//==========================================================================================
// Sound Effects
//==========================================================================================
@@ -8070,43 +8126,6 @@ public class AudioService extends IAudioService.Stub
}
}
@Override
public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid, int pid) {
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
// direction and stream type swap here because the public
// adjustSuggested has a different order than the other methods.
adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
@Override
public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid, int pid) {
if (direction != AudioManager.ADJUST_SAME) {
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType,
direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
.append(" uid:").append(uid).toString()));
}
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
adjustStreamVolume(streamType, direction, flags, callingPackage,
callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
@Override
public void setStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid, int pid) {
final boolean hasModifyAudioSettings =
mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
== PackageManager.PERMISSION_GRANTED;
setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid,
hasModifyAudioSettings);
}
@Override
public int getRingerModeInternal() {
return AudioService.this.getRingerModeInternal();

View File

@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.MediaMetadata;
import android.media.Rating;
@@ -53,8 +52,6 @@ import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
import com.android.server.LocalServices;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -144,7 +141,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
// Volume handling fields
private AudioAttributes mAudioAttrs;
private AudioManager mAudioManager;
private AudioManagerInternal mAudioManagerInternal;
private int mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL;
private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
private int mMaxVolume = 0;
@@ -179,7 +175,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
mContext = mService.getContext();
mHandler = new MessageHandler(handlerLooper);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = DEFAULT_ATTRIBUTES;
mPolicies = policies;
@@ -328,8 +323,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
@Override
public void run() {
try {
mAudioManagerInternal.setStreamVolumeForUid(stream, volumeValue, flags,
opPackageName, uid, pid);
mAudioManager.setStreamVolumeForUid(stream, volumeValue, flags,
opPackageName, uid, pid,
mContext.getApplicationInfo().targetSdkVersion);
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Cannot set volume: stream=" + stream + ", value=" + volumeValue
+ ", flags=" + flags, e);
@@ -518,16 +514,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
try {
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream,
direction, flags, opPackageName, uid, pid);
mAudioManager.adjustSuggestedStreamVolumeForUid(stream,
direction, flags, opPackageName, uid, pid,
mContext.getApplicationInfo().targetSdkVersion);
} else {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
mAudioManager.adjustSuggestedStreamVolumeForUid(
AudioManager.USE_DEFAULT_STREAM_TYPE, direction,
flags | previousFlagPlaySound, opPackageName, uid, pid);
flags | previousFlagPlaySound, opPackageName, uid, pid,
mContext.getApplicationInfo().targetSdkVersion);
}
} else {
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
opPackageName, uid, pid);
mAudioManager.adjustStreamVolumeForUid(stream, direction, flags,
opPackageName, uid, pid,
mContext.getApplicationInfo().targetSdkVersion);
}
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream="

View File

@@ -42,7 +42,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
import android.media.IRemoteVolumeController;
@@ -85,7 +84,6 @@ import android.view.ViewConfiguration;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
import com.android.server.Watchdog;
@@ -136,7 +134,7 @@ public class MediaSessionService extends SystemService implements Monitor {
new ArrayList<>();
private KeyguardManager mKeyguardManager;
private AudioManagerInternal mAudioManagerInternal;
private AudioManager mAudioManager;
private ContentResolver mContentResolver;
private boolean mHasFeatureLeanback;
@@ -162,6 +160,7 @@ public class MediaSessionService extends SystemService implements Monitor {
PowerManager pm = mContext.getSystemService(PowerManager.class);
mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
mNotificationManager = mContext.getSystemService(NotificationManager.class);
mAudioManager = mContext.getSystemService(AudioManager.class);
}
@Override
@@ -169,7 +168,6 @@ public class MediaSessionService extends SystemService implements Monitor {
publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
Watchdog.getInstance().addMonitor(this);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext);
mAudioPlayerStateMonitor.registerListener(
(config, isRemoved) -> {
@@ -2057,8 +2055,9 @@ public class MediaSessionService extends SystemService implements Monitor {
callingPid = pid;
}
try {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
direction, flags, callingOpPackageName, callingUid, callingPid);
mAudioManager.adjustSuggestedStreamVolumeForUid(suggestedStream,
direction, flags, callingOpPackageName, callingUid, callingPid,
getContext().getApplicationInfo().targetSdkVersion);
} catch (SecurityException | IllegalArgumentException e) {
Log.e(TAG, "Cannot adjust volume: direction=" + direction
+ ", suggestedStream=" + suggestedStream + ", flags=" + flags