use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
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 android_frameworks_base by DirtyUnicorns.
the class MountService method format.
@Override
public void format(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
waitForReady();
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
try {
mConnector.execute("volume", "format", vol.id, "auto");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class MountService method shouldBenchmark.
private boolean shouldBenchmark() {
final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(), Settings.Global.STORAGE_BENCHMARK_INTERVAL, -1);
if (benchInterval == -1) {
return false;
} else if (benchInterval == 0) {
return true;
}
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
final VolumeRecord rec = mRecords.get(vol.fsUuid);
if (vol.isMountedWritable() && rec != null) {
final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
if (benchAge >= benchInterval) {
return true;
}
}
}
return false;
}
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class MountService method unmount.
@Override
public void unmount(String volId) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
final VolumeInfo vol = findVolumeByIdOrThrow(volId);
// TODO: expand PMS to know about multiple volumes
if (vol.isPrimaryPhysical()) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mUnmountLock) {
mUnmountSignal = new CountDownLatch(1);
mPms.updateExternalMediaStatus(false, true);
waitForLatch(mUnmountSignal, "mUnmountSignal");
mUnmountSignal = null;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
try {
mConnector.execute("volume", "unmount", vol.id);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
use of android.os.storage.VolumeInfo in project android_frameworks_base by DirtyUnicorns.
the class PackageManagerService method movePackageInternal.
private void movePackageInternal(final String packageName, final String volumeUuid, final int moveId, UserHandle user) throws PackageManagerException {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
final PackageManager pm = mContext.getPackageManager();
final boolean currentAsec;
final String currentVolumeUuid;
final File codeFile;
final String installerPackageName;
final String packageAbiOverride;
final int appId;
final String seinfo;
final String label;
final int targetSdkVersion;
final PackageFreezer freezer;
final int[] installedUserIds;
// reader
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (pkg == null || ps == null) {
throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
}
if (pkg.applicationInfo.isSystemApp()) {
throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, "Cannot move system application");
}
if (pkg.applicationInfo.isExternalAsec()) {
currentAsec = true;
currentVolumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
} else if (pkg.applicationInfo.isForwardLocked()) {
currentAsec = true;
currentVolumeUuid = "forward_locked";
} else {
currentAsec = false;
currentVolumeUuid = ps.volumeUuid;
final File probe = new File(pkg.codePath);
final File probeOat = new File(probe, "oat");
if (!probe.isDirectory() || !probeOat.isDirectory()) {
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move only supported for modern cluster style installs");
}
}
if (Objects.equals(currentVolumeUuid, volumeUuid)) {
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Package already moved to " + volumeUuid);
}
if (pkg.applicationInfo.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) {
throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, "Device admin cannot be moved");
}
if (mFrozenPackages.contains(packageName)) {
throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, "Failed to move already frozen package");
}
codeFile = new File(pkg.codePath);
installerPackageName = ps.installerPackageName;
packageAbiOverride = ps.cpuAbiOverrideString;
appId = UserHandle.getAppId(pkg.applicationInfo.uid);
seinfo = pkg.applicationInfo.seinfo;
label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
freezer = freezePackage(packageName, "movePackageInternal");
installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
final Bundle extras = new Bundle();
extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
extras.putString(Intent.EXTRA_TITLE, label);
mMoveCallbacks.notifyCreated(moveId, extras);
int installFlags;
final boolean moveCompleteApp;
final File measurePath;
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
installFlags = INSTALL_INTERNAL;
moveCompleteApp = !currentAsec;
measurePath = Environment.getDataAppDirectory(volumeUuid);
} else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
installFlags = INSTALL_EXTERNAL;
moveCompleteApp = false;
measurePath = storage.getPrimaryPhysicalVolume().getPath();
} else {
final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid);
if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE || !volume.isMountedWritable()) {
freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move location not mounted private volume");
}
Preconditions.checkState(!currentAsec);
installFlags = INSTALL_INTERNAL;
moveCompleteApp = true;
measurePath = Environment.getDataAppDirectory(volumeUuid);
}
final PackageStats stats = new PackageStats(null, -1);
synchronized (mInstaller) {
for (int userId : installedUserIds) {
if (!getPackageSizeInfoLI(packageName, userId, stats)) {
freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Failed to measure package size");
}
}
}
if (DEBUG_INSTALL)
Slog.d(TAG, "Measured code size " + stats.codeSize + ", data size " + stats.dataSize);
final long startFreeBytes = measurePath.getFreeSpace();
final long sizeBytes;
if (moveCompleteApp) {
sizeBytes = stats.codeSize + stats.dataSize;
} else {
sizeBytes = stats.codeSize;
}
if (sizeBytes > storage.getStorageBytesUntilLow(measurePath)) {
freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Not enough free space to move");
}
mMoveCallbacks.notifyStatusChanged(moveId, 10);
final CountDownLatch installedLatch = new CountDownLatch(1);
final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) throws RemoteException {
throw new IllegalStateException();
}
@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) throws RemoteException {
if (DEBUG_INSTALL)
Slog.d(TAG, "Install result for move: " + PackageManager.installStatusToString(returnCode, msg));
installedLatch.countDown();
freezer.close();
final int status = PackageManager.installStatusToPublicStatus(returnCode);
switch(status) {
case PackageInstaller.STATUS_SUCCESS:
mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_SUCCEEDED);
break;
case PackageInstaller.STATUS_FAILURE_STORAGE:
mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE);
break;
default:
mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR);
break;
}
}
};
final MoveInfo move;
if (moveCompleteApp) {
// Kick off a thread to report progress estimates
new Thread() {
@Override
public void run() {
while (true) {
try {
if (installedLatch.await(1, TimeUnit.SECONDS)) {
break;
}
} catch (InterruptedException ignored) {
}
final long deltaFreeBytes = startFreeBytes - measurePath.getFreeSpace();
final int progress = 10 + (int) MathUtils.constrain(((deltaFreeBytes * 80) / sizeBytes), 0, 80);
mMoveCallbacks.notifyStatusChanged(moveId, progress);
}
}
}.start();
final String dataAppName = codeFile.getName();
move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName, dataAppName, appId, seinfo, targetSdkVersion);
} else {
move = null;
}
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
final Message msg = mHandler.obtainMessage(INIT_COPY);
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
final InstallParams params = new InstallParams(origin, move, installObserver, installFlags, installerPackageName, volumeUuid, null, /*verificationInfo*/
user, packageAbiOverride, null, /*grantedPermissions*/
null);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "movePackage", System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
}
Aggregations