diff options
author | jiabin <jiabin@google.com> | 2021-07-01 16:30:50 -0700 |
---|---|---|
committer | jiabin <jiabin@google.com> | 2021-07-02 10:05:07 -0700 |
commit | cfcf10324a1fbb2fe5d24ace2f67c6244e4d6f61 (patch) | |
tree | 4d7abf00f258a2cfa2e8d20a647b4034d0b47dec /media | |
parent | 35929095bdb6ef8ba48312821e75afae9437238b (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
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioManager.java | 52 | ||||
-rw-r--r-- | media/java/android/media/Ringtone.java | 2 | ||||
-rw-r--r-- | media/java/android/media/RingtoneManager.java | 9 |
3 files changed, 55 insertions, 8 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); } /** |