Search in sources :

Example 66 with VolumeInfo

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;
}
Also used : FragmentManager(android.app.FragmentManager) FragmentTransaction(android.app.FragmentTransaction) Bundle(android.os.Bundle) StorageManager(android.os.storage.StorageManager) VolumeInfo(android.os.storage.VolumeInfo) Intent(android.content.Intent) IOException(java.io.IOException) File(java.io.File)

Example 67 with VolumeInfo

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()]);
}
Also used : StorageVolume(android.os.storage.StorageVolume) UserHandle(android.os.UserHandle) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) VolumeInfo(android.os.storage.VolumeInfo) File(java.io.File) AtomicFile(android.util.AtomicFile)

Example 68 with VolumeInfo

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));
}
Also used : DiskInfo(android.os.storage.DiskInfo) VolumeInfo(android.os.storage.VolumeInfo) VolumeRecord(android.os.storage.VolumeRecord) Entry(java.util.Map.Entry) IBinder(android.os.IBinder) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) RemoteCallbackList(android.os.RemoteCallbackList) List(java.util.List) LinkedList(java.util.LinkedList) IndentingPrintWriter(com.android.internal.util.IndentingPrintWriter)

Example 69 with VolumeInfo

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);
}
Also used : VolumeInfo(android.os.storage.VolumeInfo)

Example 70 with VolumeInfo

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);
    }
}
Also used : StorageVolume(android.os.storage.StorageVolume) VolumeInfo(android.os.storage.VolumeInfo)

Aggregations

VolumeInfo (android.os.storage.VolumeInfo)145 StorageManager (android.os.storage.StorageManager)43 File (java.io.File)31 ArrayList (java.util.ArrayList)26 Intent (android.content.Intent)21 CountDownLatch (java.util.concurrent.CountDownLatch)18 DiskInfo (android.os.storage.DiskInfo)16 VolumeRecord (android.os.storage.VolumeRecord)16 Test (org.junit.Test)12 NonNull (android.annotation.NonNull)10 Notification (android.app.Notification)10 PendingIntent (android.app.PendingIntent)10 StorageVolume (android.os.storage.StorageVolume)10 IOException (java.io.IOException)10 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)10 Bundle (android.os.Bundle)9 ApplicationInfo (android.content.pm.ApplicationInfo)8 PackageStats (android.content.pm.PackageStats)8 FragmentManager (android.app.FragmentManager)5 FragmentTransaction (android.app.FragmentTransaction)5