Loading core/java/android/os/storage/StorageManager.java +117 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,21 @@ package android.os.storage; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_MEDIA_AUDIO; import static android.Manifest.permission.READ_MEDIA_IMAGES; import static android.Manifest.permission.READ_MEDIA_VIDEO; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_READ_MEDIA_AUDIO; import static android.app.AppOpsManager.OP_READ_MEDIA_IMAGES; import static android.app.AppOpsManager.OP_READ_MEDIA_VIDEO; import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_WRITE_MEDIA_AUDIO; import static android.app.AppOpsManager.OP_WRITE_MEDIA_IMAGES; import static android.app.AppOpsManager.OP_WRITE_MEDIA_VIDEO; import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.annotation.BytesLong; import android.annotation.IntDef; Loading @@ -33,6 +47,7 @@ import android.annotation.WorkerThread; import android.app.Activity; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading Loading @@ -1635,6 +1650,108 @@ public class StorageManager { } } /** * Check that given app holds both permission and appop. * * @return {@code null} if the permission and appop are held, otherwise * returns a string indicating why access was denied. */ private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (mContext.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { if (enforce) { throw new SecurityException( "Permission " + permission + " denied for package " + packageName); } else { return false; } } final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); final int mode = appOps.noteOpNoThrow(op, uid, packageName); switch (mode) { case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_DEFAULT: case AppOpsManager.MODE_IGNORED: case AppOpsManager.MODE_ERRORED: if (enforce) { throw new SecurityException("Op " + AppOpsManager.opToName(op) + " " + AppOpsManager.modeToName(mode) + " for package " + packageName); } else { return false; } default: throw new IllegalStateException( AppOpsManager.opToName(op) + " has unknown mode " + AppOpsManager.modeToName(mode)); } } // Callers must hold both the old and new permissions, so that we can // handle obscure cases like when an app targets Q but was installed on // a device that was originally running on P before being upgraded to Q. /** {@hide} */ public boolean checkPermissionReadAudio(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_AUDIO, OP_READ_MEDIA_AUDIO)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteAudio(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_AUDIO, OP_WRITE_MEDIA_AUDIO)) return false; return true; } /** {@hide} */ public boolean checkPermissionReadVideo(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_VIDEO, OP_READ_MEDIA_VIDEO)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteVideo(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_VIDEO, OP_WRITE_MEDIA_VIDEO)) return false; return true; } /** {@hide} */ public boolean checkPermissionReadImages(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_IMAGES, OP_READ_MEDIA_IMAGES)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteImages(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_IMAGES, OP_WRITE_MEDIA_IMAGES)) return false; return true; } /** {@hide} */ @VisibleForTesting public @NonNull ParcelFileDescriptor openProxyFileDescriptor( Loading media/java/android/media/RingtoneManager.java +7 −19 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.res.AssetFileDescriptor; Loading @@ -40,7 +39,6 @@ import android.os.Environment; import android.os.FileUtils; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; Loading Loading @@ -597,22 +595,12 @@ public class RingtoneManager { @UnsupportedAppUsage private Cursor getMediaRingtones(Context context) { if (PackageManager.PERMISSION_GRANTED != context.checkPermission( android.Manifest.permission.READ_EXTERNAL_STORAGE, Process.myPid(), Process.myUid())) { Log.w(TAG, "No READ_EXTERNAL_STORAGE permission, ignoring ringtones on ext storage"); return null; } // Get the external media cursor. First check to see if it is mounted. final String status = Environment.getExternalStorageState(); return (status.equals(Environment.MEDIA_MOUNTED) || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) ? query( // MediaStore now returns ringtones on other storage devices, even when // we don't have storage or audio permissions return query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS, constructBooleanTrueWhereClause(mFilterColumns), null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER, context) : null; MediaStore.Audio.Media.DEFAULT_SORT_ORDER, context); } private void setFilterColumnsList(int type) { Loading packages/SystemUI/AndroidManifest.xml +4 −2 Original line number Diff line number Diff line Loading @@ -33,8 +33,10 @@ android:protectionLevel="signature" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Used to read wallpaper --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- Used to read storage for all users --> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> Loading services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +3 −16 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; Loading Loading @@ -2089,28 +2090,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg, final int callingUid, String message) { mContext.enforceCallingOrSelfPermission(permission, message); final String opName = AppOpsManager.permissionToOp(permission); if (opName != null) { final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg); if (appOpMode != AppOpsManager.MODE_ALLOWED) { throw new SecurityException( message + ": " + callingPkg + " is not allowed to " + permission); } } } @Override public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) { final int hasPrivilege = mContext.checkCallingOrSelfPermission( android.Manifest.permission.READ_WALLPAPER_INTERNAL); if (hasPrivilege != PackageManager.PERMISSION_GRANTED) { enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE, callingPkg, Binder.getCallingUid(), "read wallpaper"); mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true, Binder.getCallingPid(), Binder.getCallingUid(), callingPkg); } wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Loading Loading
core/java/android/os/storage/StorageManager.java +117 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,21 @@ package android.os.storage; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_MEDIA_AUDIO; import static android.Manifest.permission.READ_MEDIA_IMAGES; import static android.Manifest.permission.READ_MEDIA_VIDEO; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_READ_MEDIA_AUDIO; import static android.app.AppOpsManager.OP_READ_MEDIA_IMAGES; import static android.app.AppOpsManager.OP_READ_MEDIA_VIDEO; import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_WRITE_MEDIA_AUDIO; import static android.app.AppOpsManager.OP_WRITE_MEDIA_IMAGES; import static android.app.AppOpsManager.OP_WRITE_MEDIA_VIDEO; import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.annotation.BytesLong; import android.annotation.IntDef; Loading @@ -33,6 +47,7 @@ import android.annotation.WorkerThread; import android.app.Activity; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading Loading @@ -1635,6 +1650,108 @@ public class StorageManager { } } /** * Check that given app holds both permission and appop. * * @return {@code null} if the permission and appop are held, otherwise * returns a string indicating why access was denied. */ private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (mContext.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { if (enforce) { throw new SecurityException( "Permission " + permission + " denied for package " + packageName); } else { return false; } } final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); final int mode = appOps.noteOpNoThrow(op, uid, packageName); switch (mode) { case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_DEFAULT: case AppOpsManager.MODE_IGNORED: case AppOpsManager.MODE_ERRORED: if (enforce) { throw new SecurityException("Op " + AppOpsManager.opToName(op) + " " + AppOpsManager.modeToName(mode) + " for package " + packageName); } else { return false; } default: throw new IllegalStateException( AppOpsManager.opToName(op) + " has unknown mode " + AppOpsManager.modeToName(mode)); } } // Callers must hold both the old and new permissions, so that we can // handle obscure cases like when an app targets Q but was installed on // a device that was originally running on P before being upgraded to Q. /** {@hide} */ public boolean checkPermissionReadAudio(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_AUDIO, OP_READ_MEDIA_AUDIO)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteAudio(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_AUDIO, OP_WRITE_MEDIA_AUDIO)) return false; return true; } /** {@hide} */ public boolean checkPermissionReadVideo(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_VIDEO, OP_READ_MEDIA_VIDEO)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteVideo(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_VIDEO, OP_WRITE_MEDIA_VIDEO)) return false; return true; } /** {@hide} */ public boolean checkPermissionReadImages(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_IMAGES, OP_READ_MEDIA_IMAGES)) return false; return true; } /** {@hide} */ public boolean checkPermissionWriteImages(boolean enforce, int pid, int uid, String packageName) { if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false; if (!checkPermissionAndAppOp(enforce, pid, uid, packageName, READ_MEDIA_IMAGES, OP_WRITE_MEDIA_IMAGES)) return false; return true; } /** {@hide} */ @VisibleForTesting public @NonNull ParcelFileDescriptor openProxyFileDescriptor( Loading
media/java/android/media/RingtoneManager.java +7 −19 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.res.AssetFileDescriptor; Loading @@ -40,7 +39,6 @@ import android.os.Environment; import android.os.FileUtils; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; Loading Loading @@ -597,22 +595,12 @@ public class RingtoneManager { @UnsupportedAppUsage private Cursor getMediaRingtones(Context context) { if (PackageManager.PERMISSION_GRANTED != context.checkPermission( android.Manifest.permission.READ_EXTERNAL_STORAGE, Process.myPid(), Process.myUid())) { Log.w(TAG, "No READ_EXTERNAL_STORAGE permission, ignoring ringtones on ext storage"); return null; } // Get the external media cursor. First check to see if it is mounted. final String status = Environment.getExternalStorageState(); return (status.equals(Environment.MEDIA_MOUNTED) || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) ? query( // MediaStore now returns ringtones on other storage devices, even when // we don't have storage or audio permissions return query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS, constructBooleanTrueWhereClause(mFilterColumns), null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER, context) : null; MediaStore.Audio.Media.DEFAULT_SORT_ORDER, context); } private void setFilterColumnsList(int type) { Loading
packages/SystemUI/AndroidManifest.xml +4 −2 Original line number Diff line number Diff line Loading @@ -33,8 +33,10 @@ android:protectionLevel="signature" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Used to read wallpaper --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- Used to read storage for all users --> <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> Loading
services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +3 −16 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; Loading Loading @@ -2089,28 +2090,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg, final int callingUid, String message) { mContext.enforceCallingOrSelfPermission(permission, message); final String opName = AppOpsManager.permissionToOp(permission); if (opName != null) { final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg); if (appOpMode != AppOpsManager.MODE_ALLOWED) { throw new SecurityException( message + ": " + callingPkg + " is not allowed to " + permission); } } } @Override public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) { final int hasPrivilege = mContext.checkCallingOrSelfPermission( android.Manifest.permission.READ_WALLPAPER_INTERNAL); if (hasPrivilege != PackageManager.PERMISSION_GRANTED) { enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE, callingPkg, Binder.getCallingUid(), "read wallpaper"); mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true, Binder.getCallingPid(), Binder.getCallingUid(), callingPkg); } wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Loading