summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjiabin <jiabin@google.com>2021-07-01 16:30:50 -0700
committerjiabin <jiabin@google.com>2021-07-02 10:05:07 -0700
commitcfcf10324a1fbb2fe5d24ace2f67c6244e4d6f61 (patch)
tree4d7abf00f258a2cfa2e8d20a647b4034d0b47dec
parent35929095bdb6ef8ba48312821e75afae9437238b (diff)
Add context in AudioManager.hasHapticChannels.
A context will be required for resolving a Uri. Using the context in AudioService may not always work and it may cause not oneway binder call issue. In that case, using the context in RingtoneManager could help. In AudioManager, caching a static context so that it can be used when there is not context provided. Test: atest RingtoneManagerTest Bug: 187842281 Change-Id: Ia2f514cb8f821926cf3d353cf912a44aeb584ab6
-rw-r--r--media/java/android/media/AudioManager.java52
-rw-r--r--media/java/android/media/Ringtone.java2
-rw-r--r--media/java/android/media/RingtoneManager.java9
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java20
4 files changed, 57 insertions, 26 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b7ea14ecd5d6..09ebb40e7ad7 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -103,6 +103,8 @@ public class AudioManager {
private static final AudioVolumeGroupChangeHandler sAudioAudioVolumeGroupChangedHandler =
new AudioVolumeGroupChangeHandler();
+ private static Context sContext;
+
/**
* Broadcast intent, a hint for applications that audio is about to become
* 'noisy' due to a change in audio outputs. For example, this intent may
@@ -798,6 +800,7 @@ public class AudioManager {
} else {
mOriginalContext = context;
}
+ sContext = context;
}
@UnsupportedAppUsage
@@ -7220,15 +7223,56 @@ public class AudioManager {
/**
* Return if an asset contains haptic channels or not.
+ *
+ * @param context the {@link Context} to resolve the uri.
* @param uri the {@link Uri} of the asset.
* @return true if the assert contains haptic channels.
* @hide
*/
- public static boolean hasHapticChannels(Uri uri) {
+ public static boolean hasHapticChannelsImpl(@NonNull Context context, @NonNull Uri uri) {
+ MediaExtractor extractor = new MediaExtractor();
try {
- return getService().hasHapticChannels(uri);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ extractor.setDataSource(context, uri, null);
+ for (int i = 0; i < extractor.getTrackCount(); i++) {
+ MediaFormat format = extractor.getTrackFormat(i);
+ if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT)
+ && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) {
+ return true;
+ }
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "hasHapticChannels failure:" + e);
+ }
+ return false;
+ }
+
+ /**
+ * Return if an asset contains haptic channels or not.
+ *
+ * @param context the {@link Context} to resolve the uri.
+ * @param uri the {@link Uri} of the asset.
+ * @return true if the assert contains haptic channels.
+ * @hide
+ */
+ public static boolean hasHapticChannels(@Nullable Context context, @NonNull Uri uri) {
+ Objects.requireNonNull(uri);
+ if (context != null) {
+ return hasHapticChannelsImpl(context, uri);
+ } else if (sContext != null) {
+ if (DEBUG) {
+ Log.d(TAG, "Try to use static context to query if having haptic channels");
+ }
+ return hasHapticChannelsImpl(sContext, uri);
+ } else {
+ // Try with audio service context, this may fail to get correct result.
+ if (DEBUG) {
+ Log.d(TAG, "Try to use audio service context to query if having haptic channels");
+ }
+ try {
+ return getService().hasHapticChannels(uri);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index f8297bc93b72..3cf03417334b 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -407,7 +407,7 @@ public class Ringtone {
if (mLocalPlayer != null) {
// Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
// (typically because ringer mode is vibrate).
- boolean isHapticOnly = AudioManager.hasHapticChannels(mUri)
+ boolean isHapticOnly = AudioManager.hasHapticChannels(mContext, mUri)
&& !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0;
if (isHapticOnly || mAudioManager.getStreamVolume(
AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) {
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index be6ff1baadd6..4ec79b7e085a 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -1082,18 +1082,21 @@ public class RingtoneManager {
* @return true if the ringtone contains haptic channels.
*/
public boolean hasHapticChannels(int position) {
- return hasHapticChannels(getRingtoneUri(position));
+ return AudioManager.hasHapticChannels(mContext, getRingtoneUri(position));
}
/**
* Returns if the {@link Ringtone} from a given sound URI contains
- * haptic channels or not.
+ * haptic channels or not. As this function doesn't has a context
+ * to resolve the uri, the result may be wrong if the uri cannot be
+ * resolved correctly.
+ * Use {@link #hasHapticChannels(int)} instead when possible.
*
* @param ringtoneUri The {@link Uri} of a sound or ringtone.
* @return true if the ringtone contains haptic channels.
*/
public static boolean hasHapticChannels(@NonNull Uri ringtoneUri) {
- return AudioManager.hasHapticChannels(ringtoneUri);
+ return AudioManager.hasHapticChannels(null, ringtoneUri);
}
/**
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 136916af109d..91283b9c6ccc 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -95,8 +95,6 @@ import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.IVolumeController;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
import android.media.MediaMetrics;
import android.media.MediaRecorder.AudioSource;
import android.media.PlayerBase;
@@ -163,7 +161,6 @@ import com.android.server.pm.UserManagerService;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
-import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -6305,23 +6302,10 @@ public class AudioService extends IAudioService.Stub
}
/**
- * See AudioManager.hasHapticChannels(Uri).
+ * See AudioManager.hasHapticChannels(Context, Uri).
*/
public boolean hasHapticChannels(Uri uri) {
- MediaExtractor extractor = new MediaExtractor();
- try {
- extractor.setDataSource(mContext, uri, null);
- for (int i = 0; i < extractor.getTrackCount(); i++) {
- MediaFormat format = extractor.getTrackFormat(i);
- if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT)
- && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) {
- return true;
- }
- }
- } catch (IOException e) {
- Log.e(TAG, "hasHapticChannels failure:" + e);
- }
- return false;
+ return AudioManager.hasHapticChannelsImpl(mContext, uri);
}
///////////////////////////////////////////////////////////////////////////