diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 57 | ||||
-rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 12 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageManager.java | 7 | ||||
-rw-r--r-- | core/java/android/os/storage/DiskInfo.java | 15 | ||||
-rw-r--r-- | core/java/android/os/storage/VolumeInfo.java | 36 |
5 files changed, 127 insertions, 0 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 907ae26..e71713a 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -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; @@ -1425,6 +1427,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 { return mPM.getInstallerPackageName(packageName); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 5bdb7bb..caf069f 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -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 */ diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 8844ea8..a128872 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -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. diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index dc96640..2c60d41 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -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) { diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index f06fc8c..a241728 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -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) { |