Merge "CSD: expose TestApi methods to test the feature"

This commit is contained in:
Vlad Popa
2023-01-19 18:37:53 +00:00
committed by Android (Google) Code Review
6 changed files with 302 additions and 14 deletions

View File

@@ -1629,20 +1629,27 @@ package android.media {
public class AudioManager {
method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int abandonAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void forceComputeCsdOnAllDevices(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void forceUseFrameworkMel(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioRecord getCallDownlinkExtractionAudioRecord(@NonNull android.media.AudioFormat);
method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioTrack getCallUplinkInjectionAudioTrack(@NonNull android.media.AudioFormat);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public float getCsd();
method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int);
method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFadeOutDurationOnFocusLossMillis(@NonNull android.media.AudioAttributes);
method @Nullable public static android.media.AudioHalVersionInfo getHalVersion();
method public static final int[] getPublicStreamTypes();
method @NonNull public java.util.List<java.lang.Integer> getReportedSurroundFormats();
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public float getRs2Value();
method public int getStreamMinVolumeInt(int);
method @NonNull public java.util.Map<java.lang.Integer,java.lang.Boolean> getSurroundFormats();
method public boolean hasRegisteredDynamicPolicy();
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public boolean isCsdEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.QUERY_AUDIO_STATE}) public boolean isFullVolumeDevice();
method @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public boolean isPstnCallAudioInterceptable();
method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int requestAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String, int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void setCsd(float);
method public void setRampingRingerEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void setRs2Value(float);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
}

View File

@@ -6441,6 +6441,20 @@ public class AudioManager {
}
}
/**
* Returns the registered volume controller interface.
*
* @hide
*/
@Nullable
public IVolumeController getVolumeController() {
try {
return getService().getVolumeController();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Notify audio manager about volume controller visibility changes.
* Currently limited to SystemUI.
@@ -6503,6 +6517,106 @@ public class AudioManager {
}
}
/**
* @hide
* @return the RS2 value used for momentary exposure warnings
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public float getRs2Value() {
try {
return getService().getRs2Value();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Sets the RS2 value used for momentary exposure warnings
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void setRs2Value(float rs2Value) {
try {
getService().setRs2Value(rs2Value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* @return the current computed sound dose value
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public float getCsd() {
try {
return getService().getCsd();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Sets the computed sound dose value to {@code csd}
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void setCsd(float csd) {
try {
getService().setCsd(csd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Forces the computation of MEL values (used for CSD) on framework level. This will have the
* result of ignoring the MEL values computed on HAL level. Should only be used in testing
* since this can affect the certification of a device with EN50332-3 regulation.
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void forceUseFrameworkMel(boolean useFrameworkMel) {
try {
getService().forceUseFrameworkMel(useFrameworkMel);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Forces the computation of CSD on all output devices.
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
try {
getService().forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Returns whether CSD is enabled on this device.
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public boolean isCsdEnabled() {
try {
return getService().isCsdEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @hide
* Sound dose warning at every 100% of dose during integration window

View File

@@ -260,6 +260,8 @@ interface IAudioService {
void setVolumeController(in IVolumeController controller);
@nullable IVolumeController getVolumeController();
void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);
boolean isStreamAffectedByRingerMode(int streamType);
@@ -270,6 +272,27 @@ interface IAudioService {
void lowerVolumeToRs1(String callingPackage);
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
float getRs2Value();
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
oneway void setRs2Value(float rs2Value);
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
float getCsd();
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
oneway void setCsd(float csd);
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
oneway void forceUseFrameworkMel(boolean useFrameworkMel);
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
oneway void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices);
@EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
boolean isCsdEnabled();
int setHdmiSystemAudioSupported(boolean on);
boolean isHdmiSystemAudioSupported();

View File

@@ -646,6 +646,9 @@
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
<!-- Permission required for CTS test - SoundDoseHelperTest -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SYSTEM_SETTINGS" />
<!-- Permission required for CTS test - CtsAmbientContextDetectionServiceDeviceTest -->
<uses-permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" />

View File

@@ -908,9 +908,6 @@ public class AudioService extends IAudioService.Stub
private final SoundDoseHelper mSoundDoseHelper;
@GuardedBy("mSettingsLock")
private int mCurrentImeUid;
private final Object mSupportedSystemUsagesLock = new Object();
@GuardedBy("mSupportedSystemUsagesLock")
private @AttributeSystemUsage int[] mSupportedSystemUsages =
@@ -10110,6 +10107,55 @@ public class AudioService extends IAudioService.Stub
"com.android.server.audio", "AudioService");
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public float getRs2Value() {
super.getRs2Value_enforcePermission();
return mSoundDoseHelper.getRs2Value();
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void setRs2Value(float rs2Value) {
super.setRs2Value_enforcePermission();
mSoundDoseHelper.setRs2Value(rs2Value);
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public float getCsd() {
super.getCsd_enforcePermission();
return mSoundDoseHelper.getCsd();
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void setCsd(float csd) {
super.setCsd_enforcePermission();
mSoundDoseHelper.setCsd(csd);
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void forceUseFrameworkMel(boolean useFrameworkMel) {
super.forceUseFrameworkMel_enforcePermission();
mSoundDoseHelper.forceUseFrameworkMel(useFrameworkMel);
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
super.forceComputeCsdOnAllDevices_enforcePermission();
mSoundDoseHelper.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
public boolean isCsdEnabled() {
super.isCsdEnabled_enforcePermission();
return mSoundDoseHelper.isCsdEnabled();
}
//==========================================================================================
// Hdmi CEC:
// - System audio mode:
@@ -10461,7 +10507,6 @@ public class AudioService extends IAudioService.Stub
+ " FromRestrictions=" + mMicMuteFromRestrictions
+ " FromApi=" + mMicMuteFromApi
+ " from system=" + mMicMuteFromSystemCached);
pw.print(" mCurrentImeUid="); pw.println(mCurrentImeUid);
dumpAccessibilityServiceUids(pw);
dumpAssistantServicesUids(pw);
@@ -10595,6 +10640,15 @@ public class AudioService extends IAudioService.Stub
if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
}
@Override
@Nullable
public IVolumeController getVolumeController() {
enforceVolumeController("get the volume controller");
if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
return mVolumeController.getController();
}
@Override
public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
enforceVolumeController("notify about volume controller visibility");
@@ -10640,6 +10694,10 @@ public class AudioService extends IAudioService.Stub
mVisible = false;
}
public IVolumeController getController() {
return mController;
}
public void loadSettings(ContentResolver cr) {
mLongPressTimeout = mSettings.getSecureIntForUser(cr,
Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);

View File

@@ -53,6 +53,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
@@ -70,9 +71,6 @@ public class SoundDoseHelper {
/*package*/ static final String ACTION_CHECK_MUSIC_ACTIVE =
"com.android.server.audio.action.CHECK_MUSIC_ACTIVE";
/** Flag to enable/disable the sound dose computation. */
private static final boolean USE_CSD_FOR_SAFE_HEARING = false;
// mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
// It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
// or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
@@ -96,8 +94,6 @@ public class SoundDoseHelper {
private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
private static final int REQUEST_CODE_CHECK_MUSIC_ACTIVE = 1;
private static final float CUSTOM_RS2_VALUE = 90;
// timeouts for the CSD warnings, -1 means no timeout (dialog must be ack'd by user)
private static final int CSD_WARNING_TIMEOUT_MS_DOSE_1X = 7000;
private static final int CSD_WARNING_TIMEOUT_MS_DOSE_5X = 5000;
@@ -233,6 +229,94 @@ public class SoundDoseHelper {
initCsd();
}
float getRs2Value() {
if (!mEnableCsd) {
return 0.f;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
return mSoundDose.getOutputRs2();
} catch (RemoteException e) {
Log.e(TAG, "Exception while getting the RS2 exposure value", e);
return 0.f;
}
}
void setRs2Value(float rs2Value) {
if (!mEnableCsd) {
return;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
mSoundDose.setOutputRs2(rs2Value);
} catch (RemoteException e) {
Log.e(TAG, "Exception while setting the RS2 exposure value", e);
}
}
float getCsd() {
if (!mEnableCsd) {
return -1.f;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
return mSoundDose.getCsd();
} catch (RemoteException e) {
Log.e(TAG, "Exception while getting the CSD value", e);
return -1.f;
}
}
void setCsd(float csd) {
if (!mEnableCsd) {
return;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
final SoundDoseRecord record = new SoundDoseRecord();
record.timestamp = System.currentTimeMillis();
record.value = csd;
final SoundDoseRecord[] recordArray = new SoundDoseRecord[] { record };
mSoundDose.resetCsd(csd, recordArray);
} catch (RemoteException e) {
Log.e(TAG, "Exception while setting the CSD value", e);
}
}
void forceUseFrameworkMel(boolean useFrameworkMel) {
if (!mEnableCsd) {
return;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
mSoundDose.forceUseFrameworkMel(useFrameworkMel);
} catch (RemoteException e) {
Log.e(TAG, "Exception while forcing the internal MEL computation", e);
}
}
void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
if (!mEnableCsd) {
return;
}
Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
try {
mSoundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
} catch (RemoteException e) {
Log.e(TAG, "Exception while forcing CSD computation on all devices", e);
}
}
boolean isCsdEnabled() {
return mEnableCsd;
}
/*package*/ int safeMediaVolumeIndex(int device) {
if (!mSafeMediaVolumeDevices.contains(device)) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
@@ -293,7 +377,7 @@ public class SoundDoseHelper {
|| (AudioService.mStreamVolumeAlias[streamType] != AudioSystem.STREAM_MUSIC)
|| (!mSafeMediaVolumeDevices.contains(device))
|| (index <= safeMediaVolumeIndex(device))
|| USE_CSD_FOR_SAFE_HEARING;
|| mEnableCsd;
}
/*package*/ boolean willDisplayWarningAfterCheckVolume(int streamType, int index, int device,
@@ -329,7 +413,7 @@ public class SoundDoseHelper {
/*package*/ void scheduleMusicActiveCheck() {
synchronized (mSafeMediaVolumeStateLock) {
cancelMusicActiveCheck();
if (!USE_CSD_FOR_SAFE_HEARING) {
if (!mEnableCsd) {
mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
REQUEST_CODE_CHECK_MUSIC_ACTIVE,
new Intent(ACTION_CHECK_MUSIC_ACTIVE),
@@ -460,14 +544,13 @@ public class SoundDoseHelper {
private void initCsd() {
synchronized (mSafeMediaVolumeStateLock) {
if (USE_CSD_FOR_SAFE_HEARING) {
if (mEnableCsd) {
Log.v(TAG, "Initializing sound dose");
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
try {
if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
mSoundDose.setOutputRs2(CUSTOM_RS2_VALUE);
if (mCurrentCsd != 0.f) {
Log.d(TAG, "Resetting the saved sound dose value " + mCurrentCsd);
SoundDoseRecord[] records = mDoseRecords.toArray(
@@ -502,7 +585,7 @@ public class SoundDoseHelper {
// The persisted state is either "disabled" or "active": this is the state applied
// next time we boot and cannot be "inactive"
int persistedState;
if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !USE_CSD_FOR_SAFE_HEARING) {
if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !mEnableCsd) {
persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
// The state can already be "inactive" here if the user has forced it before
// the 30 seconds timeout for forced configuration. In this case we don't reset