summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2018-12-10 18:28:56 -0700
committer Jeff Sharkey <jsharkey@android.com> 2018-12-11 09:43:13 -0700
commitdc50d4ca389743e6a20af3507b4fa442ed6d07be (patch)
tree7c40b43bd7282b338ba8ce6226853ad29729b285
parent52fe5dd97fb749aad4f570914a22aebf8d0de1c1 (diff)
Iteration on contributed media APIs.
Offer an explicit DELETE_CONTRIBUTED_MEDIA flag that can be used when uninstalling an app to indicate that any contributed media should be deleted. Adjust APIs to accept a specific UserHandle so we can pre-flight check for valid UserManager state. Bug: 116344240 Test: atest android.provider.cts.MediaStoreTest Change-Id: Ief0ba27c913791d60f86a5d7252525c9c4539fc6
-rw-r--r--api/system-current.txt5
-rw-r--r--api/test-current.txt4
-rw-r--r--core/java/android/content/pm/PackageManager.java10
-rw-r--r--core/java/android/provider/MediaStore.java52
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java17
5 files changed, 57 insertions, 31 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 29089b3e908a..36cffbd7c066 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4563,11 +4563,6 @@ package android.provider {
field public static final int FLAG_REMOVABLE_USB = 524288; // 0x80000
}
- public final class MediaStore {
- method public static void deleteContributedMedia(android.content.Context, java.lang.String);
- method public static long getContributedMediaSize(android.content.Context, java.lang.String);
- }
-
public abstract class SearchIndexableData {
ctor public SearchIndexableData();
ctor public SearchIndexableData(android.content.Context);
diff --git a/api/test-current.txt b/api/test-current.txt
index 5bedc7244430..cf0ccebb10bc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1006,8 +1006,8 @@ package android.provider {
}
public final class MediaStore {
- method public static void deleteContributedMedia(android.content.Context, java.lang.String);
- method public static long getContributedMediaSize(android.content.Context, java.lang.String);
+ method public static void deleteContributedMedia(android.content.Context, java.lang.String, android.os.UserHandle) throws java.io.IOException;
+ method public static long getContributedMediaSize(android.content.Context, java.lang.String, android.os.UserHandle) throws java.io.IOException;
}
public final class Settings {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0150f6a2765d..da39b6394f8f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1399,6 +1399,16 @@ public abstract class PackageManager {
public static final int DELETE_DONT_KILL_APP = 0x00000008;
/**
+ * Flag parameter for {@link #deletePackage} to indicate that any
+ * contributed media should also be deleted during this uninstall. The
+ * meaning of "contributed" means it won't automatically be deleted when the
+ * app is uninstalled.
+ *
+ * @hide
+ */
+ public static final int DELETE_CONTRIBUTED_MEDIA = 0x00000010;
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that package deletion
* should be chatty.
*
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 14511657f4d0..7dfd4cd0389e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -23,7 +23,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
@@ -50,6 +49,7 @@ import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
@@ -2882,18 +2882,24 @@ public final class MediaStore {
*
* @hide
*/
- @SystemApi
@TestApi
@RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
- public static @BytesLong long getContributedMediaSize(Context context, String packageName) {
- try (ContentProviderClient client = context.getContentResolver()
- .acquireContentProviderClient(AUTHORITY)) {
- final Bundle in = new Bundle();
- in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
- final Bundle out = client.call(GET_CONTRIBUTED_MEDIA_CALL, null, in);
- return out.getLong(Intent.EXTRA_INDEX);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ public static @BytesLong long getContributedMediaSize(Context context, String packageName,
+ UserHandle user) throws IOException {
+ final UserManager um = context.getSystemService(UserManager.class);
+ if (um.isUserUnlocked(user) && um.isUserRunning(user)) {
+ try {
+ final ContentResolver resolver = context
+ .createPackageContextAsUser(packageName, 0, user).getContentResolver();
+ final Bundle in = new Bundle();
+ in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
+ final Bundle out = resolver.call(AUTHORITY, GET_CONTRIBUTED_MEDIA_CALL, null, in);
+ return out.getLong(Intent.EXTRA_INDEX);
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ } else {
+ throw new IOException("User " + user + " must be unlocked and running");
}
}
@@ -2904,17 +2910,23 @@ public final class MediaStore {
*
* @hide
*/
- @SystemApi
@TestApi
@RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
- public static void deleteContributedMedia(Context context, String packageName) {
- try (ContentProviderClient client = context.getContentResolver()
- .acquireContentProviderClient(AUTHORITY)) {
- final Bundle in = new Bundle();
- in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
- client.call(DELETE_CONTRIBUTED_MEDIA_CALL, null, in);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ public static void deleteContributedMedia(Context context, String packageName,
+ UserHandle user) throws IOException {
+ final UserManager um = context.getSystemService(UserManager.class);
+ if (um.isUserUnlocked(user) && um.isUserRunning(user)) {
+ try {
+ final ContentResolver resolver = context
+ .createPackageContextAsUser(packageName, 0, user).getContentResolver();
+ final Bundle in = new Bundle();
+ in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
+ resolver.call(AUTHORITY, DELETE_CONTRIBUTED_MEDIA_CALL, null, in);
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ } else {
+ throw new IOException("User " + user + " must be unlocked and running");
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 888675c117e1..fde50a3aaa31 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -242,6 +242,7 @@ import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.MediaStore;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.security.KeyStore;
@@ -17936,7 +17937,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int removedUserId = (user != null) ? user.getIdentifier()
: UserHandle.USER_ALL;
- clearPackageStateForUserLIF(ps, removedUserId, outInfo);
+ clearPackageStateForUserLIF(ps, removedUserId, outInfo, flags);
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
return;
@@ -17966,7 +17967,7 @@ public class PackageManagerService extends IPackageManager.Stub
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
- clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
+ clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo, flags);
scheduleWritePackageRestrictionsLocked(user);
return;
} else {
@@ -17982,7 +17983,7 @@ public class PackageManagerService extends IPackageManager.Stub
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
- clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
+ clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo, flags);
scheduleWritePackageRestrictionsLocked(user);
return;
}
@@ -18099,7 +18100,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private void clearPackageStateForUserLIF(PackageSetting ps, int userId,
- PackageRemovedInfo outInfo) {
+ PackageRemovedInfo outInfo, int flags) {
final PackageParser.Package pkg;
synchronized (mPackages) {
pkg = mPackages.get(ps.name);
@@ -18124,6 +18125,14 @@ public class PackageManagerService extends IPackageManager.Stub
}
resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId);
}
+ // Also delete contributed media, when requested
+ if ((flags & PackageManager.DELETE_CONTRIBUTED_MEDIA) != 0) {
+ try {
+ MediaStore.deleteContributedMedia(mContext, ps.name, UserHandle.of(nextUserId));
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to delete contributed media for " + ps.name, e);
+ }
+ }
}
if (outInfo != null) {