summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/storage/DiskInfo.java5
-rw-r--r--core/java/android/os/storage/VolumeRecord.java14
-rw-r--r--core/java/android/provider/Settings.java3
-rw-r--r--core/java/android/util/TimeUtils.java12
-rw-r--r--services/core/java/com/android/server/MountService.java124
5 files changed, 140 insertions, 18 deletions
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 397d87e..9114107 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -54,6 +54,7 @@ public class DiskInfo implements Parcelable {
public String label;
/** Hacky; don't rely on this count */
public int volumeCount;
+ public String sysPath;
public DiskInfo(String id, int flags) {
this.id = Preconditions.checkNotNull(id);
@@ -66,6 +67,7 @@ public class DiskInfo implements Parcelable {
size = parcel.readLong();
label = parcel.readString();
volumeCount = parcel.readInt();
+ sysPath = parcel.readString();
}
public @NonNull String getId() {
@@ -139,6 +141,8 @@ public class DiskInfo implements Parcelable {
pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags));
pw.printPair("size", size);
pw.printPair("label", label);
+ pw.println();
+ pw.printPair("sysPath", sysPath);
pw.decreaseIndent();
pw.println();
}
@@ -193,5 +197,6 @@ public class DiskInfo implements Parcelable {
parcel.writeLong(size);
parcel.writeString(label);
parcel.writeInt(volumeCount);
+ parcel.writeString(sysPath);
}
}
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index cb16305..7b20223 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -19,6 +19,7 @@ package android.os.storage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DebugUtils;
+import android.util.TimeUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -42,6 +43,9 @@ public class VolumeRecord implements Parcelable {
public String partGuid;
public String nickname;
public int userFlags;
+ public long createdMillis;
+ public long lastTrimMillis;
+ public long lastBenchMillis;
public VolumeRecord(int type, String fsUuid) {
this.type = type;
@@ -54,6 +58,9 @@ public class VolumeRecord implements Parcelable {
partGuid = parcel.readString();
nickname = parcel.readString();
userFlags = parcel.readInt();
+ createdMillis = parcel.readLong();
+ lastTrimMillis = parcel.readLong();
+ lastBenchMillis = parcel.readLong();
}
public int getType() {
@@ -86,6 +93,10 @@ public class VolumeRecord implements Parcelable {
pw.printPair("nickname", nickname);
pw.printPair("userFlags",
DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags));
+ pw.println();
+ pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis));
+ pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis));
+ pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis));
pw.decreaseIndent();
pw.println();
}
@@ -140,5 +151,8 @@ public class VolumeRecord implements Parcelable {
parcel.writeString(partGuid);
parcel.writeString(nickname);
parcel.writeInt(userFlags);
+ parcel.writeLong(createdMillis);
+ parcel.writeLong(lastTrimMillis);
+ parcel.writeLong(lastBenchMillis);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e5afdde..4e13758 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6324,6 +6324,9 @@ public final class Settings {
/** Timeout in milliseconds to wait for NTP server. {@hide} */
public static final String NTP_TIMEOUT = "ntp_timeout";
+ /** {@hide} */
+ public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval";
+
/**
* Whether the package manager should send package verification broadcasts for verifiers to
* review apps prior to installation.
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 353388d..c1eb80d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -28,6 +28,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -54,6 +55,8 @@ public class TimeUtils {
private static ArrayList<TimeZone> sLastUniqueZoneOffsets = null;
private static String sLastUniqueCountry = null;
+ /** {@hide} */
+ private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* Tries to return a time zone that would have had the specified offset
@@ -441,4 +444,13 @@ public class TimeUtils {
return Long.toString(millis);
}
}
+
+ /** {@hide} */
+ public static String formatForLogging(long millis) {
+ if (millis <= 0) {
+ return "unknown";
+ } else {
+ return sLoggingFormat.format(new Date(millis));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b4fa46d..c82ba24 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -18,9 +18,11 @@ package com.android.server;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
+import static com.android.internal.util.XmlUtils.readLongAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
+import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -56,7 +58,6 @@ import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -71,12 +72,14 @@ import android.os.storage.StorageResultCode;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.Xml;
import libcore.io.IoUtils;
@@ -111,9 +114,7 @@ import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -182,7 +183,9 @@ class MountService extends IMountService.Stub
private static final boolean WATCHDOG_ENABLE = false;
private static final String TAG = "MountService";
+
private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
+ private static final String TAG_STORAGE_TRIM = "storage_trim";
private static final String VOLD_TAG = "VoldConnector";
private static final String CRYPTD_TAG = "CryptdConnector";
@@ -231,6 +234,7 @@ class MountService extends IMountService.Stub
public static final int DISK_SIZE_CHANGED = 641;
public static final int DISK_LABEL_CHANGED = 642;
public static final int DISK_SCANNED = 643;
+ public static final int DISK_SYS_PATH_CHANGED = 644;
public static final int DISK_DESTROYED = 649;
public static final int VOLUME_CREATED = 650;
@@ -244,11 +248,7 @@ class MountService extends IMountService.Stub
public static final int MOVE_STATUS = 660;
public static final int BENCHMARK_RESULT = 661;
-
- /*
- * 700 series - fstrim
- */
- public static final int FstrimCompleted = 700;
+ public static final int TRIM_RESULT = 662;
}
private static final int VERSION_INIT = 1;
@@ -265,6 +265,9 @@ class MountService extends IMountService.Stub
private static final String ATTR_PART_GUID = "partGuid";
private static final String ATTR_NICKNAME = "nickname";
private static final String ATTR_USER_FLAGS = "userFlags";
+ private static final String ATTR_CREATED_MILLIS = "createdMillis";
+ private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
+ private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
private final AtomicFile mSettingsFile;
@@ -321,7 +324,6 @@ class MountService extends IMountService.Stub
throw new IllegalArgumentException("No volume found for ID " + id);
}
- @Deprecated
private String findVolumeIdForPath(String path) {
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
@@ -334,6 +336,31 @@ class MountService extends IMountService.Stub
throw new IllegalArgumentException("No volume found for path " + path);
}
+ private VolumeRecord findRecordForPath(String path) {
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (vol.path != null && path.startsWith(vol.path)) {
+ return mRecords.get(vol.fsUuid);
+ }
+ }
+ }
+ return null;
+ }
+
+ private String scrubPath(String path) {
+ if (path.startsWith(Environment.getDataDirectory().getAbsolutePath())) {
+ return "internal";
+ }
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec == null || rec.createdMillis == 0) {
+ return "unknown";
+ } else {
+ return "ext:" + (int) ((System.currentTimeMillis() - rec.createdMillis)
+ / DateUtils.WEEK_IN_MILLIS) + "w";
+ }
+ }
+
private VolumeInfo findStorageForUuid(String volumeUuid) {
final StorageManager storage = mContext.getSystemService(StorageManager.class);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
@@ -345,6 +372,24 @@ class MountService extends IMountService.Stub
}
}
+ private boolean shouldBenchmark() {
+ final long benchInterval = Settings.Global.getLong(mContext.getContentResolver(),
+ Settings.Global.STORAGE_BENCHMARK_INTERVAL, DateUtils.WEEK_IN_MILLIS);
+ 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.isMountedReadable() && rec != null) {
+ final long benchAge = System.currentTimeMillis() - rec.lastBenchMillis;
+ if (benchAge >= benchInterval) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
private CountDownLatch findOrCreateDiskScanLatch(String diskId) {
synchronized (mLock) {
CountDownLatch latch = mDiskScanLatches.get(diskId);
@@ -563,16 +608,17 @@ class MountService extends IMountService.Stub
Slog.e(TAG, "Unable to record last fstrim!");
}
+ final boolean shouldBenchmark = shouldBenchmark();
try {
// This method must be run on the main (handler) thread,
// so it is safe to directly call into vold.
- mConnector.execute("fstrim", "dotrim");
- EventLogTags.writeFstrimStart(SystemClock.elapsedRealtime());
+ mConnector.execute("fstrim", shouldBenchmark ? "dotrimbench" : "dotrim");
} catch (NativeDaemonConnectorException ndce) {
Slog.e(TAG, "Failed to run fstrim!");
}
// invoke the completion callback, if any
+ // TODO: fstrim is non-blocking, so remove this useless callback
Runnable callback = (Runnable) msg.obj;
if (callback != null) {
callback.run();
@@ -896,6 +942,14 @@ class MountService extends IMountService.Stub
}
break;
}
+ case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
+ if (cooked.length != 3) break;
+ final DiskInfo disk = mDisks.get(cooked[1]);
+ if (disk != null) {
+ disk.sysPath = cooked[2];
+ }
+ break;
+ }
case VoldResponseCode.DISK_DESTROYED: {
if (cooked.length != 2) break;
final DiskInfo disk = mDisks.remove(cooked[1]);
@@ -984,17 +1038,46 @@ class MountService extends IMountService.Stub
onMoveStatusLocked(status);
break;
}
-
case VoldResponseCode.BENCHMARK_RESULT: {
+ if (cooked.length != 7) break;
+ final String path = cooked[1];
+ final String ident = cooked[2];
+ final long create = Long.parseLong(cooked[3]);
+ final long drop = Long.parseLong(cooked[4]);
+ final long run = Long.parseLong(cooked[5]);
+ final long destroy = Long.parseLong(cooked[6]);
+
final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
- dropBox.addText(TAG_STORAGE_BENCHMARK, raw);
+ dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
+ + " " + ident + " " + create + " " + run + " " + destroy);
+
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec != null) {
+ rec.lastBenchMillis = System.currentTimeMillis();
+ writeSettingsLocked();
+ }
+
break;
}
+ case VoldResponseCode.TRIM_RESULT: {
+ if (cooked.length != 4) break;
+ final String path = cooked[1];
+ final long bytes = Long.parseLong(cooked[2]);
+ final long time = Long.parseLong(cooked[3]);
+
+ final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
+ dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path)
+ + " " + bytes + " " + time);
+
+ final VolumeRecord rec = findRecordForPath(path);
+ if (rec != null) {
+ rec.lastTrimMillis = System.currentTimeMillis();
+ writeSettingsLocked();
+ }
- case VoldResponseCode.FstrimCompleted: {
- EventLogTags.writeFstrimFinish(SystemClock.elapsedRealtime());
break;
}
+
default: {
Slog.d(TAG, "Unhandled vold event " + code);
}
@@ -1106,6 +1189,7 @@ class MountService extends IMountService.Stub
if (rec == null) {
rec = new VolumeRecord(vol.type, vol.fsUuid);
rec.partGuid = vol.partGuid;
+ rec.createdMillis = System.currentTimeMillis();
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
rec.nickname = vol.disk.getDescription();
}
@@ -1385,6 +1469,9 @@ class MountService extends IMountService.Stub
meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
+ meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
+ meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
+ meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
return meta;
}
@@ -1395,6 +1482,9 @@ class MountService extends IMountService.Stub
writeStringAttribute(out, ATTR_PART_GUID, rec.partGuid);
writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
+ writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
+ writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
+ writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
out.endTag(null, TAG_VOLUME);
}
@@ -3232,11 +3322,9 @@ class MountService extends IMountService.Stub
mConnector.dump(fd, pw, args);
pw.decreaseIndent();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
pw.println();
pw.print("Last maintenance: ");
- pw.println(sdf.format(new Date(mLastMaintenance)));
+ pw.println(TimeUtils.formatForLogging(mLastMaintenance));
}
/** {@inheritDoc} */