Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc50d4ca authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

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
parent 52fe5dd9
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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 {
+10 −0
Original line number Diff line number Diff line
@@ -1398,6 +1398,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.
+32 −20
Original line number Diff line number Diff line
@@ -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)) {
    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 = client.call(GET_CONTRIBUTED_MEDIA_CALL, null, in);
                final Bundle out = resolver.call(AUTHORITY, GET_CONTRIBUTED_MEDIA_CALL, null, in);
                return out.getLong(Intent.EXTRA_INDEX);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
            } 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)) {
    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);
            client.call(DELETE_CONTRIBUTED_MEDIA_CALL, null, in);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
                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");
        }
    }
}
+13 −4
Original line number Diff line number Diff line
@@ -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) {