summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/os/storage/IStorageManager.aidl3
-rw-r--r--core/java/android/os/storage/StorageManager.java28
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java53
4 files changed, 85 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 00dec11c1f56..8710e613602f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -31868,6 +31868,7 @@ package android.os.storage {
method @WorkerThread public long getAllocatableBytes(@NonNull java.util.UUID) throws java.io.IOException;
method @WorkerThread public long getCacheQuotaBytes(@NonNull java.util.UUID) throws java.io.IOException;
method @WorkerThread public long getCacheSizeBytes(@NonNull java.util.UUID) throws java.io.IOException;
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE) public android.app.PendingIntent getManageSpaceActivityIntent(@NonNull String, int);
method public String getMountedObbPath(String);
method @NonNull public android.os.storage.StorageVolume getPrimaryStorageVolume();
method @NonNull public java.util.List<android.os.storage.StorageVolume> getRecentStorageVolumes();
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 0041699df9ef..98b4e0b4f402 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -28,6 +28,8 @@ import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import com.android.internal.os.AppFuseMount;
+import android.app.PendingIntent;
+
/**
* WARNING! Update IMountService.h and IMountService.cpp if you change this
@@ -198,4 +200,5 @@ interface IStorageManager {
void disableAppDataIsolation(in String pkgName, int pid, int userId) = 90;
void notifyAppIoBlocked(in String volumeUuid, int uid, int tid, int reason) = 91;
void notifyAppIoResumed(in String volumeUuid, int uid, int tid, int reason) = 92;
+ PendingIntent getManageSpaceActivityIntent(in String packageName, int requestCode) = 93;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 7c8874cc1ea7..71a849963818 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -49,6 +49,7 @@ import android.app.Activity;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
@@ -701,6 +702,33 @@ public class StorageManager {
}
}
+ /**
+ * Returns a {@link PendingIntent} that can be used by Apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} permission
+ * to launch the manageSpaceActivity for any App that implements it, irrespective of its
+ * exported status.
+ * <p>
+ * Caller has the responsibility of supplying a valid packageName which has
+ * manageSpaceActivity implemented.
+ *
+ * @param packageName package name for the App for which manageSpaceActivity is to be launched
+ * @param requestCode for launching the activity
+ * @return PendingIntent to launch the manageSpaceActivity if successful, null if the
+ * packageName doesn't have a manageSpaceActivity.
+ * @throws IllegalArgumentException an invalid packageName is supplied.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE)
+ @Nullable
+ public PendingIntent getManageSpaceActivityIntent(
+ @NonNull String packageName, int requestCode) {
+ try {
+ return mStorageManager.getManageSpaceActivityIntent(packageName,
+ requestCode);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private ObbInfo getObbInfo(String canonicalPath) {
try {
final ObbInfo obbInfo = ObbScanner.getObbInfo(canonicalPath);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 233a50d417ad..c5233f43dcb9 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -24,6 +24,10 @@ import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_ONE_SHOT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
@@ -55,6 +59,7 @@ import android.app.AnrController;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
+import android.app.PendingIntent;
import android.app.admin.SecurityLog;
import android.app.usage.StorageStatsManager;
import android.content.BroadcastReceiver;
@@ -3371,6 +3376,54 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ /**
+ * Returns PendingIntent which can be used by Apps with MANAGE_EXTERNAL_STORAGE permission
+ * to launch the manageSpaceActivity of the App specified by packageName.
+ */
+ @Override
+ @Nullable
+ public PendingIntent getManageSpaceActivityIntent(
+ @NonNull String packageName, int requestCode) {
+ // Only Apps with MANAGE_EXTERNAL_STORAGE permission should be able to call this API.
+ enforcePermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE);
+
+ // We want to call the manageSpaceActivity as a SystemService and clear identity
+ // of the calling App
+ int originalUid = Binder.getCallingUidOrThrow();
+ long token = Binder.clearCallingIdentity();
+
+ try {
+ ApplicationInfo appInfo = mIPackageManager.getApplicationInfo(packageName, 0,
+ UserHandle.getUserId(originalUid));
+ if (appInfo == null) {
+ throw new IllegalArgumentException(
+ "Invalid packageName");
+ }
+ if (appInfo.manageSpaceActivityName == null) {
+ Log.i(TAG, packageName + " doesn't have a manageSpaceActivity");
+ return null;
+ }
+ Context targetAppContext = mContext.createPackageContext(packageName, 0);
+
+ Intent intent = new Intent(Intent.ACTION_DEFAULT);
+ intent.setClassName(packageName,
+ appInfo.manageSpaceActivityName);
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
+
+ PendingIntent activity = PendingIntent.getActivity(targetAppContext, requestCode,
+ intent,
+ FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE);
+ return activity;
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException(
+ "packageName not found");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
/** Not thread safe */
class AppFuseMountScope extends AppFuseBridge.MountScope {
private boolean mMounted = false;