diff options
author | Haamed Gheibi <haamed@google.com> | 2021-07-12 20:47:45 +0000 |
---|---|---|
committer | Haamed Gheibi <haamed@google.com> | 2021-07-14 18:21:17 +0000 |
commit | 02a7ee5d65cb8d40fd1dde9aaf6b5ead9222a5a6 (patch) | |
tree | 6fb30a5bc0d0e7fadd37d62cdba537c4d5d9237b /media | |
parent | bab7c6ab6b363574baaace4df576c1abb67f4507 (diff) | |
parent | fa0439912edd9559d7c0f46bef2b2898de68f50f (diff) |
Merge SP1A.210709.002
Change-Id: I4610885d5d770d858895057cdd9fea387a5e33dd
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioFormat.java | 4 | ||||
-rw-r--r-- | media/java/android/media/AudioManager.java | 52 | ||||
-rw-r--r-- | media/java/android/media/MediaRecorder.java | 6 | ||||
-rw-r--r-- | media/java/android/media/MediaRouter2Manager.java | 58 | ||||
-rw-r--r-- | media/java/android/media/MediaServiceManager.java | 16 | ||||
-rw-r--r-- | media/java/android/media/Ringtone.java | 2 | ||||
-rw-r--r-- | media/java/android/media/RingtoneManager.java | 9 |
7 files changed, 131 insertions, 16 deletions
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index e35b0d516e56..b07dc9b581b2 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -310,6 +310,10 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_LEGACY_SHORT_ARRAY_THRESHOLD = ENCODING_OPUS; /** Audio data format: PCM 24 bit per sample packed as 3 bytes. + * + * The bytes are in little-endian order, so the least significant byte + * comes first in the byte array. + * * Not guaranteed to be supported by devices, may be emulated if not supported. */ public static final int ENCODING_PCM_24BIT_PACKED = 21; /** Audio data format: PCM 32 bit per sample. diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index ef478ee6aa6b..5b48bea776a8 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 @@ -7276,15 +7279,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/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 805340be688c..5936700ed742 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -854,7 +854,7 @@ public class MediaRecorder implements AudioRouting, setVideoSize(profile.getWidth(), profile.getHeight()); setVideoEncodingBitRate(profile.getBitrate()); setVideoEncoder(profile.getCodec()); - if (profile.getProfile() > 0) { + if (profile.getProfile() >= 0) { setVideoEncodingProfileLevel(profile.getProfile(), 0 /* level */); } } @@ -1135,10 +1135,10 @@ public class MediaRecorder implements AudioRouting, * @throws IllegalArgumentException when an invalid profile or level value is used. */ public void setVideoEncodingProfileLevel(int profile, int level) { - if (profile <= 0) { + if (profile < 0) { throw new IllegalArgumentException("Video encoding profile is not positive"); } - if (level <= 0) { + if (level < 0) { throw new IllegalArgumentException("Video encoding level is not positive"); } setParameter("video-param-encoder-profile=" + profile); diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 915cb1272040..628f7eef84f9 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -221,10 +221,24 @@ public final class MediaRouter2Manager { Objects.requireNonNull(packageName, "packageName must not be null"); List<RoutingSessionInfo> sessions = getRoutingSessions(packageName); - return getAvailableRoutesForRoutingSession(sessions.get(sessions.size() - 1)); + return getAvailableRoutes(sessions.get(sessions.size() - 1)); } /** + * Gets routes that can be transferable seamlessly for an application. + * + * @param packageName the package name of the application + */ + @NonNull + public List<MediaRoute2Info> getTransferableRoutes(@NonNull String packageName) { + Objects.requireNonNull(packageName, "packageName must not be null"); + + List<RoutingSessionInfo> sessions = getRoutingSessions(packageName); + return getTransferableRoutes(sessions.get(sessions.size() - 1)); + } + + + /** * Gets available routes for the given routing session. * The returned routes can be passed to * {@link #transfer(RoutingSessionInfo, MediaRoute2Info)} for transferring the routing session. @@ -232,8 +246,7 @@ public final class MediaRouter2Manager { * @param sessionInfo the routing session that would be transferred */ @NonNull - public List<MediaRoute2Info> getAvailableRoutesForRoutingSession( - @NonNull RoutingSessionInfo sessionInfo) { + public List<MediaRoute2Info> getAvailableRoutes(@NonNull RoutingSessionInfo sessionInfo) { Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); List<MediaRoute2Info> routes = new ArrayList<>(); @@ -256,6 +269,45 @@ public final class MediaRouter2Manager { } /** + * Gets routes that can be transferable seamlessly for the given routing session. + * The returned routes can be passed to + * {@link #transfer(RoutingSessionInfo, MediaRoute2Info)} for transferring the routing session. + * <p> + * This includes routes that are {@link RoutingSessionInfo#getTransferableRoutes() transferable} + * by provider itself and routes that are different playback type (e.g. local/remote) + * from the given routing session. + * + * @param sessionInfo the routing session that would be transferred + */ + @NonNull + public List<MediaRoute2Info> getTransferableRoutes(@NonNull RoutingSessionInfo sessionInfo) { + Objects.requireNonNull(sessionInfo, "sessionInfo must not be null"); + + List<MediaRoute2Info> routes = new ArrayList<>(); + + String packageName = sessionInfo.getClientPackageName(); + List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName); + if (preferredFeatures == null) { + preferredFeatures = Collections.emptyList(); + } + synchronized (mRoutesLock) { + for (MediaRoute2Info route : mRoutes.values()) { + if (sessionInfo.getSelectedRoutes().contains(route.getId()) + || sessionInfo.getTransferableRoutes().contains(route.getId())) { + routes.add(route); + continue; + } + // Add Phone -> Cast and Cast -> Phone + if (route.hasAnyFeatures(preferredFeatures) + && (sessionInfo.isSystemSession() ^ route.isSystemRoute())) { + routes.add(route); + } + } + } + return routes; + } + + /** * Returns the preferred features of the specified package name. */ @NonNull diff --git a/media/java/android/media/MediaServiceManager.java b/media/java/android/media/MediaServiceManager.java index b899559d2e50..fd89c0c67e71 100644 --- a/media/java/android/media/MediaServiceManager.java +++ b/media/java/android/media/MediaServiceManager.java @@ -45,12 +45,21 @@ public class MediaServiceManager { */ public static final class ServiceRegisterer { private final String mServiceName; + private final boolean mLazyStart; /** * @hide */ - public ServiceRegisterer(String serviceName) { + public ServiceRegisterer(String serviceName, boolean lazyStart) { mServiceName = serviceName; + mLazyStart = lazyStart; + } + + /** + * @hide + */ + public ServiceRegisterer(String serviceName) { + this(serviceName, false /*lazyStart*/); } /** @@ -61,6 +70,9 @@ public class MediaServiceManager { */ @Nullable public IBinder get() { + if (mLazyStart) { + return ServiceManager.waitForService(mServiceName); + } return ServiceManager.getService(mServiceName); } } @@ -78,7 +90,7 @@ public class MediaServiceManager { */ @NonNull public ServiceRegisterer getMediaTranscodingServiceRegisterer() { - return new ServiceRegisterer(MEDIA_TRANSCODING_SERVICE); + return new ServiceRegisterer(MEDIA_TRANSCODING_SERVICE, true /*lazyStart*/); } /** 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); } /** |