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

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

Candidate volumes for packages, fix symlink.

Add API to determine the possible candidate volumes that a package
can be moved to.  For example, it currently knows that we need to
move ASEC-based apps through internal storage before migrating them
to a private volume.

Comparator for consistent VolumeInfo ordering when displayed in UI.

Fix native library symlink to be volume UUID aware.

Bug: 19993667
Change-Id: I68d5fac5f0f776ac1c7dd15e7a984bfe2704f3f7
parent 9f09b2d9
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Display;
@@ -1424,6 +1426,61 @@ final class ApplicationPackageManager extends PackageManager {
        }
    }

    @Override
    public @NonNull VolumeInfo getApplicationCurrentVolume(ApplicationInfo app) {
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        if (app.isInternal()) {
            return Preconditions.checkNotNull(
                    storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL));
        } else if (app.isExternalAsec()) {
            final List<VolumeInfo> vols = storage.getVolumes();
            for (VolumeInfo vol : vols) {
                if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isPrimary()) {
                    return vol;
                }
            }
            throw new IllegalStateException("Failed to find primary public volume");
        } else {
            return Preconditions.checkNotNull(storage.findVolumeByUuid(app.volumeUuid));
        }
    }

    @Override
    public @NonNull List<VolumeInfo> getApplicationCandidateVolumes(ApplicationInfo app) {
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        final List<VolumeInfo> vols = storage.getVolumes();
        final List<VolumeInfo> candidates = new ArrayList<>();
        for (VolumeInfo vol : vols) {
            if (isCandidateVolume(app, vol)) {
                candidates.add(vol);
            }
        }
        return candidates;
    }

    private static boolean isCandidateVolume(ApplicationInfo app, VolumeInfo vol) {
        // Private internal is always an option
        if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
            return true;
        }

        // System apps and apps demanding internal storage can't be moved
        // anywhere else
        if (app.isSystemApp()
                || app.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
            return false;
        }

        // Moving into an ASEC on public primary is only an option when app is
        // internal, or already in ASEC
        if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isPrimary()) {
            return app.isInternal() || app.isExternalAsec();
        }

        // Otherwise we can move to any private volume
        return (vol.getType() == VolumeInfo.TYPE_PRIVATE);
    }

    @Override
    public String getInstallerPackageName(String packageName) {
        try {
+12 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Printer;

import com.android.internal.util.ArrayUtils;
@@ -937,6 +938,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
    }

    /** @hide */
    public boolean isInternal() {
        return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
    }

    /** @hide */
    public boolean isExternalAsec() {
        return TextUtils.isEmpty(volumeUuid)
                && (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
    }

    /**
     * @hide
     */
+7 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.CheckResult;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringRes;
@@ -4162,6 +4163,12 @@ public abstract class PackageManager {
    public abstract void movePackageAndData(String packageName, String volumeUuid,
            IPackageMoveObserver observer);

    /** {@hide} */
    public abstract @Nullable VolumeInfo getApplicationCurrentVolume(ApplicationInfo app);

    /** {@hide} */
    public abstract @NonNull List<VolumeInfo> getApplicationCandidateVolumes(ApplicationInfo app);

    /**
     * Returns the device identity that verifiers can use to associate their scheme to a particular
     * device. This should not be used by anything other than a package verifier.
+15 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;

import java.io.CharArrayWriter;
import java.util.Objects;

/**
 * Information about a physical disk which may contain one or more
@@ -118,6 +119,20 @@ public class DiskInfo implements Parcelable {
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof DiskInfo) {
            return Objects.equals(id, ((DiskInfo) o).id);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    public static final Creator<DiskInfo> CREATOR = new Creator<DiskInfo>() {
        @Override
        public DiskInfo createFromParcel(Parcel in) {
+36 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ import com.android.internal.util.Preconditions;

import java.io.CharArrayWriter;
import java.io.File;
import java.util.Comparator;
import java.util.Objects;

/**
 * Information about a storage volume that may be mounted. A volume may be a
@@ -77,6 +79,22 @@ public class VolumeInfo implements Parcelable {
    private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
    private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();

    private static final Comparator<VolumeInfo>
            sDescriptionComparator = new Comparator<VolumeInfo>() {
        @Override
        public int compare(VolumeInfo lhs, VolumeInfo rhs) {
            if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(lhs.getId())) {
                return -1;
            } else if (lhs.getDescription() == null) {
                return 1;
            } else if (rhs.getDescription() == null) {
                return -1;
            } else {
                return lhs.getDescription().compareTo(rhs.getDescription());
            }
        }
    };

    static {
        sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED);
        sStateToEnvironment.put(VolumeInfo.STATE_MOUNTING, Environment.MEDIA_CHECKING);
@@ -150,6 +168,10 @@ public class VolumeInfo implements Parcelable {
        return getBroadcastForEnvironment(getEnvironmentForState(state));
    }

    public static @NonNull Comparator<VolumeInfo> getDescriptionComparator() {
        return sDescriptionComparator;
    }

    public @NonNull String getId() {
        return id;
    }
@@ -344,6 +366,20 @@ public class VolumeInfo implements Parcelable {
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof VolumeInfo) {
            return Objects.equals(id, ((VolumeInfo) o).id);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    public static final Creator<VolumeInfo> CREATOR = new Creator<VolumeInfo>() {
        @Override
        public VolumeInfo createFromParcel(Parcel in) {
Loading