diff options
Diffstat (limited to 'media/java')
-rw-r--r-- | media/java/Android.bp | 12 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 9 | ||||
-rw-r--r-- | media/java/android/media/ExifInterface.java | 30 | ||||
-rw-r--r-- | media/java/android/media/IMediaRouterClient.aidl | 2 | ||||
-rw-r--r-- | media/java/android/media/IMediaRouterService.aidl | 1 | ||||
-rw-r--r-- | media/java/android/media/MediaCodec.java | 26 | ||||
-rw-r--r-- | media/java/android/media/MediaDrm.java | 11 | ||||
-rw-r--r-- | media/java/android/media/MediaFormat.java | 20 | ||||
-rw-r--r-- | media/java/android/media/MediaMetadataRetriever.java | 5 | ||||
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 6 | ||||
-rw-r--r-- | media/java/android/media/MediaRouter.java | 20 | ||||
-rw-r--r-- | media/java/android/media/MediaRouter2.java | 16 | ||||
-rw-r--r-- | media/java/android/media/PlayerBase.java | 147 | ||||
-rw-r--r-- | media/java/android/media/tv/tuner/frontend/FrontendStatus.java | 82 | ||||
-rwxr-xr-x | media/java/android/mtp/MtpDatabase.java | 18 |
15 files changed, 172 insertions, 233 deletions
diff --git a/media/java/Android.bp b/media/java/Android.bp index aea63a073e95..eeaf6e9015ac 100644 --- a/media/java/Android.bp +++ b/media/java/Android.bp @@ -8,6 +8,18 @@ package { } filegroup { + name: "framework-media-sources", + srcs: [ + "**/*.java", + "**/*.aidl", + ], + exclude_srcs: [ + ":framework-media-tv-tunerresourcemanager-sources-aidl", + ], + visibility: ["//frameworks/base"], +} + +filegroup { name: "IMidiDeviceServer.aidl", srcs: ["android/media/midi/IMidiDeviceServer.aidl"], } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 9a13953c4a62..329399103984 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager; import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; import android.os.Build; +import android.os.Vibrator; import android.telephony.TelephonyManager; import android.util.Log; import android.util.Pair; @@ -1962,6 +1963,14 @@ public class AudioSystem public static native int getDevicesForRoleAndCapturePreset( int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices); + /** + * @hide + * Set the vibrators' information. The value will be used to initialize HapticGenerator. + * @param vibrators a list of all available vibrators + * @return command completion status + */ + public static native int setVibratorInfos(@NonNull List<Vibrator> vibrators); + // Items shared with audio service /** diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 21f8623b1953..d746c850a018 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -32,6 +32,7 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.FileUtils; +import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -1531,16 +1532,24 @@ public class ExifInterface { if (fileDescriptor == null) { throw new NullPointerException("fileDescriptor cannot be null"); } - FileDescriptor modernFd = FileUtils.convertToModernFd(fileDescriptor); + // If a file descriptor has a modern file descriptor, this means that the file can be + // transcoded and not using the modern file descriptor will trigger the transcoding + // operation. Thus, to avoid unnecessary transcoding, need to convert to modern file + // descriptor if it exists. As of Android S, transcoding is not supported for image files, + // so this is for protecting against non-image files sent to ExifInterface, but support may + // be added in the future. + ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fileDescriptor); if (modernFd != null) { - fileDescriptor = modernFd; + fileDescriptor = modernFd.getFileDescriptor(); } mAssetInputStream = null; mFilename = null; boolean isFdDuped = false; - if (isSeekableFD(fileDescriptor)) { + // Can't save attributes to files with transcoding because apps get a different copy of + // that file when they're not using it through framework libraries like ExifInterface. + if (isSeekableFD(fileDescriptor) && modernFd == null) { mSeekableFileDescriptor = fileDescriptor; // Keep the original file descriptor in order to save attributes when it's seekable. // Otherwise, just close the given file descriptor after reading it because the save @@ -2545,27 +2554,22 @@ public class ExifInterface { private void initForFilename(String filename) throws IOException { FileInputStream in = null; - FileInputStream legacyInputStream = null; mAssetInputStream = null; mFilename = filename; mIsInputStream = false; try { in = new FileInputStream(filename); - FileDescriptor modernFd = FileUtils.convertToModernFd(in.getFD()); + ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(in.getFD()); if (modernFd != null) { - legacyInputStream = in; - in = new FileInputStream(modernFd); - } - - if (isSeekableFD(in.getFD())) { - mSeekableFileDescriptor = in.getFD(); - } else { + closeQuietly(in); + in = new FileInputStream(modernFd.getFileDescriptor()); mSeekableFileDescriptor = null; + } else if (isSeekableFD(in.getFD())) { + mSeekableFileDescriptor = in.getFD(); } loadAttributes(in); } finally { closeQuietly(in); - closeQuietly(legacyInputStream); } } diff --git a/media/java/android/media/IMediaRouterClient.aidl b/media/java/android/media/IMediaRouterClient.aidl index 53122bb990d6..6b754e157cfb 100644 --- a/media/java/android/media/IMediaRouterClient.aidl +++ b/media/java/android/media/IMediaRouterClient.aidl @@ -22,6 +22,6 @@ package android.media; oneway interface IMediaRouterClient { void onStateChanged(); void onRestoreRoute(); - void onSelectedRouteChanged(String routeId); + void onGroupRouteSelected(String routeId); void onGlobalA2dpChanged(boolean a2dpOn); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 4b8a8adade1f..f817a3c3c353 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -48,6 +48,7 @@ interface IMediaRouterService { // MediaRouterService.java for readability. // Methods for MediaRouter2 + void checkModifyAudioRoutingPermission(); List<MediaRoute2Info> getSystemRoutes(); RoutingSessionInfo getSystemSessionInfo(); diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index b51777c3135a..4968bd1e0ce7 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1684,7 +1684,6 @@ final public class MediaCodec { private MediaCodecInfo mCodecInfo; private final Object mCodecInfoLock = new Object(); private MediaCrypto mCrypto; - private String mPlaybackId; private static final int EVENT_CALLBACK = 1; private static final int EVENT_SET_CALLBACK = 2; @@ -4499,14 +4498,25 @@ final public class MediaCodec { int i = 0; for (final String key: params.keySet()) { - keys[i] = key; - Object value = params.get(key); - - // Bundle's byte array is a byte[], JNI layer only takes ByteBuffer - if (value instanceof byte[]) { - values[i] = ByteBuffer.wrap((byte[])value); + if (key.equals(MediaFormat.KEY_AUDIO_SESSION_ID)) { + int sessionId = 0; + try { + sessionId = (Integer)params.get(key); + } catch (Exception e) { + throw new IllegalArgumentException("Wrong Session ID Parameter!"); + } + keys[i] = "audio-hw-sync"; + values[i] = AudioSystem.getAudioHwSyncForSession(sessionId); } else { - values[i] = value; + keys[i] = key; + Object value = params.get(key); + + // Bundle's byte array is a byte[], JNI layer only takes ByteBuffer + if (value instanceof byte[]) { + values[i] = ByteBuffer.wrap((byte[])value); + } else { + values[i] = value; + } } ++i; } diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index 10b99dce53b0..864350e25929 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -2991,13 +2991,16 @@ public final class MediaDrm implements AutoCloseable { * A {@link LogMessage} records an event in the {@link MediaDrm} framework * or vendor plugin. */ - public static class LogMessage { + public static final class LogMessage { + private final long timestampMillis; + private final int priority; + private final String message; /** * Timing of the recorded event measured in milliseconds since the Epoch, * 1970-01-01 00:00:00 +0000 (UTC). */ - public final long timestampMillis; + public final long getTimestampMillis() { return timestampMillis; } /** * Priority of the recorded event. @@ -3013,13 +3016,13 @@ public final class MediaDrm implements AutoCloseable { * </ul> */ @Log.Level - public final int priority; + public final int getPriority() { return priority; } /** * Description of the recorded event. */ @NonNull - public final String message; + public final String getMessage() { return message; } private LogMessage(long timestampMillis, int priority, String message) { this.timestampMillis = timestampMillis; diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index af0a9cf2481e..50a326e9a595 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -219,6 +219,15 @@ public final class MediaFormat { private Map<String, Object> mMap; /** + * A key describing the log session ID for MediaCodec. The log session ID is a random 32-byte + * hexadecimal string that is used to associate metrics from multiple media codec instances + * to the same playback or recording session. + * The associated value is a string. + * @hide + */ + public static final String LOG_SESSION_ID = "log-session-id"; + + /** * A key describing the mime type of the MediaFormat. * The associated value is a string. */ @@ -1069,6 +1078,17 @@ public final class MediaFormat { public static final String KEY_AUDIO_SESSION_ID = "audio-session-id"; /** + * A key describing the audio hardware sync ID of the AudioTrack associated + * to a tunneled video codec. The associated value is an integer. + * + * @hide + * + * @see MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback + * @see AudioManager#getAudioHwSyncForSession + */ + public static final String KEY_AUDIO_HW_SYNC = "audio-hw-sync"; + + /** * A key for boolean AUTOSELECT behavior for the track. Tracks with AUTOSELECT=true * are considered when automatically selecting a track without specific user * choice, based on the current locale. diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index c13f610a908c..2943eee5b1da 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -33,6 +33,7 @@ import android.os.Build; import android.os.Bundle; import android.os.FileUtils; import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.text.TextUtils; @@ -300,11 +301,11 @@ public class MediaMetadataRetriever implements AutoCloseable { */ public void setDataSource(FileDescriptor fd, long offset, long length) throws IllegalArgumentException { - FileDescriptor modernFd = FileUtils.convertToModernFd(fd); + ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fd); if (modernFd == null) { _setDataSource(fd, offset, length); } else { - _setDataSource(modernFd, offset, length); + _setDataSource(modernFd.getFileDescriptor(), offset, length); } } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 644afb79814f..2d8babdc9f94 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -46,6 +46,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; +import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.PowerManager; @@ -97,7 +98,6 @@ import java.util.UUID; import java.util.Vector; import java.util.concurrent.Executor; - /** * MediaPlayer class can be used to control playback of audio/video files and streams. * @@ -1268,11 +1268,11 @@ public class MediaPlayer extends PlayerBase */ public void setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException { - FileDescriptor modernFd = FileUtils.convertToModernFd(fd); + ParcelFileDescriptor modernFd = FileUtils.convertToModernFd(fd); if (modernFd == null) { _setDataSource(fd, offset, length); } else { - _setDataSource(modernFd, offset, length); + _setDataSource(modernFd.getFileDescriptor(), offset, length); } } diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index dc43ad342725..480e2eaaf40f 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -122,6 +122,8 @@ public class MediaRouter { mIsBluetoothA2dpOn = mAudioService.isBluetoothA2dpOn(); } catch (RemoteException e) { Log.e(TAG, "Error querying Bluetooth A2DP state", e); + //TODO: When we reach here, mIsBluetoothA2dpOn may not be synced with + // mBluetoothA2dpRoute. } mHandler.post(new Runnable() { @Override public void run() { @@ -403,18 +405,18 @@ public class MediaRouter { } } - void updateSelectedRouteForId(String routeId) { - RouteInfo selectedRoute = isBluetoothA2dpOn() + void handleGroupRouteSelected(String routeId) { + RouteInfo routeToSelect = isBluetoothA2dpOn() ? mBluetoothA2dpRoute : mDefaultAudioVideo; final int count = mRoutes.size(); for (int i = 0; i < count; i++) { final RouteInfo route = mRoutes.get(i); if (TextUtils.equals(route.mGlobalRouteId, routeId)) { - selectedRoute = route; + routeToSelect = route; } } - if (selectedRoute != mSelectedRoute) { - selectRouteStatic(selectedRoute.mSupportedTypes, selectedRoute, false); + if (routeToSelect != mSelectedRoute) { + selectRouteStatic(routeToSelect.mSupportedTypes, routeToSelect, /*explicit=*/false); } } @@ -675,10 +677,10 @@ public class MediaRouter { } @Override - public void onSelectedRouteChanged(String routeId) { + public void onGroupRouteSelected(String groupRouteId) { mHandler.post(() -> { if (Client.this == mClient) { - updateSelectedRouteForId(routeId); + handleGroupRouteSelected(groupRouteId); } }); } @@ -689,9 +691,9 @@ public class MediaRouter { public void onGlobalA2dpChanged(boolean a2dpOn) { mHandler.post(() -> { if (mSelectedRoute == mDefaultAudioVideo && a2dpOn) { - setSelectedRoute(mBluetoothA2dpRoute, false); + setSelectedRoute(mBluetoothA2dpRoute, /*explicit=*/false); } else if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpOn) { - setSelectedRoute(mDefaultAudioVideo, false); + setSelectedRoute(mDefaultAudioVideo, /*explicit=*/false); } }); } diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 1f6855a4ae8e..90fa9a52f5cf 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -21,6 +21,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; @@ -159,9 +160,11 @@ public final class MediaRouter2 { * Finally, it will have no effect to call {@link #setOnGetControllerHintsListener}. * * @param clientPackageName the package name of the app to control + * @throws SecurityException if the caller doesn't have MODIFY_AUDIO_ROUTING permission. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) @Nullable public static MediaRouter2 getInstance(@NonNull Context context, @NonNull String clientPackageName) { @@ -179,13 +182,20 @@ public final class MediaRouter2 { synchronized (sSystemRouterLock) { MediaRouter2 instance = sSystemMediaRouter2Map.get(clientPackageName); if (instance == null) { - // TODO: Add permission check here using MODIFY_AUDIO_ROUTING. if (sManager == null) { + IMediaRouterService serviceBinder = IMediaRouterService.Stub.asInterface( + ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE)); + try { + // MediaRouterService will throw a SecurityException if the caller + // doesn't have MODIFY_AUDIO_ROUTING permission. + serviceBinder.checkModifyAudioRoutingPermission(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } sManager = MediaRouter2Manager.getInstance(context.getApplicationContext()); } instance = new MediaRouter2(context, clientPackageName); sSystemMediaRouter2Map.put(clientPackageName, instance); - // TODO: Remove router instance once it is not needed. instance.registerManagerCallbackForSystemRouter(); } return instance; @@ -281,9 +291,9 @@ public final class MediaRouter2 { mDiscoveryPreference = new RouteDiscoveryPreference.Builder( sManager.getPreferredFeatures(clientPackageName), true).build(); updateAllRoutesFromManager(); - mMediaRouterService = null; // TODO: Make this non-null and check permission. // Only used by non-system MediaRouter2. + mMediaRouterService = null; mPackageName = null; } diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index 5d0f0aa8a921..86ed50bacb63 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -19,12 +19,10 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; -import android.app.AppOpsManager; import android.content.Context; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; -import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.text.TextUtils; @@ -51,10 +49,6 @@ public abstract class PlayerBase { private static final boolean DEBUG = DEBUG_APP_OPS || false; private static IAudioService sService; //lazy initialization, use getService() - /** if true, only use OP_PLAY_AUDIO monitoring for logging, and rely on muting to happen - * in AudioFlinger */ - private static final boolean USE_AUDIOFLINGER_MUTING_FOR_OP = true; - // parameters of the player that affect AppOps protected AudioAttributes mAttributes; @@ -112,21 +106,6 @@ public abstract class PlayerBase { * Call from derived class when instantiation / initialization is successful */ protected void baseRegisterPlayer(int sessionId) { - if (!USE_AUDIOFLINGER_MUTING_FOR_OP) { - IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); - mAppOps = IAppOpsService.Stub.asInterface(b); - // initialize mHasAppOpsPlayAudio - updateAppOpsPlayAudio(); - // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed - mAppOpsCallback = new IAppOpsCallbackWrapper(this); - try { - mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO, - ActivityThread.currentPackageName(), mAppOpsCallback); - } catch (RemoteException e) { - Log.e(TAG, "Error registering appOps callback", e); - mHasAppOpsPlayAudio = false; - } - } try { mPlayerIId = getService().trackPlayer( new PlayerIdCard(mImplType, mAttributes, new IPlayerWrapper(this), @@ -150,9 +129,7 @@ public abstract class PlayerBase { Log.e(TAG, "Error talking to audio service, audio attributes will not be updated", e); } synchronized (mLock) { - boolean attributesChanged = (mAttributes != attr); mAttributes = attr; - updateAppOpsPlayAudio_sync(attributesChanged); } } @@ -209,11 +186,6 @@ public abstract class PlayerBase { Log.v(TAG, "baseStart() piid=" + mPlayerIId + " deviceId=" + deviceId); } updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED, deviceId); - synchronized (mLock) { - if (isRestricted_sync()) { - playerSetVolume(true/*muting*/,0, 0); - } - } } void baseSetStartDelayMs(int delayMs) { @@ -254,13 +226,11 @@ public abstract class PlayerBase { private void updatePlayerVolume() { final float finalLeftVol, finalRightVol; - final boolean isRestricted; synchronized (mLock) { finalLeftVol = mVolMultiplier * mLeftVolume * mPanMultiplierL; finalRightVol = mVolMultiplier * mRightVolume * mPanMultiplierR; - isRestricted = isRestricted_sync(); } - playerSetVolume(isRestricted /*muting*/, finalLeftVol, finalRightVol); + playerSetVolume(false /*muting*/, finalLeftVol, finalRightVol); } void setVolumeMultiplier(float vol) { @@ -281,9 +251,6 @@ public abstract class PlayerBase { int baseSetAuxEffectSendLevel(float level) { synchronized (mLock) { mAuxEffectSendLevel = level; - if (isRestricted_sync()) { - return AudioSystem.SUCCESS; - } } return playerSetAuxEffectSendLevel(false/*muting*/, level); } @@ -317,98 +284,6 @@ public abstract class PlayerBase { } } - private void updateAppOpsPlayAudio() { - synchronized (mLock) { - updateAppOpsPlayAudio_sync(false); - } - } - - /** - * To be called whenever a condition that might affect audibility of this player is updated. - * Must be called synchronized on mLock. - */ - void updateAppOpsPlayAudio_sync(boolean attributesChanged) { - if (USE_AUDIOFLINGER_MUTING_FOR_OP) { - return; - } - boolean oldHasAppOpsPlayAudio = mHasAppOpsPlayAudio; - try { - int mode = AppOpsManager.MODE_IGNORED; - if (mAppOps != null) { - mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, - mAttributes.getUsage(), - Process.myUid(), ActivityThread.currentPackageName()); - } - mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED); - } catch (RemoteException e) { - mHasAppOpsPlayAudio = false; - } - - // AppsOps alters a player's volume; when the restriction changes, reflect it on the actual - // volume used by the player - try { - if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio || - attributesChanged) { - getService().playerHasOpPlayAudio(mPlayerIId, mHasAppOpsPlayAudio); - if (!isRestricted_sync()) { - if (DEBUG_APP_OPS) { - Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume - + "/" + mRightVolume); - } - playerSetVolume(false/*muting*/, - mLeftVolume * mPanMultiplierL, mRightVolume * mPanMultiplierR); - playerSetAuxEffectSendLevel(false/*muting*/, mAuxEffectSendLevel); - } else { - if (DEBUG_APP_OPS) { - Log.v(TAG, "updateAppOpsPlayAudio: muting player"); - } - playerSetVolume(true/*muting*/, 0.0f, 0.0f); - playerSetAuxEffectSendLevel(true/*muting*/, 0.0f); - } - } - } catch (Exception e) { - // failing silently, player might not be in right state - } - } - - /** - * To be called by the subclass whenever an operation is potentially restricted. - * As the media player-common behavior are incorporated into this class, the subclass's need - * to call this method should be removed, and this method could become private. - * FIXME can this method be private so subclasses don't have to worry about when to check - * the restrictions. - * @return - */ - boolean isRestricted_sync() { - if (USE_AUDIOFLINGER_MUTING_FOR_OP) { - return false; - } - // check app ops - if (mHasAppOpsPlayAudio) { - return false; - } - // check bypass flag - if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { - return false; - } - // check force audibility flag and camera restriction - if (((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) - && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)) { - boolean cameraSoundForced = false; - try { - cameraSoundForced = getService().isCameraSoundForced(); - } catch (RemoteException e) { - Log.e(TAG, "Cannot access AudioService in isRestricted_sync()"); - } catch (NullPointerException e) { - Log.e(TAG, "Null AudioService in isRestricted_sync()"); - } - if (cameraSoundForced) { - return false; - } - } - return true; - } - private static IAudioService getService() { if (sService != null) { @@ -478,26 +353,6 @@ public abstract class PlayerBase { abstract void playerStop(); //===================================================================== - private static class IAppOpsCallbackWrapper extends IAppOpsCallback.Stub { - private final WeakReference<PlayerBase> mWeakPB; - - public IAppOpsCallbackWrapper(PlayerBase pb) { - mWeakPB = new WeakReference<PlayerBase>(pb); - } - - @Override - public void opChanged(int op, int uid, String packageName) { - if (op == AppOpsManager.OP_PLAY_AUDIO) { - if (DEBUG_APP_OPS) { Log.v(TAG, "opChanged: op=PLAY_AUDIO pack=" + packageName); } - final PlayerBase pb = mWeakPB.get(); - if (pb != null) { - pb.updateAppOpsPlayAudio(); - } - } - } - } - - //===================================================================== /** * Wrapper around an implementation of IPlayer for all subclasses of PlayerBase * that doesn't keep a strong reference on PlayerBase diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java index 4acaa58a1842..b82a5a914da8 100644 --- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java +++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java @@ -52,8 +52,8 @@ public class FrontendStatus { FRONTEND_STATUS_TYPE_T2_SYSTEM_ID, FRONTEND_STATUS_TYPE_INTERLEAVINGS, FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS, FRONTEND_STATUS_TYPE_TS_DATA_RATES, FRONTEND_STATUS_TYPE_MODULATIONS_EXT, FRONTEND_STATUS_TYPE_ROLL_OFF, - FRONTEND_STATUS_TYPE_IS_MISO, FRONTEND_STATUS_TYPE_IS_LINEAR, - FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES}) + FRONTEND_STATUS_TYPE_IS_MISO_ENABLED, FRONTEND_STATUS_TYPE_IS_LINEAR, + FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED}) @Retention(RetentionPolicy.SOURCE) public @interface FrontendStatusType {} @@ -218,7 +218,7 @@ public class FrontendStatus { /** * If the frontend currently supports MISO or not. Only supported in Tuner HAL 1.1 or higher. */ - public static final int FRONTEND_STATUS_TYPE_IS_MISO = + public static final int FRONTEND_STATUS_TYPE_IS_MISO_ENABLED = android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_MISO; /** * If the frontend code rate is linear or not. Only supported in Tuner HAL 1.1 or higher. @@ -228,7 +228,7 @@ public class FrontendStatus { /** * If short frames is enabled or not. Only supported in Tuner HAL 1.1 or higher. */ - public static final int FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES = + public static final int FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED = android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_SHORT_FRAMES; /** @hide */ @@ -465,7 +465,7 @@ public class FrontendStatus { */ public boolean isDemodLocked() { if (mIsDemodLocked == null) { - throw new IllegalStateException(); + throw new IllegalStateException("DemodLocked status is empty"); } return mIsDemodLocked; } @@ -474,7 +474,7 @@ public class FrontendStatus { */ public int getSnr() { if (mSnr == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Snr status is empty"); } return mSnr; } @@ -485,7 +485,7 @@ public class FrontendStatus { */ public int getBer() { if (mBer == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Ber status is empty"); } return mBer; } @@ -497,7 +497,7 @@ public class FrontendStatus { */ public int getPer() { if (mPer == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Per status is empty"); } return mPer; } @@ -508,7 +508,7 @@ public class FrontendStatus { */ public int getPerBer() { if (mPerBer == null) { - throw new IllegalStateException(); + throw new IllegalStateException("PerBer status is empty"); } return mPerBer; } @@ -517,7 +517,7 @@ public class FrontendStatus { */ public int getSignalQuality() { if (mSignalQuality == null) { - throw new IllegalStateException(); + throw new IllegalStateException("SignalQuality status is empty"); } return mSignalQuality; } @@ -526,7 +526,7 @@ public class FrontendStatus { */ public int getSignalStrength() { if (mSignalStrength == null) { - throw new IllegalStateException(); + throw new IllegalStateException("SignalStrength status is empty"); } return mSignalStrength; } @@ -535,7 +535,7 @@ public class FrontendStatus { */ public int getSymbolRate() { if (mSymbolRate == null) { - throw new IllegalStateException(); + throw new IllegalStateException("SymbolRate status is empty"); } return mSymbolRate; } @@ -546,7 +546,7 @@ public class FrontendStatus { @FrontendSettings.InnerFec public long getInnerFec() { if (mInnerFec == null) { - throw new IllegalStateException(); + throw new IllegalStateException("InnerFec status is empty"); } return mInnerFec; } @@ -556,7 +556,7 @@ public class FrontendStatus { @FrontendModulation public int getModulation() { if (mModulation == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Modulation status is empty"); } return mModulation; } @@ -566,7 +566,7 @@ public class FrontendStatus { @FrontendSettings.FrontendSpectralInversion public int getSpectralInversion() { if (mInversion == null) { - throw new IllegalStateException(); + throw new IllegalStateException("SpectralInversion status is empty"); } return mInversion; } @@ -576,7 +576,7 @@ public class FrontendStatus { @Lnb.Voltage public int getLnbVoltage() { if (mLnbVoltage == null) { - throw new IllegalStateException(); + throw new IllegalStateException("LnbVoltage status is empty"); } return mLnbVoltage; } @@ -585,7 +585,7 @@ public class FrontendStatus { */ public int getPlpId() { if (mPlpId == null) { - throw new IllegalStateException(); + throw new IllegalStateException("PlpId status is empty"); } return mPlpId; } @@ -594,7 +594,7 @@ public class FrontendStatus { */ public boolean isEwbs() { if (mIsEwbs == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Ewbs status is empty"); } return mIsEwbs; } @@ -603,7 +603,7 @@ public class FrontendStatus { */ public int getAgc() { if (mAgc == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Agc status is empty"); } return mAgc; } @@ -612,7 +612,7 @@ public class FrontendStatus { */ public boolean isLnaOn() { if (mIsLnaOn == null) { - throw new IllegalStateException(); + throw new IllegalStateException("LnaOn status is empty"); } return mIsLnaOn; } @@ -622,7 +622,7 @@ public class FrontendStatus { @NonNull public boolean[] getLayerErrors() { if (mIsLayerErrors == null) { - throw new IllegalStateException(); + throw new IllegalStateException("LayerErrors status is empty"); } return mIsLayerErrors; } @@ -631,7 +631,7 @@ public class FrontendStatus { */ public int getMer() { if (mMer == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Mer status is empty"); } return mMer; } @@ -642,7 +642,7 @@ public class FrontendStatus { */ public int getFreqOffset() { if (mFreqOffset == null) { - throw new IllegalStateException(); + throw new IllegalStateException("FreqOffset status is empty"); } return mFreqOffset; } @@ -652,7 +652,7 @@ public class FrontendStatus { @DvbtFrontendSettings.Hierarchy public int getHierarchy() { if (mHierarchy == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Hierarchy status is empty"); } return mHierarchy; } @@ -661,7 +661,7 @@ public class FrontendStatus { */ public boolean isRfLocked() { if (mIsRfLocked == null) { - throw new IllegalStateException(); + throw new IllegalStateException("isRfLocked status is empty"); } return mIsRfLocked; } @@ -671,7 +671,7 @@ public class FrontendStatus { @NonNull public Atsc3PlpTuningInfo[] getAtsc3PlpTuningInfo() { if (mPlpInfo == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Atsc3PlpTuningInfo status is empty"); } return mPlpInfo; } @@ -687,7 +687,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getBers status"); if (mBers == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Bers status is empty"); } return mBers; } @@ -704,7 +704,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getCodeRates status"); if (mCodeRates == null) { - throw new IllegalStateException(); + throw new IllegalStateException("CodeRates status is empty"); } return mCodeRates; } @@ -720,7 +720,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getBandwidth status"); if (mBandwidth == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Bandwidth status is empty"); } return mBandwidth; } @@ -736,7 +736,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getGuardInterval status"); if (mGuardInterval == null) { - throw new IllegalStateException(); + throw new IllegalStateException("GuardInterval status is empty"); } return mGuardInterval; } @@ -752,7 +752,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getTransmissionMode status"); if (mTransmissionMode == null) { - throw new IllegalStateException(); + throw new IllegalStateException("TransmissionMode status is empty"); } return mTransmissionMode; } @@ -768,7 +768,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getUec status"); if (mUec == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Uec status is empty"); } return mUec; } @@ -784,7 +784,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getSystemId status"); if (mSystemId == null) { - throw new IllegalStateException(); + throw new IllegalStateException("SystemId status is empty"); } return mSystemId; } @@ -801,7 +801,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getInterleaving status"); if (mInterleaving == null) { - throw new IllegalStateException(); + throw new IllegalStateException("Interleaving status is empty"); } return mInterleaving; } @@ -819,7 +819,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getIsdbtSegment status"); if (mIsdbtSegment == null) { - throw new IllegalStateException(); + throw new IllegalStateException("IsdbtSegment status is empty"); } return mIsdbtSegment; } @@ -835,7 +835,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getTsDataRate status"); if (mTsDataRate == null) { - throw new IllegalStateException(); + throw new IllegalStateException("TsDataRate status is empty"); } return mTsDataRate; } @@ -852,7 +852,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getExtendedModulations status"); if (mModulationsExt == null) { - throw new IllegalStateException(); + throw new IllegalStateException("ExtendedModulations status is empty"); } return mModulationsExt; } @@ -868,7 +868,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "getRollOff status"); if (mRollOff == null) { - throw new IllegalStateException(); + throw new IllegalStateException("RollOff status is empty"); } return mRollOff; } @@ -883,7 +883,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "isMisoEnabled status"); if (mIsMisoEnabled == null) { - throw new IllegalStateException(); + throw new IllegalStateException("isMisoEnabled status is empty"); } return mIsMisoEnabled; } @@ -898,7 +898,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "isLinear status"); if (mIsLinear == null) { - throw new IllegalStateException(); + throw new IllegalStateException("isLinear status is empty"); } return mIsLinear; } @@ -913,7 +913,7 @@ public class FrontendStatus { TunerVersionChecker.checkHigherOrEqualVersionTo( TunerVersionChecker.TUNER_VERSION_1_1, "isShortFramesEnabled status"); if (mIsShortFrames == null) { - throw new IllegalStateException(); + throw new IllegalStateException("isShortFramesEnabled status is empty"); } return mIsShortFrames; } diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 6141b7fc7463..860d88afe4a2 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -805,8 +805,10 @@ public class MtpDatabase implements AutoCloseable { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteStream); - if (byteStream.size() > MAX_THUMB_SIZE) + if (byteStream.size() > MAX_THUMB_SIZE) { + Log.w(TAG, "getThumbnailProcess: size=" + byteStream.size()); return null; + } byte[] byteArray = byteStream.toByteArray(); @@ -836,7 +838,15 @@ public class MtpDatabase implements AutoCloseable { outLongs[0] = thumbOffsetAndSize != null ? thumbOffsetAndSize[1] : 0; outLongs[1] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_X_DIMENSION, 0); outLongs[2] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_Y_DIMENSION, 0); - return true; + if (exif.getThumbnailRange() != null) { + if ((outLongs[0] == 0) || (outLongs[1] == 0) || (outLongs[2] == 0)) { + Log.d(TAG, "getThumbnailInfo: check thumb info:" + + thumbOffsetAndSize[0] + "," + thumbOffsetAndSize[1] + + "," + outLongs[1] + "," + outLongs[2]); + } + + return true; + } } catch (IOException e) { // ignore and fall through } @@ -869,7 +879,9 @@ public class MtpDatabase implements AutoCloseable { case MtpConstants.FORMAT_JFIF: try { ExifInterface exif = new ExifInterface(path); - return exif.getThumbnail(); + + if (exif.getThumbnailRange() != null) + return exif.getThumbnail(); } catch (IOException e) { // ignore and fall through } |