use of android.os.storage.VolumeInfo in project platform_frameworks_base by android.
the class OpenExternalDirectoryActivity method showFragment.
/**
* Validates the given path (volume + directory) and display the appropriate dialog asking the
* user to grant access to it.
*/
private static boolean showFragment(OpenExternalDirectoryActivity activity, int userId, StorageVolume storageVolume, String directoryName) {
if (DEBUG)
Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory " + directoryName + ", and user " + userId);
final boolean isRoot = directoryName.equals(DIRECTORY_ROOT);
final boolean isPrimary = storageVolume.isPrimary();
if (isRoot && isPrimary) {
if (DEBUG)
Log.d(TAG, "root access requested on primary volume");
return false;
}
final File volumeRoot = storageVolume.getPathFile();
File file;
try {
file = isRoot ? volumeRoot : new File(volumeRoot, directoryName).getCanonicalFile();
} catch (IOException e) {
Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump() + " and directory " + directoryName);
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
final StorageManager sm = (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE);
final String root, directory;
if (isRoot) {
root = volumeRoot.getAbsolutePath();
directory = ".";
} else {
root = file.getParent();
directory = file.getName();
// Verify directory is valid.
if (TextUtils.isEmpty(directory) || !isStandardDirectory(directory)) {
if (DEBUG)
Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '" + file.getAbsolutePath() + "')");
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
return false;
}
}
// Gets volume label and converted path.
String volumeLabel = null;
String volumeUuid = null;
final List<VolumeInfo> volumes = sm.getVolumes();
if (DEBUG)
Log.d(TAG, "Number of volumes: " + volumes.size());
File internalRoot = null;
boolean found = true;
for (VolumeInfo volume : volumes) {
if (isRightVolume(volume, root, userId)) {
found = true;
internalRoot = volume.getInternalPathForUser(userId);
// Must convert path before calling getDocIdForFileCreateNewDir()
if (DEBUG)
Log.d(TAG, "Converting " + root + " to " + internalRoot);
file = isRoot ? internalRoot : new File(internalRoot, directory);
volumeUuid = storageVolume.getUuid();
volumeLabel = sm.getBestVolumeDescription(volume);
if (TextUtils.isEmpty(volumeLabel)) {
volumeLabel = storageVolume.getDescription(activity);
}
if (TextUtils.isEmpty(volumeLabel)) {
volumeLabel = activity.getString(android.R.string.unknownName);
Log.w(TAG, "No volume description for " + volume + "; using " + volumeLabel);
}
break;
}
}
if (internalRoot == null) {
// Should not happen on normal circumstances, unless app crafted an invalid volume
// using reflection or the list of mounted volumes changed.
Log.e(TAG, "Didn't find right volume for '" + storageVolume.dump() + "' on " + volumes);
return false;
}
// Checks if the user has granted the permission already.
final Intent intent = getIntentForExistingPermission(activity, isRoot, internalRoot, file);
if (intent != null) {
logValidScopedAccessRequest(activity, directory, SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
activity.setResult(RESULT_OK, intent);
activity.finish();
return true;
}
if (!found) {
Log.e(TAG, "Could not get volume for " + file);
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
// Gets the package label.
final String appLabel = getAppLabel(activity);
if (appLabel == null) {
// Error already logged.
return false;
}
// Sets args that will be retrieve on onCreate()
final Bundle args = new Bundle();
args.putString(EXTRA_FILE, file.getAbsolutePath());
args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
args.putString(EXTRA_VOLUME_UUID, volumeUuid);
args.putString(EXTRA_APP_LABEL, appLabel);
args.putBoolean(EXTRA_IS_ROOT, isRoot);
args.putBoolean(EXTRA_IS_PRIMARY, isPrimary);
final FragmentManager fm = activity.getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
final OpenExternalDirectoryDialogFragment fragment = new OpenExternalDirectoryDialogFragment();
fragment.setArguments(args);
ft.add(fragment, FM_TAG);
ft.commitAllowingStateLoss();
return true;
}
use of android.os.storage.VolumeInfo in project platform_frameworks_base by android.
the class MountService method getVolumeList.
@Override
public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
final int userId = UserHandle.getUserId(uid);
final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
final boolean userKeyUnlocked;
final boolean storagePermission;
final long token = Binder.clearCallingIdentity();
try {
userKeyUnlocked = isUserKeyUnlocked(userId);
storagePermission = mMountServiceInternal.hasExternalStorage(uid, packageName);
} finally {
Binder.restoreCallingIdentity(token);
}
boolean foundPrimary = false;
final ArrayList<StorageVolume> res = new ArrayList<>();
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
switch(vol.getType()) {
case VolumeInfo.TYPE_PUBLIC:
case VolumeInfo.TYPE_EMULATED:
break;
default:
continue;
}
boolean match = false;
if (forWrite) {
match = vol.isVisibleForWrite(userId);
} else {
match = vol.isVisibleForRead(userId) || (includeInvisible && vol.getPath() != null);
}
if (!match)
continue;
boolean reportUnmounted = false;
if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
reportUnmounted = true;
} else if (!storagePermission && !realState) {
reportUnmounted = true;
}
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, reportUnmounted);
if (vol.isPrimary()) {
res.add(0, userVol);
foundPrimary = true;
} else {
res.add(userVol);
}
}
}
if (!foundPrimary) {
Log.w(TAG, "No primary storage defined yet; hacking together a stub");
final boolean primaryPhysical = SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false);
final String id = "stub_primary";
final File path = Environment.getLegacyExternalStorageDirectory();
final String description = mContext.getString(android.R.string.unknownName);
final boolean primary = true;
final boolean removable = primaryPhysical;
final boolean emulated = !primaryPhysical;
final long mtpReserveSize = 0L;
final boolean allowMassStorage = false;
final long maxFileSize = 0L;
final UserHandle owner = new UserHandle(userId);
final String uuid = null;
final String state = Environment.MEDIA_REMOVED;
res.add(0, new StorageVolume(id, StorageVolume.STORAGE_ID_INVALID, path, description, primary, removable, emulated, mtpReserveSize, allowMassStorage, maxFileSize, owner, uuid, state));
}
return res.toArray(new StorageVolume[res.size()]);
}
use of android.os.storage.VolumeInfo in project platform_frameworks_base by android.
the class MountService method dump.
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
synchronized (mLock) {
pw.println("Disks:");
pw.increaseIndent();
for (int i = 0; i < mDisks.size(); i++) {
final DiskInfo disk = mDisks.valueAt(i);
disk.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Volumes:");
pw.increaseIndent();
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id))
continue;
vol.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Records:");
pw.increaseIndent();
for (int i = 0; i < mRecords.size(); i++) {
final VolumeRecord note = mRecords.valueAt(i);
note.dump(pw);
}
pw.decreaseIndent();
pw.println();
pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
if (pair == null) {
pw.println("Internal storage total size: N/A");
} else {
pw.print("Internal storage (");
pw.print(pair.first);
pw.print(") total size: ");
pw.print(pair.second);
pw.print(" (");
pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
pw.println(" GB)");
}
pw.println("Force adoptable: " + mForceAdoptable);
pw.println();
pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
}
synchronized (mObbMounts) {
pw.println();
pw.println("mObbMounts:");
pw.increaseIndent();
final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet().iterator();
while (binders.hasNext()) {
Entry<IBinder, List<ObbState>> e = binders.next();
pw.println(e.getKey() + ":");
pw.increaseIndent();
final List<ObbState> obbStates = e.getValue();
for (final ObbState obbState : obbStates) {
pw.println(obbState);
}
pw.decreaseIndent();
}
pw.decreaseIndent();
pw.println();
pw.println("mObbPathToStateMap:");
pw.increaseIndent();
final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
while (maps.hasNext()) {
final Entry<String, ObbState> e = maps.next();
pw.print(e.getKey());
pw.print(" -> ");
pw.println(e.getValue());
}
pw.decreaseIndent();
}
pw.println();
pw.println("mConnector:");
pw.increaseIndent();
mConnector.dump(fd, pw, args);
pw.decreaseIndent();
pw.println();
pw.println("mCryptConnector:");
pw.increaseIndent();
mCryptConnector.dump(fd, pw, args);
pw.decreaseIndent();
pw.println();
pw.print("Last maintenance: ");
pw.println(TimeUtils.formatForLogging(mLastMaintenance));
}
use of android.os.storage.VolumeInfo in project platform_frameworks_base by android.
the class MountService method addInternalVolumeLocked.
private void addInternalVolumeLocked() {
// Create a stub volume that represents internal storage
final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, VolumeInfo.TYPE_PRIVATE, null, null);
internal.state = VolumeInfo.STATE_MOUNTED;
internal.path = Environment.getDataDirectory().getAbsolutePath();
mVolumes.put(internal.id, internal);
}
use of android.os.storage.VolumeInfo in project platform_frameworks_base by android.
the class MountService method onUnlockUser.
private void onUnlockUser(int userId) {
Slog.d(TAG, "onUnlockUser " + userId);
// bind mount against.
try {
mConnector.execute("volume", "user_started", userId);
} catch (NativeDaemonConnectorException ignored) {
}
// correctly, then synthesize events for any already-mounted volumes.
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
}
}
mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
}
}
Aggregations