Add a new atom to log when an app is moved from internal to external
storage and vice versa.
Bug: 123688171
Test: Manually tested using stats_testdrive script.
Change-Id: Ie6c31388b779421796554465f87a4dbdf742d7e1
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c2b81e4..a752a9f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -254,6 +254,7 @@
PrivacyIndicatorsInteracted privacy_indicators_interacted = 180;
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
NetworkStackReported network_stack_reported = 182;
+ AppMovedStorageReported app_moved_storage_reported = 183;
}
// Pulled events will start at field 10000.
@@ -3445,6 +3446,30 @@
optional string package_name = 2;
}
+/**
+ * Logs information about a package that is moved from the internal to external storage and vice
+ * versa.
+ * It logs the package name, the type of the external storage where the package is installed
+ * (if moved to external storage, or UNKNOWN if moved to internal storage),
+ * and the move type: if it's from internal to external or the other way around.
+ *
+ * Logged from:
+ frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
+ */
+message AppMovedStorageReported {
+ enum MoveType {
+ UNKNOWN = 0;
+ TO_EXTERNAL = 1;
+ TO_INTERNAL = 2;
+ }
+ // The type of the external storage.
+ optional android.stats.storage.ExternalStorageType external_storage_type = 1;
+ // The type of move.
+ optional MoveType move_type = 2;
+ // The name of the package that was moved.
+ optional string package_name = 3;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 81448b7..5726d72 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1938,8 +1938,13 @@
// Send broadcast package appeared if external for all users
if (isExternal(res.pkg)) {
if (!update) {
+ final StorageManager storage =
+ mContext.getSystemService(StorageManager.class);
+ VolumeInfo volume =
+ storage.findVolumeByUuid(
+ res.pkg.applicationInfo.storageUuid.toString());
int packageExternalStorageType =
- getPackageExternalStorageType(res.pkg);
+ getPackageExternalStorageType(volume, isExternal(res.pkg));
// If the package was installed externally, log it.
if (packageExternalStorageType != StorageEnums.UNKNOWN) {
StatsLog.write(StatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
@@ -2036,15 +2041,16 @@
/**
* Gets the type of the external storage a package is installed on.
- * @param pkg The package for which to get the external storage type.
- * @return {@link StorageEnum#TYPE_UNKNOWN} if it is not stored externally or the corresponding
- * {@link StorageEnum} storage type value if it is.
+ * @param packageVolume The storage volume of the package.
+ * @param packageIsExternal true if the package is currently installed on
+ * external/removable/unprotected storage.
+ * @return {@link StorageEnum#TYPE_UNKNOWN} if the package is not stored externally or the
+ * corresponding {@link StorageEnum} storage type value if it is.
*/
- private int getPackageExternalStorageType(PackageParser.Package pkg) {
- final StorageManager storage = mContext.getSystemService(StorageManager.class);
- VolumeInfo volume = storage.findVolumeByUuid(pkg.applicationInfo.storageUuid.toString());
- if (volume != null) {
- DiskInfo disk = volume.getDisk();
+ private static int getPackageExternalStorageType(VolumeInfo packageVolume,
+ boolean packageIsExternal) {
+ if (packageVolume != null) {
+ DiskInfo disk = packageVolume.getDisk();
if (disk != null) {
if (disk.isSd()) {
return StorageEnums.SD_CARD;
@@ -2052,7 +2058,7 @@
if (disk.isUsb()) {
return StorageEnums.USB;
}
- if (isExternal(pkg)) {
+ if (packageIsExternal) {
return StorageEnums.OTHER;
}
}
@@ -22483,6 +22489,7 @@
final int targetSdkVersion;
final PackageFreezer freezer;
final int[] installedUserIds;
+ final boolean isCurrentLocationExternal;
// reader
synchronized (mPackages) {
@@ -22529,6 +22536,7 @@
"Failed to move already frozen package");
}
+ isCurrentLocationExternal = isExternal(pkg);
codeFile = new File(pkg.codePath);
installerPackageName = ps.installerPackageName;
packageAbiOverride = ps.cpuAbiOverrideString;
@@ -22631,6 +22639,7 @@
case PackageInstaller.STATUS_SUCCESS:
mMoveCallbacks.notifyStatusChanged(moveId,
PackageManager.MOVE_SUCCEEDED);
+ logAppMovedStorage(packageName, isCurrentLocationExternal);
break;
case PackageInstaller.STATUS_FAILURE_STORAGE:
mMoveCallbacks.notifyStatusChanged(moveId,
@@ -22689,6 +22698,36 @@
mHandler.sendMessage(msg);
}
+ /**
+ * Logs that an app has been moved from internal to external storage and vice versa.
+ * @param packageName The package that was moved.
+ */
+ private void logAppMovedStorage(String packageName, boolean isPreviousLocationExternal) {
+ final PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ }
+ if (pkg == null) {
+ return;
+ }
+
+ final StorageManager storage = mContext.getSystemService(StorageManager.class);
+ VolumeInfo volume = storage.findVolumeByUuid(pkg.applicationInfo.storageUuid.toString());
+ int packageExternalStorageType = getPackageExternalStorageType(volume, isExternal(pkg));
+
+ if (!isPreviousLocationExternal && isExternal(pkg)) {
+ // Move from internal to external storage.
+ StatsLog.write(StatsLog.APP_MOVED_STORAGE_REPORTED, packageExternalStorageType,
+ StatsLog.APP_MOVED_STORAGE_REPORTED__MOVE_TYPE__TO_EXTERNAL,
+ packageName);
+ } else if (isPreviousLocationExternal && !isExternal(pkg)) {
+ // Move from external to internal storage.
+ StatsLog.write(StatsLog.APP_MOVED_STORAGE_REPORTED, packageExternalStorageType,
+ StatsLog.APP_MOVED_STORAGE_REPORTED__MOVE_TYPE__TO_INTERNAL,
+ packageName);
+ }
+ }
+
@Override
public int movePrimaryStorage(String volumeUuid) throws RemoteException {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);