am b36586a7: Split some VolumeInfo state into VolumeRecord.
* commit 'b36586a7c9b7718f33961406537e27bbd9b16211': Split some VolumeInfo state into VolumeRecord.
This commit is contained in:
@@ -79,6 +79,7 @@ import android.view.Display;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.UserIcons;
|
||||
|
||||
@@ -2054,8 +2055,7 @@ final class ApplicationPackageManager extends PackageManager {
|
||||
/** {@hide} */
|
||||
private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements
|
||||
Handler.Callback {
|
||||
private static final int MSG_STARTED = 1;
|
||||
private static final int MSG_STATUS_CHANGED = 2;
|
||||
private static final int MSG_STATUS_CHANGED = 1;
|
||||
|
||||
final MoveCallback mCallback;
|
||||
final Handler mHandler;
|
||||
@@ -2067,26 +2067,25 @@ final class ApplicationPackageManager extends PackageManager {
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
final int moveId = msg.arg1;
|
||||
switch (msg.what) {
|
||||
case MSG_STARTED:
|
||||
mCallback.onStarted(moveId, (String) msg.obj);
|
||||
return true;
|
||||
case MSG_STATUS_CHANGED:
|
||||
mCallback.onStatusChanged(moveId, msg.arg2, (long) msg.obj);
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
mCallback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3,
|
||||
(long) args.arg4);
|
||||
args.recycle();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStarted(int moveId, String title) {
|
||||
mHandler.obtainMessage(MSG_STARTED, moveId, 0, title).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(int moveId, int status, long estMillis) {
|
||||
mHandler.obtainMessage(MSG_STATUS_CHANGED, moveId, status, estMillis).sendToTarget();
|
||||
public void onStatusChanged(int moveId, String moveTitle, int status, long estMillis) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.argi1 = moveId;
|
||||
args.arg2 = moveTitle;
|
||||
args.argi3 = status;
|
||||
args.arg4 = estMillis;
|
||||
mHandler.obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,5 @@ package android.content.pm;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IPackageMoveObserver {
|
||||
void onStarted(int moveId, String title);
|
||||
void onStatusChanged(int moveId, int status, long estMillis);
|
||||
void onStatusChanged(int moveId, String moveTitle, int status, long estMillis);
|
||||
}
|
||||
|
||||
@@ -4212,8 +4212,8 @@ public abstract class PackageManager {
|
||||
|
||||
/** {@hide} */
|
||||
public static abstract class MoveCallback {
|
||||
public abstract void onStarted(int moveId, String title);
|
||||
public abstract void onStatusChanged(int moveId, int status, long estMillis);
|
||||
public abstract void onStatusChanged(int moveId, String moveTitle, int status,
|
||||
long estMillis);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
|
||||
@@ -941,6 +941,24 @@ public interface IMountService extends IInterface {
|
||||
return _result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeRecord[] getVolumeRecords(int _flags) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
VolumeRecord[] _result;
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeInt(_flags);
|
||||
mRemote.transact(Stub.TRANSACTION_getVolumeRecords, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = _reply.createTypedArray(VolumeRecord.CREATOR);
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mount(String volId) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
@@ -1033,12 +1051,12 @@ public interface IMountService extends IInterface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolumeNickname(String volId, String nickname) throws RemoteException {
|
||||
public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeString(volId);
|
||||
_data.writeString(fsUuid);
|
||||
_data.writeString(nickname);
|
||||
mRemote.transact(Stub.TRANSACTION_setVolumeNickname, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
@@ -1049,12 +1067,12 @@ public interface IMountService extends IInterface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException {
|
||||
public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeString(volId);
|
||||
_data.writeString(fsUuid);
|
||||
_data.writeInt(flags);
|
||||
_data.writeInt(mask);
|
||||
mRemote.transact(Stub.TRANSACTION_setVolumeUserFlags, _data, _reply, 0);
|
||||
@@ -1065,6 +1083,21 @@ public interface IMountService extends IInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forgetVolume(String fsUuid) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeString(fsUuid);
|
||||
mRemote.transact(Stub.TRANSACTION_forgetVolume, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryStorageUuid() throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
@@ -1192,20 +1225,22 @@ public interface IMountService extends IInterface {
|
||||
|
||||
static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44;
|
||||
static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45;
|
||||
static final int TRANSACTION_getVolumeRecords = IBinder.FIRST_CALL_TRANSACTION + 46;
|
||||
|
||||
static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 46;
|
||||
static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 47;
|
||||
static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 48;
|
||||
static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 47;
|
||||
static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 48;
|
||||
static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 49;
|
||||
|
||||
static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 49;
|
||||
static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 50;
|
||||
static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 51;
|
||||
static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 50;
|
||||
static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 51;
|
||||
static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 52;
|
||||
|
||||
static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 52;
|
||||
static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 53;
|
||||
static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 53;
|
||||
static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 54;
|
||||
static final int TRANSACTION_forgetVolume = IBinder.FIRST_CALL_TRANSACTION + 55;
|
||||
|
||||
static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 54;
|
||||
static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 55;
|
||||
static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 56;
|
||||
static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 57;
|
||||
|
||||
/**
|
||||
* Cast an IBinder object into an IMountService interface, generating a
|
||||
@@ -1647,6 +1682,14 @@ public interface IMountService extends IInterface {
|
||||
reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||||
return true;
|
||||
}
|
||||
case TRANSACTION_getVolumeRecords: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
int _flags = data.readInt();
|
||||
VolumeRecord[] volumes = getVolumeRecords(_flags);
|
||||
reply.writeNoException();
|
||||
reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
|
||||
return true;
|
||||
}
|
||||
case TRANSACTION_mount: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
String volId = data.readString();
|
||||
@@ -1707,6 +1750,13 @@ public interface IMountService extends IInterface {
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
case TRANSACTION_forgetVolume: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
String fsUuid = data.readString();
|
||||
forgetVolume(fsUuid);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
case TRANSACTION_getPrimaryStorageUuid: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
String volumeUuid = getPrimaryStorageUuid();
|
||||
@@ -2012,6 +2062,7 @@ public interface IMountService extends IInterface {
|
||||
|
||||
public DiskInfo[] getDisks() throws RemoteException;
|
||||
public VolumeInfo[] getVolumes(int flags) throws RemoteException;
|
||||
public VolumeRecord[] getVolumeRecords(int flags) throws RemoteException;
|
||||
|
||||
public void mount(String volId) throws RemoteException;
|
||||
public void unmount(String volId) throws RemoteException;
|
||||
@@ -2021,8 +2072,9 @@ public interface IMountService extends IInterface {
|
||||
public void partitionPrivate(String diskId) throws RemoteException;
|
||||
public void partitionMixed(String diskId, int ratio) throws RemoteException;
|
||||
|
||||
public void setVolumeNickname(String volId, String nickname) throws RemoteException;
|
||||
public void setVolumeUserFlags(String volId, int flags, int mask) throws RemoteException;
|
||||
public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException;
|
||||
public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException;
|
||||
public void forgetVolume(String fsUuid) throws RemoteException;
|
||||
|
||||
public String getPrimaryStorageUuid() throws RemoteException;
|
||||
public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
|
||||
|
||||
@@ -93,8 +93,8 @@ public interface IMountServiceListener extends IInterface {
|
||||
}
|
||||
case TRANSACTION_onVolumeMetadataChanged: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
final VolumeInfo vol = (VolumeInfo) data.readParcelable(null);
|
||||
onVolumeMetadataChanged(vol);
|
||||
final String fsUuid = data.readString();
|
||||
onVolumeMetadataChanged(fsUuid);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
@@ -192,12 +192,12 @@ public interface IMountServiceListener extends IInterface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException {
|
||||
public void onVolumeMetadataChanged(String fsUuid) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeParcelable(vol, 0);
|
||||
_data.writeString(fsUuid);
|
||||
mRemote.transact(Stub.TRANSACTION_onVolumeMetadataChanged, _data, _reply,
|
||||
android.os.IBinder.FLAG_ONEWAY);
|
||||
_reply.readException();
|
||||
@@ -253,7 +253,7 @@ public interface IMountServiceListener extends IInterface {
|
||||
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState)
|
||||
throws RemoteException;
|
||||
|
||||
public void onVolumeMetadataChanged(VolumeInfo vol) throws RemoteException;
|
||||
public void onVolumeMetadataChanged(String fsUuid) throws RemoteException;
|
||||
|
||||
public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class StorageEventListener {
|
||||
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
|
||||
}
|
||||
|
||||
public void onVolumeMetadataChanged(VolumeInfo vol) {
|
||||
public void onVolumeMetadataChanged(String fsUuid) {
|
||||
}
|
||||
|
||||
public void onDiskScanned(DiskInfo disk, int volumeCount) {
|
||||
|
||||
@@ -79,9 +79,6 @@ public class StorageManager {
|
||||
/** {@hide} */
|
||||
public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
|
||||
|
||||
/** {@hide} */
|
||||
public static final int FLAG_ALL_METADATA = 1 << 0;
|
||||
|
||||
private final Context mContext;
|
||||
private final ContentResolver mResolver;
|
||||
|
||||
@@ -120,7 +117,7 @@ public class StorageManager {
|
||||
args.recycle();
|
||||
return true;
|
||||
case MSG_VOLUME_METADATA_CHANGED:
|
||||
mCallback.onVolumeMetadataChanged((VolumeInfo) args.arg1);
|
||||
mCallback.onVolumeMetadataChanged((String) args.arg1);
|
||||
args.recycle();
|
||||
return true;
|
||||
case MSG_DISK_SCANNED:
|
||||
@@ -156,9 +153,9 @@ public class StorageManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVolumeMetadataChanged(VolumeInfo vol) {
|
||||
public void onVolumeMetadataChanged(String fsUuid) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = vol;
|
||||
args.arg1 = fsUuid;
|
||||
mHandler.obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget();
|
||||
}
|
||||
|
||||
@@ -515,6 +512,18 @@ public class StorageManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public @Nullable VolumeRecord findRecordByUuid(String fsUuid) {
|
||||
Preconditions.checkNotNull(fsUuid);
|
||||
// TODO; go directly to service to make this faster
|
||||
for (VolumeRecord rec : getVolumeRecords()) {
|
||||
if (Objects.equals(rec.fsUuid, fsUuid)) {
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public @Nullable VolumeInfo findPrivateForEmulated(VolumeInfo emulatedVol) {
|
||||
return findVolumeById(emulatedVol.getId().replace("emulated", "private"));
|
||||
@@ -527,13 +536,17 @@ public class StorageManager {
|
||||
|
||||
/** {@hide} */
|
||||
public @NonNull List<VolumeInfo> getVolumes() {
|
||||
return getVolumes(0);
|
||||
try {
|
||||
return Arrays.asList(mMountService.getVolumes(0));
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public @NonNull List<VolumeInfo> getVolumes(int flags) {
|
||||
public @NonNull List<VolumeRecord> getVolumeRecords() {
|
||||
try {
|
||||
return Arrays.asList(mMountService.getVolumes(flags));
|
||||
return Arrays.asList(mMountService.getVolumeRecords(0));
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
@@ -541,13 +554,23 @@ public class StorageManager {
|
||||
|
||||
/** {@hide} */
|
||||
public @Nullable String getBestVolumeDescription(VolumeInfo vol) {
|
||||
String descrip = vol.getDescription();
|
||||
if (vol.disk != null) {
|
||||
if (TextUtils.isEmpty(descrip)) {
|
||||
descrip = vol.disk.getDescription();
|
||||
// Nickname always takes precedence when defined
|
||||
if (!TextUtils.isEmpty(vol.fsUuid)) {
|
||||
final VolumeRecord rec = findRecordByUuid(vol.fsUuid);
|
||||
if (!TextUtils.isEmpty(rec.nickname)) {
|
||||
return rec.nickname;
|
||||
}
|
||||
}
|
||||
return descrip;
|
||||
|
||||
if (!TextUtils.isEmpty(vol.getDescription())) {
|
||||
return vol.getDescription();
|
||||
}
|
||||
|
||||
if (vol.disk != null) {
|
||||
return vol.disk.getDescription();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
@@ -616,29 +639,38 @@ public class StorageManager {
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void setVolumeNickname(String volId, String nickname) {
|
||||
public void setVolumeNickname(String fsUuid, String nickname) {
|
||||
try {
|
||||
mMountService.setVolumeNickname(volId, nickname);
|
||||
mMountService.setVolumeNickname(fsUuid, nickname);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void setVolumeInited(String volId, boolean inited) {
|
||||
public void setVolumeInited(String fsUuid, boolean inited) {
|
||||
try {
|
||||
mMountService.setVolumeUserFlags(volId, inited ? VolumeInfo.USER_FLAG_INITED : 0,
|
||||
VolumeInfo.USER_FLAG_INITED);
|
||||
mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
|
||||
VolumeRecord.USER_FLAG_INITED);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void setVolumeSnoozed(String volId, boolean snoozed) {
|
||||
public void setVolumeSnoozed(String fsUuid, boolean snoozed) {
|
||||
try {
|
||||
mMountService.setVolumeUserFlags(volId, snoozed ? VolumeInfo.USER_FLAG_SNOOZED : 0,
|
||||
VolumeInfo.USER_FLAG_SNOOZED);
|
||||
mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
|
||||
VolumeRecord.USER_FLAG_SNOOZED);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void forgetVolume(String fsUuid) {
|
||||
try {
|
||||
mMountService.forgetVolume(fsUuid);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
|
||||
@@ -78,9 +78,6 @@ public class VolumeInfo implements Parcelable {
|
||||
public static final int MOUNT_FLAG_PRIMARY = 1 << 0;
|
||||
public static final int MOUNT_FLAG_VISIBLE = 1 << 1;
|
||||
|
||||
public static final int USER_FLAG_INITED = 1 << 0;
|
||||
public static final int USER_FLAG_SNOOZED = 1 << 1;
|
||||
|
||||
private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
|
||||
private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
|
||||
|
||||
@@ -135,8 +132,6 @@ public class VolumeInfo implements Parcelable {
|
||||
|
||||
/** Framework state */
|
||||
public final int mtpIndex;
|
||||
public String nickname;
|
||||
public int userFlags = 0;
|
||||
|
||||
public VolumeInfo(String id, int type, DiskInfo disk, int mtpIndex) {
|
||||
this.id = Preconditions.checkNotNull(id);
|
||||
@@ -161,8 +156,6 @@ public class VolumeInfo implements Parcelable {
|
||||
fsLabel = parcel.readString();
|
||||
path = parcel.readString();
|
||||
mtpIndex = parcel.readInt();
|
||||
nickname = parcel.readString();
|
||||
userFlags = parcel.readInt();
|
||||
}
|
||||
|
||||
public static @NonNull String getEnvironmentForState(int state) {
|
||||
@@ -210,10 +203,6 @@ public class VolumeInfo implements Parcelable {
|
||||
return fsUuid;
|
||||
}
|
||||
|
||||
public @Nullable String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public int getMountUserId() {
|
||||
return mountUserId;
|
||||
}
|
||||
@@ -221,8 +210,6 @@ public class VolumeInfo implements Parcelable {
|
||||
public @Nullable String getDescription() {
|
||||
if (ID_PRIVATE_INTERNAL.equals(id)) {
|
||||
return Resources.getSystem().getString(com.android.internal.R.string.storage_internal);
|
||||
} else if (!TextUtils.isEmpty(nickname)) {
|
||||
return nickname;
|
||||
} else if (!TextUtils.isEmpty(fsLabel)) {
|
||||
return fsLabel;
|
||||
} else {
|
||||
@@ -250,14 +237,6 @@ public class VolumeInfo implements Parcelable {
|
||||
return (mountFlags & MOUNT_FLAG_VISIBLE) != 0;
|
||||
}
|
||||
|
||||
public boolean isInited() {
|
||||
return (userFlags & USER_FLAG_INITED) != 0;
|
||||
}
|
||||
|
||||
public boolean isSnoozed() {
|
||||
return (userFlags & USER_FLAG_SNOOZED) != 0;
|
||||
}
|
||||
|
||||
public boolean isVisibleToUser(int userId) {
|
||||
if (type == TYPE_PUBLIC && userId == this.mountUserId) {
|
||||
return isVisible();
|
||||
@@ -394,8 +373,6 @@ public class VolumeInfo implements Parcelable {
|
||||
pw.println();
|
||||
pw.printPair("path", path);
|
||||
pw.printPair("mtpIndex", mtpIndex);
|
||||
pw.printPair("nickname", nickname);
|
||||
pw.printPair("userFlags", DebugUtils.flagsToString(getClass(), "USER_FLAG_", userFlags));
|
||||
pw.decreaseIndent();
|
||||
pw.println();
|
||||
}
|
||||
@@ -461,7 +438,5 @@ public class VolumeInfo implements Parcelable {
|
||||
parcel.writeString(fsLabel);
|
||||
parcel.writeString(path);
|
||||
parcel.writeInt(mtpIndex);
|
||||
parcel.writeString(nickname);
|
||||
parcel.writeInt(userFlags);
|
||||
}
|
||||
}
|
||||
|
||||
139
core/java/android/os/storage/VolumeRecord.java
Normal file
139
core/java/android/os/storage/VolumeRecord.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os.storage;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.DebugUtils;
|
||||
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Notes for a storage volume which may not be currently present.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class VolumeRecord implements Parcelable {
|
||||
public static final String EXTRA_FS_UUID =
|
||||
"android.os.storage.extra.FS_UUID";
|
||||
|
||||
public static final int USER_FLAG_INITED = 1 << 0;
|
||||
public static final int USER_FLAG_SNOOZED = 1 << 1;
|
||||
|
||||
public final int type;
|
||||
public final String fsUuid;
|
||||
public String nickname;
|
||||
public int userFlags;
|
||||
|
||||
public VolumeRecord(int type, String fsUuid) {
|
||||
this.type = type;
|
||||
this.fsUuid = Preconditions.checkNotNull(fsUuid);
|
||||
}
|
||||
|
||||
public VolumeRecord(Parcel parcel) {
|
||||
type = parcel.readInt();
|
||||
fsUuid = parcel.readString();
|
||||
nickname = parcel.readString();
|
||||
userFlags = parcel.readInt();
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getFsUuid() {
|
||||
return fsUuid;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public boolean isInited() {
|
||||
return (userFlags & USER_FLAG_INITED) != 0;
|
||||
}
|
||||
|
||||
public boolean isSnoozed() {
|
||||
return (userFlags & USER_FLAG_SNOOZED) != 0;
|
||||
}
|
||||
|
||||
public void dump(IndentingPrintWriter pw) {
|
||||
pw.println("VolumeRecord:");
|
||||
pw.increaseIndent();
|
||||
pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type));
|
||||
pw.printPair("fsUuid", fsUuid);
|
||||
pw.printPair("nickname", nickname);
|
||||
pw.printPair("userFlags",
|
||||
DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags));
|
||||
pw.decreaseIndent();
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeRecord clone() {
|
||||
final Parcel temp = Parcel.obtain();
|
||||
try {
|
||||
writeToParcel(temp, 0);
|
||||
temp.setDataPosition(0);
|
||||
return CREATOR.createFromParcel(temp);
|
||||
} finally {
|
||||
temp.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof VolumeRecord) {
|
||||
return Objects.equals(fsUuid, ((VolumeRecord) o).fsUuid);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fsUuid.hashCode();
|
||||
}
|
||||
|
||||
public static final Creator<VolumeRecord> CREATOR = new Creator<VolumeRecord>() {
|
||||
@Override
|
||||
public VolumeRecord createFromParcel(Parcel in) {
|
||||
return new VolumeRecord(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeRecord[] newArray(int size) {
|
||||
return new VolumeRecord[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeInt(type);
|
||||
parcel.writeString(fsUuid);
|
||||
parcel.writeString(nickname);
|
||||
parcel.writeInt(userFlags);
|
||||
}
|
||||
}
|
||||
@@ -3012,6 +3012,26 @@
|
||||
<!-- Notification action to browse external media [CHAR LIMIT=20] -->
|
||||
<string name="ext_media_browse_action">Explore</string>
|
||||
|
||||
<!-- Notification title when external media is missing [CHAR LIMIT=30] -->
|
||||
<string name="ext_media_missing_title"><xliff:g id="name" example="SD card">%s</xliff:g> missing</string>
|
||||
<!-- Notification body when external media is missing [CHAR LIMIT=30] -->
|
||||
<string name="ext_media_missing_message">Reinsert this device</string>
|
||||
|
||||
<!-- Notification title when moving an application to external storage [CHAR LIMIT=30] -->
|
||||
<string name="ext_media_move_specific_title">Moving <xliff:g id="name" example="Calculator">%s</xliff:g></string>
|
||||
<!-- Notification title when moving data to external storage [CHAR LIMIT=32] -->
|
||||
<string name="ext_media_move_title">Moving data</string>
|
||||
|
||||
<!-- Notification title when moving data to external storage [CHAR LIMIT=32] -->
|
||||
<string name="ext_media_move_success_title">Move complete</string>
|
||||
<!-- Notification title when moving data to external storage [CHAR LIMIT=64] -->
|
||||
<string name="ext_media_move_success_message">Data moved to <xliff:g id="name" example="SD card">%s</xliff:g></string>
|
||||
|
||||
<!-- Notification title when moving data to external storage failed [CHAR LIMIT=32] -->
|
||||
<string name="ext_media_move_failure_title">Couldn\'t move data</string>
|
||||
<!-- Notification title when moving data to external storage failed [CHAR LIMIT=64] -->
|
||||
<string name="ext_media_move_failure_message">Data left at original location</string>
|
||||
|
||||
<!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. -->
|
||||
<string name="activity_list_empty">No matching activities found.</string>
|
||||
|
||||
|
||||
@@ -1899,6 +1899,14 @@
|
||||
<java-symbol type="string" name="ext_media_init_action" />
|
||||
<java-symbol type="string" name="ext_media_unmount_action" />
|
||||
<java-symbol type="string" name="ext_media_browse_action" />
|
||||
<java-symbol type="string" name="ext_media_missing_title" />
|
||||
<java-symbol type="string" name="ext_media_missing_message" />
|
||||
<java-symbol type="string" name="ext_media_move_specific_title" />
|
||||
<java-symbol type="string" name="ext_media_move_title" />
|
||||
<java-symbol type="string" name="ext_media_move_success_title" />
|
||||
<java-symbol type="string" name="ext_media_move_success_message" />
|
||||
<java-symbol type="string" name="ext_media_move_failure_title" />
|
||||
<java-symbol type="string" name="ext_media_move_failure_message" />
|
||||
<java-symbol type="string" name="usb_storage_error_message" />
|
||||
<java-symbol type="string" name="usb_storage_message" />
|
||||
<java-symbol type="string" name="usb_storage_notification_message" />
|
||||
|
||||
@@ -24,11 +24,17 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.MoveCallback;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.storage.DiskInfo;
|
||||
import android.os.storage.StorageEventListener;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.os.storage.VolumeRecord;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -39,12 +45,14 @@ import java.util.List;
|
||||
public class StorageNotification extends SystemUI {
|
||||
private static final String TAG = "StorageNotification";
|
||||
|
||||
private static final int NOTIF_ID = 0x53544f52; // STOR
|
||||
private static final int PUBLIC_ID = 0x53505542; // SPUB
|
||||
private static final int PRIVATE_ID = 0x53505256; // SPRV
|
||||
private static final int DISK_ID = 0x5344534b; // SDSK
|
||||
private static final int MOVE_ID = 0x534d4f56; // SMOV
|
||||
|
||||
private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME";
|
||||
|
||||
// TODO: delay some notifications to avoid bumpy fast operations
|
||||
// TODO: annoy user when private media is missing
|
||||
|
||||
private NotificationManager mNotificationManager;
|
||||
private StorageManager mStorageManager;
|
||||
@@ -52,17 +60,29 @@ public class StorageNotification extends SystemUI {
|
||||
private final StorageEventListener mListener = new StorageEventListener() {
|
||||
@Override
|
||||
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
|
||||
onVolumeStateChangedInternal(vol, oldState, newState);
|
||||
onVolumeStateChangedInternal(vol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVolumeMetadataChanged(VolumeInfo vol) {
|
||||
public void onVolumeMetadataChanged(String fsUuid) {
|
||||
// Avoid kicking notifications when getting early metadata before
|
||||
// mounted. If already mounted, we're being kicked because of a
|
||||
// nickname or init'ed change.
|
||||
if (vol.isMountedReadable()) {
|
||||
onVolumeStateChangedInternal(vol, vol.getState(), vol.getState());
|
||||
final VolumeInfo vol = mStorageManager.findVolumeByUuid(fsUuid);
|
||||
if (vol != null && vol.isMountedReadable()) {
|
||||
onVolumeStateChangedInternal(vol);
|
||||
}
|
||||
|
||||
final VolumeRecord rec = mStorageManager.findRecordByUuid(fsUuid);
|
||||
if (rec == null) {
|
||||
// Private volume was probably just forgotten
|
||||
mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDiskScanned(DiskInfo disk, int volumeCount) {
|
||||
onDiskScannedInternal(disk, volumeCount);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,8 +90,19 @@ public class StorageNotification extends SystemUI {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
// TODO: kick this onto background thread
|
||||
final String volId = intent.getStringExtra(VolumeInfo.EXTRA_VOLUME_ID);
|
||||
mStorageManager.setVolumeSnoozed(volId, true);
|
||||
final String fsUuid = intent.getStringExtra(VolumeRecord.EXTRA_FS_UUID);
|
||||
mStorageManager.setVolumeSnoozed(fsUuid, true);
|
||||
}
|
||||
};
|
||||
|
||||
private final MoveCallback mMoveCallback = new MoveCallback() {
|
||||
@Override
|
||||
public void onStatusChanged(int moveId, String moveTitle, int status, long estMillis) {
|
||||
if (PackageManager.isMoveStatusFinished(status)) {
|
||||
onMoveFinished(moveId, moveTitle, status);
|
||||
} else {
|
||||
onMoveProgress(moveId, moveTitle, status, estMillis);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,20 +119,99 @@ public class StorageNotification extends SystemUI {
|
||||
// Kick current state into place
|
||||
final List<VolumeInfo> vols = mStorageManager.getVolumes();
|
||||
for (VolumeInfo vol : vols) {
|
||||
onVolumeStateChangedInternal(vol, vol.getState(), vol.getState());
|
||||
onVolumeStateChangedInternal(vol);
|
||||
}
|
||||
|
||||
mContext.getPackageManager().registerMoveCallback(mMoveCallback, new Handler());
|
||||
|
||||
updateMissingPrivateVolumes();
|
||||
}
|
||||
|
||||
private void updateMissingPrivateVolumes() {
|
||||
final List<VolumeRecord> recs = mStorageManager.getVolumeRecords();
|
||||
for (VolumeRecord rec : recs) {
|
||||
if (rec.getType() != VolumeInfo.TYPE_PRIVATE) continue;
|
||||
|
||||
final String fsUuid = rec.getFsUuid();
|
||||
final VolumeInfo info = mStorageManager.findVolumeByUuid(fsUuid);
|
||||
if (info != null && info.isMountedWritable()) {
|
||||
// Yay, private volume is here!
|
||||
mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL);
|
||||
|
||||
} else {
|
||||
// Boo, annoy the user to reinsert the private volume
|
||||
final CharSequence title = mContext.getString(R.string.ext_media_missing_title,
|
||||
rec.getNickname());
|
||||
final CharSequence text = mContext.getString(R.string.ext_media_missing_message);
|
||||
|
||||
final Notification notif = new Notification.Builder(mContext)
|
||||
.setSmallIcon(R.drawable.stat_notify_sdcard)
|
||||
.setColor(mContext.getColor(R.color.system_notification_accent_color))
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setStyle(new Notification.BigTextStyle().bigText(text))
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setLocalOnly(true)
|
||||
.setContentIntent(buildForgetPendingIntent(rec))
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.setOngoing(true)
|
||||
.build();
|
||||
|
||||
mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, notif, UserHandle.ALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onVolumeStateChangedInternal(VolumeInfo vol, int oldState, int newState) {
|
||||
// We only care about public volumes
|
||||
if (vol.getType() != VolumeInfo.TYPE_PUBLIC) {
|
||||
return;
|
||||
}
|
||||
private void onDiskScannedInternal(DiskInfo disk, int volumeCount) {
|
||||
if (volumeCount == 0) {
|
||||
// No supported volumes found, give user option to format
|
||||
final CharSequence title = mContext.getString(
|
||||
R.string.ext_media_unmountable_notification_title, disk.getDescription());
|
||||
final CharSequence text = mContext.getString(
|
||||
R.string.ext_media_unmountable_notification_message, disk.getDescription());
|
||||
|
||||
Log.d(TAG, vol.toString());
|
||||
final Notification notif = new Notification.Builder(mContext)
|
||||
.setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
|
||||
.setColor(mContext.getColor(R.color.system_notification_accent_color))
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setStyle(new Notification.BigTextStyle().bigText(text))
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setLocalOnly(true)
|
||||
.setContentIntent(buildInitPendingIntent(disk))
|
||||
.setCategory(Notification.CATEGORY_ERROR)
|
||||
.build();
|
||||
|
||||
mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, notif, UserHandle.ALL);
|
||||
|
||||
} else {
|
||||
// Yay, we have volumes!
|
||||
mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
private void onVolumeStateChangedInternal(VolumeInfo vol) {
|
||||
switch (vol.getType()) {
|
||||
case VolumeInfo.TYPE_PRIVATE:
|
||||
onPrivateVolumeStateChangedInternal(vol);
|
||||
break;
|
||||
case VolumeInfo.TYPE_PUBLIC:
|
||||
onPublicVolumeStateChangedInternal(vol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void onPrivateVolumeStateChangedInternal(VolumeInfo vol) {
|
||||
Log.d(TAG, "Notifying about private volume: " + vol.toString());
|
||||
|
||||
updateMissingPrivateVolumes();
|
||||
}
|
||||
|
||||
private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
|
||||
Log.d(TAG, "Notifying about public volume: " + vol.toString());
|
||||
|
||||
final Notification notif;
|
||||
switch (newState) {
|
||||
switch (vol.getState()) {
|
||||
case VolumeInfo.STATE_UNMOUNTED:
|
||||
notif = onVolumeUnmounted(vol);
|
||||
break;
|
||||
@@ -133,9 +243,9 @@ public class StorageNotification extends SystemUI {
|
||||
}
|
||||
|
||||
if (notif != null) {
|
||||
mNotificationManager.notifyAsUser(vol.getId(), NOTIF_ID, notif, UserHandle.ALL);
|
||||
mNotificationManager.notifyAsUser(vol.getId(), PUBLIC_ID, notif, UserHandle.ALL);
|
||||
} else {
|
||||
mNotificationManager.cancelAsUser(vol.getId(), NOTIF_ID, UserHandle.ALL);
|
||||
mNotificationManager.cancelAsUser(vol.getId(), PUBLIC_ID, UserHandle.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,20 +269,24 @@ public class StorageNotification extends SystemUI {
|
||||
}
|
||||
|
||||
private Notification onVolumeMounted(VolumeInfo vol) {
|
||||
final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid());
|
||||
|
||||
// Don't annoy when user dismissed in past
|
||||
if (vol.isSnoozed()) return null;
|
||||
if (rec.isSnoozed()) return null;
|
||||
|
||||
final DiskInfo disk = vol.getDisk();
|
||||
if (disk.isAdoptable() && !vol.isInited()) {
|
||||
if (disk.isAdoptable() && !rec.isInited()) {
|
||||
final CharSequence title = disk.getDescription();
|
||||
final CharSequence text = mContext.getString(
|
||||
R.string.ext_media_new_notification_message, disk.getDescription());
|
||||
|
||||
final PendingIntent initAction = buildInitPendingIntent(vol);
|
||||
return buildNotificationBuilder(vol, title, text)
|
||||
.addAction(new Action(0, mContext.getString(R.string.ext_media_init_action),
|
||||
buildInitPendingIntent(vol)))
|
||||
initAction))
|
||||
.addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action),
|
||||
buildUnmountPendingIntent(vol)))
|
||||
.setContentIntent(initAction)
|
||||
.setDeleteIntent(buildSnoozeIntent(vol))
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.build();
|
||||
@@ -182,11 +296,13 @@ public class StorageNotification extends SystemUI {
|
||||
final CharSequence text = mContext.getString(
|
||||
R.string.ext_media_ready_notification_message, disk.getDescription());
|
||||
|
||||
final PendingIntent browseAction = buildBrowsePendingIntent(vol);
|
||||
return buildNotificationBuilder(vol, title, text)
|
||||
.addAction(new Action(0, mContext.getString(R.string.ext_media_browse_action),
|
||||
buildBrowsePendingIntent(vol)))
|
||||
browseAction))
|
||||
.addAction(new Action(0, mContext.getString(R.string.ext_media_unmount_action),
|
||||
buildUnmountPendingIntent(vol)))
|
||||
.setContentIntent(browseAction)
|
||||
.setDeleteIntent(buildSnoozeIntent(vol))
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.setPriority(Notification.PRIORITY_LOW)
|
||||
@@ -260,16 +376,84 @@ public class StorageNotification extends SystemUI {
|
||||
.build();
|
||||
}
|
||||
|
||||
private int getSmallIcon(VolumeInfo vol) {
|
||||
if (vol.disk.isSd()) {
|
||||
switch (vol.getState()) {
|
||||
private void onMoveProgress(int moveId, String moveTitle, int status, long estMillis) {
|
||||
final CharSequence title;
|
||||
if (!TextUtils.isEmpty(moveTitle)) {
|
||||
title = mContext.getString(R.string.ext_media_move_specific_title, moveTitle);
|
||||
} else {
|
||||
title = mContext.getString(R.string.ext_media_move_title);
|
||||
}
|
||||
|
||||
final CharSequence text;
|
||||
if (estMillis < 0) {
|
||||
text = null;
|
||||
} else {
|
||||
text = DateUtils.formatDuration(estMillis);
|
||||
}
|
||||
|
||||
final Notification notif = new Notification.Builder(mContext)
|
||||
.setSmallIcon(R.drawable.stat_notify_sdcard)
|
||||
.setColor(mContext.getColor(R.color.system_notification_accent_color))
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setStyle(new Notification.BigTextStyle().bigText(text))
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setLocalOnly(true)
|
||||
.setCategory(Notification.CATEGORY_PROGRESS)
|
||||
.setPriority(Notification.PRIORITY_LOW)
|
||||
.setProgress(100, status, false)
|
||||
.setOngoing(true)
|
||||
.build();
|
||||
|
||||
mNotificationManager.notifyAsUser(moveTitle, MOVE_ID, notif, UserHandle.ALL);
|
||||
}
|
||||
|
||||
private void onMoveFinished(int moveId, String moveTitle, int status) {
|
||||
if (!TextUtils.isEmpty(moveTitle)) {
|
||||
// We currently ignore finished app moves; just clear the last
|
||||
// published progress
|
||||
mNotificationManager.cancelAsUser(moveTitle, MOVE_ID, UserHandle.ALL);
|
||||
return;
|
||||
}
|
||||
|
||||
final VolumeInfo vol = mContext.getPackageManager().getPrimaryStorageCurrentVolume();
|
||||
final String descrip = mStorageManager.getBestVolumeDescription(vol);
|
||||
|
||||
final CharSequence title;
|
||||
final CharSequence text;
|
||||
if (status == PackageManager.MOVE_SUCCEEDED) {
|
||||
title = mContext.getString(R.string.ext_media_move_success_title);
|
||||
text = mContext.getString(R.string.ext_media_move_success_message, descrip);
|
||||
} else {
|
||||
title = mContext.getString(R.string.ext_media_move_failure_title);
|
||||
text = mContext.getString(R.string.ext_media_move_failure_message);
|
||||
}
|
||||
|
||||
final Notification notif = new Notification.Builder(mContext)
|
||||
.setSmallIcon(R.drawable.stat_notify_sdcard)
|
||||
.setColor(mContext.getColor(R.color.system_notification_accent_color))
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setStyle(new Notification.BigTextStyle().bigText(text))
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setLocalOnly(true)
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.setPriority(Notification.PRIORITY_LOW)
|
||||
.build();
|
||||
|
||||
mNotificationManager.notifyAsUser(moveTitle, MOVE_ID, notif, UserHandle.ALL);
|
||||
}
|
||||
|
||||
private int getSmallIcon(DiskInfo disk, int state) {
|
||||
if (disk.isSd()) {
|
||||
switch (state) {
|
||||
case VolumeInfo.STATE_CHECKING:
|
||||
case VolumeInfo.STATE_EJECTING:
|
||||
return R.drawable.stat_notify_sdcard_prepare;
|
||||
default:
|
||||
return R.drawable.stat_notify_sdcard;
|
||||
}
|
||||
} else if (vol.disk.isUsb()) {
|
||||
} else if (disk.isUsb()) {
|
||||
return R.drawable.stat_sys_data_usb;
|
||||
} else {
|
||||
return R.drawable.stat_notify_sdcard;
|
||||
@@ -279,7 +463,7 @@ public class StorageNotification extends SystemUI {
|
||||
private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
|
||||
CharSequence text) {
|
||||
return new Notification.Builder(mContext)
|
||||
.setSmallIcon(getSmallIcon(vol))
|
||||
.setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
|
||||
.setColor(mContext.getColor(R.color.system_notification_accent_color))
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
@@ -288,6 +472,17 @@ public class StorageNotification extends SystemUI {
|
||||
.setLocalOnly(true);
|
||||
}
|
||||
|
||||
private PendingIntent buildInitPendingIntent(DiskInfo disk) {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
"com.android.settings.deviceinfo.StorageWizardInit");
|
||||
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.getId());
|
||||
|
||||
final int requestKey = disk.getId().hashCode();
|
||||
return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
private PendingIntent buildInitPendingIntent(VolumeInfo vol) {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
@@ -321,7 +516,7 @@ public class StorageNotification extends SystemUI {
|
||||
private PendingIntent buildDetailsPendingIntent(VolumeInfo vol) {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
"com.android.settings.Settings$StorageVolumeSettingsActivity");
|
||||
"com.android.settings.Settings$PublicVolumeSettingsActivity");
|
||||
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
|
||||
|
||||
final int requestKey = vol.getId().hashCode();
|
||||
@@ -331,10 +526,21 @@ public class StorageNotification extends SystemUI {
|
||||
|
||||
private PendingIntent buildSnoozeIntent(VolumeInfo vol) {
|
||||
final Intent intent = new Intent(ACTION_SNOOZE_VOLUME);
|
||||
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
|
||||
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.getFsUuid());
|
||||
|
||||
final int requestKey = vol.getId().hashCode();
|
||||
return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
private PendingIntent buildForgetPendingIntent(VolumeRecord rec) {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
"com.android.settings.Settings$PrivateVolumeForgetActivity");
|
||||
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, rec.getFsUuid());
|
||||
|
||||
final int requestKey = rec.getFsUuid().hashCode();
|
||||
return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ import android.os.storage.StorageManager;
|
||||
import android.os.storage.StorageResultCode;
|
||||
import android.os.storage.StorageVolume;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.os.storage.VolumeRecord;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.DebugUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
@@ -251,49 +251,7 @@ class MountService extends IMountService.Stub
|
||||
private static final String ATTR_NICKNAME = "nickname";
|
||||
private static final String ATTR_USER_FLAGS = "userFlags";
|
||||
|
||||
private final AtomicFile mMetadataFile;
|
||||
|
||||
private static class VolumeMetadata {
|
||||
public final int type;
|
||||
public final String fsUuid;
|
||||
public String nickname;
|
||||
public int userFlags;
|
||||
|
||||
public VolumeMetadata(int type, String fsUuid) {
|
||||
this.type = type;
|
||||
this.fsUuid = Preconditions.checkNotNull(fsUuid);
|
||||
}
|
||||
|
||||
public static VolumeMetadata read(XmlPullParser in) throws IOException {
|
||||
final int type = readIntAttribute(in, ATTR_TYPE);
|
||||
final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
|
||||
final VolumeMetadata meta = new VolumeMetadata(type, fsUuid);
|
||||
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
|
||||
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
|
||||
return meta;
|
||||
}
|
||||
|
||||
public static void write(XmlSerializer out, VolumeMetadata meta) throws IOException {
|
||||
out.startTag(null, TAG_VOLUME);
|
||||
writeIntAttribute(out, ATTR_TYPE, meta.type);
|
||||
writeStringAttribute(out, ATTR_FS_UUID, meta.fsUuid);
|
||||
writeStringAttribute(out, ATTR_NICKNAME, meta.nickname);
|
||||
writeIntAttribute(out, ATTR_USER_FLAGS, meta.userFlags);
|
||||
out.endTag(null, TAG_VOLUME);
|
||||
}
|
||||
|
||||
public void dump(IndentingPrintWriter pw) {
|
||||
pw.println("VolumeMetadata:");
|
||||
pw.increaseIndent();
|
||||
pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type));
|
||||
pw.printPair("fsUuid", fsUuid);
|
||||
pw.printPair("nickname", nickname);
|
||||
pw.printPair("userFlags",
|
||||
DebugUtils.flagsToString(VolumeInfo.class, "USER_FLAG_", userFlags));
|
||||
pw.decreaseIndent();
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
private final AtomicFile mSettingsFile;
|
||||
|
||||
/**
|
||||
* <em>Never</em> hold the lock while performing downcalls into vold, since
|
||||
@@ -311,9 +269,9 @@ class MountService extends IMountService.Stub
|
||||
@GuardedBy("mLock")
|
||||
private ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
|
||||
|
||||
/** Map from UUID to metadata */
|
||||
/** Map from UUID to record */
|
||||
@GuardedBy("mLock")
|
||||
private ArrayMap<String, VolumeMetadata> mMetadata = new ArrayMap<>();
|
||||
private ArrayMap<String, VolumeRecord> mRecords = new ArrayMap<>();
|
||||
@GuardedBy("mLock")
|
||||
private String mPrimaryStorageUuid;
|
||||
|
||||
@@ -370,15 +328,6 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private VolumeMetadata findOrCreateMetadataLocked(VolumeInfo vol) {
|
||||
VolumeMetadata meta = mMetadata.get(vol.fsUuid);
|
||||
if (meta == null) {
|
||||
meta = new VolumeMetadata(vol.type, vol.fsUuid);
|
||||
mMetadata.put(meta.fsUuid, meta);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
|
||||
synchronized (mLock) {
|
||||
CountDownLatch latch = mDiskScanLatches.get(diskId);
|
||||
@@ -913,7 +862,7 @@ class MountService extends IMountService.Stub
|
||||
final int oldState = vol.state;
|
||||
final int newState = Integer.parseInt(cooked[2]);
|
||||
vol.state = newState;
|
||||
onVolumeStateChangedLocked(vol.clone(), oldState, newState);
|
||||
onVolumeStateChangedLocked(vol, oldState, newState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -923,7 +872,6 @@ class MountService extends IMountService.Stub
|
||||
if (vol != null) {
|
||||
vol.fsType = cooked[2];
|
||||
}
|
||||
mCallbacks.notifyVolumeMetadataChanged(vol.clone());
|
||||
break;
|
||||
}
|
||||
case VoldResponseCode.VOLUME_FS_UUID_CHANGED: {
|
||||
@@ -932,8 +880,6 @@ class MountService extends IMountService.Stub
|
||||
if (vol != null) {
|
||||
vol.fsUuid = cooked[2];
|
||||
}
|
||||
refreshMetadataLocked();
|
||||
mCallbacks.notifyVolumeMetadataChanged(vol.clone());
|
||||
break;
|
||||
}
|
||||
case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: {
|
||||
@@ -945,7 +891,7 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
vol.fsLabel = builder.toString().trim();
|
||||
}
|
||||
mCallbacks.notifyVolumeMetadataChanged(vol.clone());
|
||||
// TODO: notify listeners that label changed
|
||||
break;
|
||||
}
|
||||
case VoldResponseCode.VOLUME_PATH_CHANGED: {
|
||||
@@ -1070,6 +1016,19 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
|
||||
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
|
||||
// Remember that we saw this volume so we're ready to accept user
|
||||
// metadata, or so we can annoy them when a private volume is ejected
|
||||
if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
|
||||
if (!mRecords.containsKey(vol.fsUuid)) {
|
||||
final VolumeRecord rec = new VolumeRecord(vol.type, vol.fsUuid);
|
||||
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
|
||||
rec.nickname = vol.disk.getDescription();
|
||||
}
|
||||
mRecords.put(rec.fsUuid, rec);
|
||||
writeSettingsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
|
||||
|
||||
if (isBroadcastWorthy(vol)) {
|
||||
@@ -1117,7 +1076,7 @@ class MountService extends IMountService.Stub
|
||||
|
||||
// TODO: estimate remaining time
|
||||
try {
|
||||
mMoveCallback.onStatusChanged(-1, status, -1);
|
||||
mMoveCallback.onStatusChanged(-1, null, status, -1);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
|
||||
@@ -1127,7 +1086,7 @@ class MountService extends IMountService.Stub
|
||||
Slog.d(TAG, "Move to " + mMoveTargetUuid + " copy phase finshed; persisting");
|
||||
|
||||
mPrimaryStorageUuid = mMoveTargetUuid;
|
||||
writeMetadataLocked();
|
||||
writeSettingsLocked();
|
||||
}
|
||||
|
||||
if (PackageManager.isMoveStatusFinished(status)) {
|
||||
@@ -1138,25 +1097,6 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh latest metadata into any currently active {@link VolumeInfo}.
|
||||
*/
|
||||
private void refreshMetadataLocked() {
|
||||
final int size = mVolumes.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final VolumeInfo vol = mVolumes.valueAt(i);
|
||||
final VolumeMetadata meta = mMetadata.get(vol.fsUuid);
|
||||
|
||||
if (meta != null) {
|
||||
vol.nickname = meta.nickname;
|
||||
vol.userFlags = meta.userFlags;
|
||||
} else {
|
||||
vol.nickname = null;
|
||||
vol.userFlags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enforcePermission(String perm) {
|
||||
mContext.enforceCallingOrSelfPermission(perm, perm);
|
||||
}
|
||||
@@ -1205,11 +1145,11 @@ class MountService extends IMountService.Stub
|
||||
mLastMaintenance = mLastMaintenanceFile.lastModified();
|
||||
}
|
||||
|
||||
mMetadataFile = new AtomicFile(
|
||||
mSettingsFile = new AtomicFile(
|
||||
new File(Environment.getSystemSecureDirectory(), "storage.xml"));
|
||||
|
||||
synchronized (mLock) {
|
||||
readMetadataLocked();
|
||||
readSettingsLocked();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1235,12 +1175,12 @@ class MountService extends IMountService.Stub
|
||||
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
|
||||
}
|
||||
|
||||
private void readMetadataLocked() {
|
||||
mMetadata.clear();
|
||||
private void readSettingsLocked() {
|
||||
mRecords.clear();
|
||||
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = mMetadataFile.openRead();
|
||||
fis = mSettingsFile.openRead();
|
||||
final XmlPullParser in = Xml.newPullParser();
|
||||
in.setInput(fis, null);
|
||||
|
||||
@@ -1263,8 +1203,8 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
|
||||
} else if (TAG_VOLUME.equals(tag)) {
|
||||
final VolumeMetadata meta = VolumeMetadata.read(in);
|
||||
mMetadata.put(meta.fsUuid, meta);
|
||||
final VolumeRecord rec = readVolumeRecord(in);
|
||||
mRecords.put(rec.fsUuid, rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1279,10 +1219,10 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMetadataLocked() {
|
||||
private void writeSettingsLocked() {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = mMetadataFile.startWrite();
|
||||
fos = mSettingsFile.startWrite();
|
||||
|
||||
XmlSerializer out = new FastXmlSerializer();
|
||||
out.setOutput(fos, "utf-8");
|
||||
@@ -1290,22 +1230,40 @@ class MountService extends IMountService.Stub
|
||||
out.startTag(null, TAG_VOLUMES);
|
||||
writeIntAttribute(out, ATTR_VERSION, VERSION_ADD_PRIMARY);
|
||||
writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
|
||||
final int size = mMetadata.size();
|
||||
final int size = mRecords.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final VolumeMetadata meta = mMetadata.valueAt(i);
|
||||
VolumeMetadata.write(out, meta);
|
||||
final VolumeRecord rec = mRecords.valueAt(i);
|
||||
writeVolumeRecord(out, rec);
|
||||
}
|
||||
out.endTag(null, TAG_VOLUMES);
|
||||
out.endDocument();
|
||||
|
||||
mMetadataFile.finishWrite(fos);
|
||||
mSettingsFile.finishWrite(fos);
|
||||
} catch (IOException e) {
|
||||
if (fos != null) {
|
||||
mMetadataFile.failWrite(fos);
|
||||
mSettingsFile.failWrite(fos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static VolumeRecord readVolumeRecord(XmlPullParser in) throws IOException {
|
||||
final int type = readIntAttribute(in, ATTR_TYPE);
|
||||
final String fsUuid = readStringAttribute(in, ATTR_FS_UUID);
|
||||
final VolumeRecord meta = new VolumeRecord(type, fsUuid);
|
||||
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
|
||||
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
|
||||
return meta;
|
||||
}
|
||||
|
||||
public static void writeVolumeRecord(XmlSerializer out, VolumeRecord rec) throws IOException {
|
||||
out.startTag(null, TAG_VOLUME);
|
||||
writeIntAttribute(out, ATTR_TYPE, rec.type);
|
||||
writeStringAttribute(out, ATTR_FS_UUID, rec.fsUuid);
|
||||
writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
|
||||
writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
|
||||
out.endTag(null, TAG_VOLUME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposed API calls below here
|
||||
*/
|
||||
@@ -1471,32 +1429,40 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolumeNickname(String volId, String nickname) {
|
||||
public void setVolumeNickname(String fsUuid, String nickname) {
|
||||
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
|
||||
waitForReady();
|
||||
|
||||
synchronized (mLock) {
|
||||
final VolumeInfo vol = findVolumeById(volId);
|
||||
final VolumeMetadata meta = findOrCreateMetadataLocked(vol);
|
||||
meta.nickname = nickname;
|
||||
refreshMetadataLocked();
|
||||
writeMetadataLocked();
|
||||
mCallbacks.notifyVolumeMetadataChanged(vol.clone());
|
||||
final VolumeRecord rec = mRecords.get(fsUuid);
|
||||
rec.nickname = nickname;
|
||||
mCallbacks.notifyVolumeMetadataChanged(fsUuid);
|
||||
writeSettingsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolumeUserFlags(String volId, int flags, int mask) {
|
||||
public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
|
||||
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
|
||||
waitForReady();
|
||||
|
||||
synchronized (mLock) {
|
||||
final VolumeInfo vol = findVolumeById(volId);
|
||||
final VolumeMetadata meta = findOrCreateMetadataLocked(vol);
|
||||
meta.userFlags = (meta.userFlags & ~mask) | (flags & mask);
|
||||
refreshMetadataLocked();
|
||||
writeMetadataLocked();
|
||||
mCallbacks.notifyVolumeMetadataChanged(vol.clone());
|
||||
final VolumeRecord rec = mRecords.get(fsUuid);
|
||||
rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
|
||||
mCallbacks.notifyVolumeMetadataChanged(fsUuid);
|
||||
writeSettingsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forgetVolume(String fsUuid) {
|
||||
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
|
||||
waitForReady();
|
||||
|
||||
synchronized (mLock) {
|
||||
mRecords.remove(fsUuid);
|
||||
mCallbacks.notifyVolumeMetadataChanged(fsUuid);
|
||||
writeSettingsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2329,11 +2295,6 @@ class MountService extends IMountService.Stub
|
||||
|
||||
@Override
|
||||
public VolumeInfo[] getVolumes(int flags) {
|
||||
if ((flags & StorageManager.FLAG_ALL_METADATA) != 0) {
|
||||
// TODO: implement support for returning all metadata
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
|
||||
for (int i = 0; i < mVolumes.size(); i++) {
|
||||
@@ -2343,6 +2304,17 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeRecord[] getVolumeRecords(int flags) {
|
||||
synchronized (mLock) {
|
||||
final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
|
||||
for (int i = 0; i < mRecords.size(); i++) {
|
||||
res[i] = mRecords.valueAt(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
private void addObbStateLocked(ObbState obbState) throws RemoteException {
|
||||
final IBinder binder = obbState.getBinder();
|
||||
List<ObbState> obbStates = mObbMounts.get(binder);
|
||||
@@ -2892,7 +2864,7 @@ class MountService extends IMountService.Stub
|
||||
break;
|
||||
}
|
||||
case MSG_VOLUME_METADATA_CHANGED: {
|
||||
callback.onVolumeMetadataChanged((VolumeInfo) args.arg1);
|
||||
callback.onVolumeMetadataChanged((String) args.arg1);
|
||||
break;
|
||||
}
|
||||
case MSG_DISK_SCANNED: {
|
||||
@@ -2912,21 +2884,21 @@ class MountService extends IMountService.Stub
|
||||
|
||||
private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = vol;
|
||||
args.arg1 = vol.clone();
|
||||
args.argi2 = oldState;
|
||||
args.argi3 = newState;
|
||||
obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
|
||||
}
|
||||
|
||||
private void notifyVolumeMetadataChanged(VolumeInfo vol) {
|
||||
private void notifyVolumeMetadataChanged(String fsUuid) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = vol;
|
||||
args.arg1 = fsUuid;
|
||||
obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget();
|
||||
}
|
||||
|
||||
private void notifyDiskScanned(DiskInfo disk, int volumeCount) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = disk;
|
||||
args.arg1 = disk.clone();
|
||||
args.argi2 = volumeCount;
|
||||
obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
|
||||
}
|
||||
@@ -2937,10 +2909,10 @@ class MountService extends IMountService.Stub
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
|
||||
|
||||
for (String arg : args) {
|
||||
if ("--clear-metadata".equals(arg)) {
|
||||
if ("--clear".equals(arg)) {
|
||||
synchronized (mLock) {
|
||||
mMetadata.clear();
|
||||
writeMetadataLocked();
|
||||
mRecords.clear();
|
||||
writeSettingsLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2966,11 +2938,11 @@ class MountService extends IMountService.Stub
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println();
|
||||
pw.println("Metadata:");
|
||||
pw.println("Records:");
|
||||
pw.increaseIndent();
|
||||
for (int i = 0; i < mMetadata.size(); i++) {
|
||||
final VolumeMetadata meta = mMetadata.valueAt(i);
|
||||
meta.dump(pw);
|
||||
for (int i = 0; i < mRecords.size(); i++) {
|
||||
final VolumeRecord note = mRecords.valueAt(i);
|
||||
note.dump(pw);
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
|
||||
|
||||
@@ -14192,7 +14192,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
movePackageInternal(packageName, volumeUuid, moveId);
|
||||
} catch (PackageManagerException e) {
|
||||
Slog.d(TAG, "Failed to move " + packageName, e);
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR);
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, null,
|
||||
PackageManager.MOVE_FAILED_INTERNAL_ERROR);
|
||||
}
|
||||
return moveId;
|
||||
}
|
||||
@@ -14209,6 +14210,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final String packageAbiOverride;
|
||||
final int appId;
|
||||
final String seinfo;
|
||||
final String moveTitle;
|
||||
|
||||
// reader
|
||||
synchronized (mPackages) {
|
||||
@@ -14228,9 +14230,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
// TODO: yell if already in desired location
|
||||
|
||||
mMoveCallbacks.notifyStarted(moveId,
|
||||
String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)));
|
||||
|
||||
pkg.mOperationPending = true;
|
||||
|
||||
currentAsec = pkg.applicationInfo.isForwardLocked()
|
||||
@@ -14241,6 +14240,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
packageAbiOverride = ps.cpuAbiOverrideString;
|
||||
appId = UserHandle.getAppId(pkg.applicationInfo.uid);
|
||||
seinfo = pkg.applicationInfo.seinfo;
|
||||
moveTitle = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
|
||||
}
|
||||
|
||||
int installFlags;
|
||||
@@ -14268,7 +14268,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
Slog.d(TAG, "Moving " + packageName + " from " + currentVolumeUuid + " to " + volumeUuid);
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, 10, -1);
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 10);
|
||||
|
||||
if (moveData) {
|
||||
synchronized (mInstallLock) {
|
||||
@@ -14288,7 +14288,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, 50);
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 50);
|
||||
|
||||
final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
|
||||
@Override
|
||||
@@ -14315,15 +14315,15 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final int status = PackageManager.installStatusToPublicStatus(returnCode);
|
||||
switch (status) {
|
||||
case PackageInstaller.STATUS_SUCCESS:
|
||||
mMoveCallbacks.notifyStatusChanged(moveId,
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, moveTitle,
|
||||
PackageManager.MOVE_SUCCEEDED);
|
||||
break;
|
||||
case PackageInstaller.STATUS_FAILURE_STORAGE:
|
||||
mMoveCallbacks.notifyStatusChanged(moveId,
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, moveTitle,
|
||||
PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE);
|
||||
break;
|
||||
default:
|
||||
mMoveCallbacks.notifyStatusChanged(moveId,
|
||||
mMoveCallbacks.notifyStatusChanged(moveId, moveTitle,
|
||||
PackageManager.MOVE_FAILED_INTERNAL_ERROR);
|
||||
break;
|
||||
}
|
||||
@@ -14346,15 +14346,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
|
||||
|
||||
final int realMoveId = mNextMoveId.getAndIncrement();
|
||||
final String realTitle = null;
|
||||
|
||||
final IPackageMoveObserver callback = new IPackageMoveObserver.Stub() {
|
||||
@Override
|
||||
public void onStarted(int moveId, String title) {
|
||||
// Ignored
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(int moveId, int status, long estMillis) {
|
||||
mMoveCallbacks.notifyStatusChanged(realMoveId, status, estMillis);
|
||||
public void onStatusChanged(int moveId, String title, int status, long estMillis) {
|
||||
mMoveCallbacks.notifyStatusChanged(realMoveId, realTitle, status, estMillis);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14709,7 +14706,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
private static class MoveCallbacks extends Handler {
|
||||
private static final int MSG_STARTED = 1;
|
||||
private static final int MSG_STATUS_CHANGED = 2;
|
||||
|
||||
private final RemoteCallbackList<IPackageMoveObserver>
|
||||
@@ -14747,37 +14743,26 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
private void invokeCallback(IPackageMoveObserver callback, int what, SomeArgs args)
|
||||
throws RemoteException {
|
||||
switch (what) {
|
||||
case MSG_STARTED: {
|
||||
callback.onStarted(args.argi1, (String) args.arg2);
|
||||
break;
|
||||
}
|
||||
case MSG_STATUS_CHANGED: {
|
||||
callback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3);
|
||||
callback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3,
|
||||
(long) args.arg4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyStarted(int moveId, String title) {
|
||||
Slog.v(TAG, "Move " + moveId + " started with title " + title);
|
||||
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.argi1 = moveId;
|
||||
args.arg2 = title;
|
||||
obtainMessage(MSG_STARTED, args).sendToTarget();
|
||||
private void notifyStatusChanged(int moveId, String moveTitle, int status) {
|
||||
notifyStatusChanged(moveId, moveTitle, status, -1);
|
||||
}
|
||||
|
||||
private void notifyStatusChanged(int moveId, int status) {
|
||||
notifyStatusChanged(moveId, status, -1);
|
||||
}
|
||||
|
||||
private void notifyStatusChanged(int moveId, int status, long estMillis) {
|
||||
private void notifyStatusChanged(int moveId, String moveTitle, int status, long estMillis) {
|
||||
Slog.v(TAG, "Move " + moveId + " status " + status);
|
||||
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.argi1 = moveId;
|
||||
args.argi2 = status;
|
||||
args.arg3 = estMillis;
|
||||
args.arg2 = moveTitle;
|
||||
args.argi3 = status;
|
||||
args.arg4 = estMillis;
|
||||
obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget();
|
||||
|
||||
synchronized (mLastStatus) {
|
||||
|
||||
Reference in New Issue
Block a user