use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class AppCollectorTest method testAppOnExternalVolume.
@Test
public void testAppOnExternalVolume() throws Exception {
addApplication("com.test.app", "differentuuid");
VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
volume.fsUuid = "testuuid";
AppCollector collector = new AppCollector(mContext, volume);
assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class ExternalStorageProvider method updateVolumesLocked.
private void updateVolumesLocked() {
mRoots.clear();
VolumeInfo primaryVolume = null;
final int userId = UserHandle.myUserId();
final List<VolumeInfo> volumes = mStorageManager.getVolumes();
for (VolumeInfo volume : volumes) {
if (!volume.isMountedReadable())
continue;
final String rootId;
final String title;
if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
// a time, and it's always considered the primary
if (DEBUG)
Log.d(TAG, "Found primary volume: " + volume);
rootId = ROOT_ID_PRIMARY_EMULATED;
if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
// This is basically the user's primary device storage.
// Use device name for the volume since this is likely same thing
// the user sees when they mount their phone on another device.
String deviceName = Settings.Global.getString(getContext().getContentResolver(), Settings.Global.DEVICE_NAME);
// Device name should always be set. In case it isn't, though,
// fall back to a localized "Internal Storage" string.
title = !TextUtils.isEmpty(deviceName) ? deviceName : getContext().getString(R.string.root_internal_storage);
} else {
// This should cover all other storage devices, like an SD card
// or USB OTG drive plugged in. Using getBestVolumeDescription()
// will give us a nice string like "Samsung SD card" or "SanDisk USB drive"
final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
title = mStorageManager.getBestVolumeDescription(privateVol);
}
} else if (volume.getType() == VolumeInfo.TYPE_PUBLIC && volume.getMountUserId() == userId) {
rootId = volume.getFsUuid();
title = mStorageManager.getBestVolumeDescription(volume);
} else {
// Unsupported volume; ignore
continue;
}
if (TextUtils.isEmpty(rootId)) {
Log.d(TAG, "Missing UUID for " + volume.getId() + "; skipping");
continue;
}
if (mRoots.containsKey(rootId)) {
Log.w(TAG, "Duplicate UUID " + rootId + " for " + volume.getId() + "; skipping");
continue;
}
final RootInfo root = new RootInfo();
mRoots.put(rootId, root);
root.rootId = rootId;
root.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
final DiskInfo disk = volume.getDisk();
if (DEBUG)
Log.d(TAG, "Disk for root " + rootId + " is " + disk);
if (disk != null && disk.isSd()) {
root.flags |= Root.FLAG_REMOVABLE_SD;
} else if (disk != null && disk.isUsb()) {
root.flags |= Root.FLAG_REMOVABLE_USB;
}
if (volume.isPrimary()) {
// save off the primary volume for subsequent "Home" dir initialization.
primaryVolume = volume;
root.flags |= Root.FLAG_ADVANCED;
}
// Dunno when this would NOT be the case, but never hurts to be correct.
if (volume.isMountedWritable()) {
root.flags |= Root.FLAG_SUPPORTS_CREATE;
}
root.title = title;
if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
root.flags |= Root.FLAG_HAS_SETTINGS;
}
if (volume.isVisibleForRead(userId)) {
root.visiblePath = volume.getPathForUser(userId);
} else {
root.visiblePath = null;
}
root.path = volume.getInternalPathForUser(userId);
try {
root.docId = getDocIdForFile(root.path);
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
}
}
// by calling either getPathForUser, or getInternalPathForUser.
if (primaryVolume != null && primaryVolume.isVisible()) {
final RootInfo root = new RootInfo();
root.rootId = ROOT_ID_HOME;
mRoots.put(root.rootId, root);
root.title = getContext().getString(R.string.root_documents);
// Only report bytes on *volumes*...as a matter of policy.
root.reportAvailableBytes = false;
root.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
// Dunno when this would NOT be the case, but never hurts to be correct.
if (primaryVolume.isMountedWritable()) {
root.flags |= Root.FLAG_SUPPORTS_CREATE;
}
// Create the "Documents" directory on disk (don't use the localized title).
root.visiblePath = new File(primaryVolume.getPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
root.path = new File(primaryVolume.getInternalPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
try {
root.docId = getDocIdForFile(root.path);
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
}
}
Log.d(TAG, "After updating volumes, found " + mRoots.size() + " active roots");
// Note this affects content://com.android.externalstorage.documents/root/39BD-07C5
// as well as content://com.android.externalstorage.documents/document/*/children,
// so just notify on content://com.android.externalstorage.documents/.
getContext().getContentResolver().notifyChange(BASE_URI, null, false);
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class Sm method runListVolumes.
public void runListVolumes() throws RemoteException {
final String filter = nextArg();
final int filterType;
if ("public".equals(filter)) {
filterType = VolumeInfo.TYPE_PUBLIC;
} else if ("private".equals(filter)) {
filterType = VolumeInfo.TYPE_PRIVATE;
} else if ("emulated".equals(filter)) {
filterType = VolumeInfo.TYPE_EMULATED;
} else {
filterType = -1;
}
final VolumeInfo[] vols = mSm.getVolumes(0);
for (VolumeInfo vol : vols) {
if (filterType == -1 || filterType == vol.getType()) {
final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
System.out.println(vol.getId() + " " + envState + " " + vol.getFsUuid());
}
}
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class PackageHelper method resolveInstallVolume.
/**
* Given a requested {@link PackageInfo#installLocation} and calculated
* install size, pick the actual volume to install the app. Only considers
* internal and private volumes, and prefers to keep an existing package on
* its current volume.
*
* @return the {@link VolumeInfo#fsUuid} to install onto, or {@code null}
* for internal storage.
*/
public static String resolveInstallVolume(Context context, String packageName, int installLocation, long sizeBytes) throws IOException {
final boolean forceAllowOnExternal = Settings.Global.getInt(context.getContentResolver(), Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0;
// TODO: handle existing apps installed in ASEC; currently assumes
// they'll end up back on internal storage
ApplicationInfo existingInfo = null;
try {
existingInfo = context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException ignored) {
}
final StorageManager storageManager = context.getSystemService(StorageManager.class);
final boolean fitsOnInternal = fitsOnInternal(context, sizeBytes);
final ArraySet<String> allCandidates = new ArraySet<>();
VolumeInfo bestCandidate = null;
long bestCandidateAvailBytes = Long.MIN_VALUE;
for (VolumeInfo vol : storageManager.getVolumes()) {
if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.isMountedWritable()) {
final long availBytes = storageManager.getStorageBytesUntilLow(new File(vol.path));
if (availBytes >= sizeBytes) {
allCandidates.add(vol.fsUuid);
}
if (availBytes >= bestCandidateAvailBytes) {
bestCandidate = vol;
bestCandidateAvailBytes = availBytes;
}
}
}
// System apps always forced to internal storage
if (existingInfo != null && existingInfo.isSystemApp()) {
installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
}
// If app expresses strong desire for internal storage, honor it
if (!forceAllowOnExternal && installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
if (existingInfo != null && !Objects.equals(existingInfo.volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
throw new IOException("Cannot automatically move " + packageName + " from " + existingInfo.volumeUuid + " to internal storage");
}
if (fitsOnInternal) {
return StorageManager.UUID_PRIVATE_INTERNAL;
} else {
throw new IOException("Requested internal only, but not enough space");
}
}
// If app already exists somewhere, we must stay on that volume
if (existingInfo != null) {
if (Objects.equals(existingInfo.volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL) && fitsOnInternal) {
return StorageManager.UUID_PRIVATE_INTERNAL;
} else if (allCandidates.contains(existingInfo.volumeUuid)) {
return existingInfo.volumeUuid;
} else {
throw new IOException("Not enough space on existing volume " + existingInfo.volumeUuid + " for " + packageName + " upgrade");
}
}
// volume with most space
if (bestCandidate != null) {
return bestCandidate.fsUuid;
} else if (fitsOnInternal) {
return StorageManager.UUID_PRIVATE_INTERNAL;
} else {
throw new IOException("No special requests, but no room anywhere");
}
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class FileCollector method getSystemSize.
/**
* Returns the size of a system for a given context. This is done by finding the difference
* between the shared data and the total primary storage size.
* @param context Context to use to get storage information.
*/
public static long getSystemSize(Context context) {
PackageManager pm = context.getPackageManager();
VolumeInfo primaryVolume = pm.getPrimaryStorageCurrentVolume();
StorageManager sm = context.getSystemService(StorageManager.class);
VolumeInfo shared = sm.findEmulatedForPrivate(primaryVolume);
if (shared == null) {
return 0;
}
final long sharedDataSize = shared.getPath().getTotalSpace();
long systemSize = sm.getPrimaryStorageSize() - sharedDataSize;
// This case is not exceptional -- we just fallback to the shared data volume in this case.
if (systemSize <= 0) {
return 0;
}
return systemSize;
}
Aggregations