AudioManager: Add call screening audio mode.
Add new audio mode MODE_CALL_SCREENING allowing call screening
to take place while other audio use cases are still active.
Also add API to indicate if the platform supports this audio mode.
Bug: 140384450
Test: make
Change-Id: I056f79580d9c7b4de5eabb6d8d8c917f39162bcd
diff --git a/api/current.txt b/api/current.txt
index f9a2957..81cf7cf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23500,6 +23500,7 @@
method @Deprecated public boolean isBluetoothA2dpOn();
method public boolean isBluetoothScoAvailableOffCall();
method public boolean isBluetoothScoOn();
+ method public boolean isCallScreeningModeSupported();
method public static boolean isHapticPlaybackSupported();
method public boolean isMicrophoneMute();
method public boolean isMusicActive();
@@ -23598,6 +23599,7 @@
field public static final int GET_DEVICES_ALL = 3; // 0x3
field public static final int GET_DEVICES_INPUTS = 1; // 0x1
field public static final int GET_DEVICES_OUTPUTS = 2; // 0x2
+ field public static final int MODE_CALL_SCREENING = 4; // 0x4
field public static final int MODE_CURRENT = -1; // 0xffffffff
field public static final int MODE_INVALID = -2; // 0xfffffffe
field public static final int MODE_IN_CALL = 2; // 0x2
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 541b937..01f9d0b0 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2264,6 +2264,12 @@
return jStatus;
}
+static jboolean
+android_media_AudioSystem_isCallScreeningModeSupported(JNIEnv *env, jobject thiz)
+{
+ return AudioSystem::isCallScreenModeSupported();
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -2343,6 +2349,7 @@
{"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy},
{"setRttEnabled", "(Z)I", (void *)android_media_AudioSystem_setRttEnabled},
{"setAudioHalPids", "([I)I", (void *)android_media_AudioSystem_setAudioHalPids},
+ {"isCallScreeningModeSupported", "()Z", (void *)android_media_AudioSystem_isCallScreeningModeSupported},
};
static const JNINativeMethod gEventHandlerMethods[] = {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9ad7f2a..d552491 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1,4 +1,5 @@
/*
+/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -1931,12 +1932,11 @@
* application when it places a phone call, as it will cause signals from the radio layer
* to feed the platform mixer.
*
- * @param mode the requested audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
- * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
+ * @param mode the requested audio mode.
* Informs the HAL about the current audio state so that
* it can route the audio appropriately.
*/
- public void setMode(int mode) {
+ public void setMode(@AudioMode int mode) {
final IAudioService service = getService();
try {
service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName());
@@ -1948,14 +1948,47 @@
/**
* Returns the current audio mode.
*
- * @return the current audio mode ({@link #MODE_NORMAL}, {@link #MODE_RINGTONE},
- * {@link #MODE_IN_CALL} or {@link #MODE_IN_COMMUNICATION}).
- * Returns the current current audio state from the HAL.
+ * @return the current audio mode.
*/
+ @AudioMode
public int getMode() {
final IAudioService service = getService();
try {
- return service.getMode();
+ int mode = service.getMode();
+ int sdk;
+ try {
+ sdk = getContext().getApplicationInfo().targetSdkVersion;
+ } catch (NullPointerException e) {
+ // some tests don't have a Context
+ sdk = Build.VERSION.SDK_INT;
+ }
+ if (mode == MODE_CALL_SCREENING && sdk <= Build.VERSION_CODES.Q) {
+ mode = MODE_IN_CALL;
+ }
+ return mode;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Indicates if the platform supports a special call screening and call monitoring mode.
+ * <p>
+ * When this mode is supported, it is possible to perform call screening and monitoring
+ * functions while other use cases like music or movie playback are active.
+ * <p>
+ * Use {@link #setMode(int)} with mode {@link #MODE_CALL_SCREENING} to place the platform in
+ * call screening mode.
+ * <p>
+ * If call screening mode is not supported, setting mode to
+ * MODE_CALL_SCREENING will be ignored and will not change current mode reported by
+ * {@link #getMode()}.
+ * @return true if call screening mode is supported, false otherwise.
+ */
+ public boolean isCallScreeningModeSupported() {
+ final IAudioService service = getService();
+ try {
+ return service.isCallScreeningModeSupported();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1989,6 +2022,22 @@
* In communication audio mode. An audio/video chat or VoIP call is established.
*/
public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION;
+ /**
+ * Call screening in progress. Call is connected and audio is accessible to call
+ * screening applications but other audio use cases are still possible.
+ */
+ public static final int MODE_CALL_SCREENING = AudioSystem.MODE_CALL_SCREENING;
+
+ /** @hide */
+ @IntDef(flag = false, prefix = "MODE_", value = {
+ MODE_NORMAL,
+ MODE_RINGTONE,
+ MODE_IN_CALL,
+ MODE_IN_COMMUNICATION,
+ MODE_CALL_SCREENING }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioMode {}
/* Routing bits for setRouting/getRouting API */
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 900572d..a3a8777 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -132,7 +132,8 @@
public static final int MODE_RINGTONE = 1;
public static final int MODE_IN_CALL = 2;
public static final int MODE_IN_COMMUNICATION = 3;
- public static final int NUM_MODES = 4;
+ public static final int MODE_CALL_SCREENING = 4;
+ public static final int NUM_MODES = 5;
public static String modeToString(int mode) {
switch (mode) {
@@ -142,6 +143,7 @@
case MODE_INVALID: return "MODE_INVALID";
case MODE_NORMAL: return "MODE_NORMAL";
case MODE_RINGTONE: return "MODE_RINGTONE";
+ case MODE_CALL_SCREENING: return "MODE_CALL_SCREENING";
default: return "unknown mode (" + mode + ")";
}
}
@@ -1130,6 +1132,11 @@
*/
public static native int setAudioHalPids(int[] pids);
+ /**
+ * @see AudioManager#isCallScreeningModeSupported()
+ */
+ public static native boolean isCallScreeningModeSupported();
+
// Items shared with audio service
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index fc05610..ef451ce 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -263,6 +263,8 @@
boolean hasHapticChannels(in Uri uri);
+ boolean isCallScreeningModeSupported();
+
// WARNING: read warning at top of file, new methods that need to be used by native
// code via IAudioManager.h need to be added to the top section.
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d09139c..b81f5e1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -772,6 +772,8 @@
readAndSetLowRamDevice();
+ mIsCallScreeningModeSupported = AudioSystem.isCallScreeningModeSupported();
+
// Call setRingerModeInt() to apply correct mute
// state on streams affected by ringer mode.
mRingerAndZenModeMutedStreams = 0;
@@ -965,6 +967,8 @@
readAndSetLowRamDevice();
+ mIsCallScreeningModeSupported = AudioSystem.isCallScreeningModeSupported();
+
// Restore device connection states, BT state
mDeviceBroker.onAudioServerDied();
@@ -3287,6 +3291,12 @@
return;
}
+ if (mode == AudioSystem.MODE_CALL_SCREENING && !mIsCallScreeningModeSupported) {
+ Log.w(TAG, "setMode(MODE_CALL_SCREENING) not permitted "
+ + "when call screening is not supported");
+ return;
+ }
+
if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
return;
}
@@ -3417,6 +3427,14 @@
return mMode;
}
+ /** cached value read from audiopolicy manager after initialization. */
+ private boolean mIsCallScreeningModeSupported = false;
+
+ /** @see AudioManager#isCallScreeningModeSupported() */
+ public boolean isCallScreeningModeSupported() {
+ return mIsCallScreeningModeSupported;
+ }
+
//==========================================================================================
// Sound Effects
//==========================================================================================
@@ -6149,6 +6167,7 @@
pw.print(" mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
pw.print(" mHdmiTvClient="); pw.println(mHdmiTvClient);
pw.print(" mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
+ pw.print(" mIsCallScreeningModeSupported="); pw.println(mIsCallScreeningModeSupported);
dumpAudioPolicies(pw);
mDynPolicyLogger.dump(pw);