DiskStats Westworld Migration
Migrates the existing information collected by diskstats to westworld. Creates 4 pulled atoms, 2 of which read from a cached file produced by DiskStatsLoggingService. Most of the logic is taken from DiskStatsService.java. Test: Manually verified information is the same as dumpsys. Will look into cts as well. Change-Id: I9818ac787de46514bc09ab3887cbfaec6cff273c
This commit is contained in:
@@ -150,12 +150,16 @@ message Atom {
|
||||
SystemUptime system_uptime = 10015;
|
||||
CpuActiveTime cpu_active_time = 10016;
|
||||
CpuClusterTime cpu_cluster_time = 10017;
|
||||
DiskSpace disk_space = 10018;
|
||||
DiskSpace disk_space = 10018 [deprecated=true];
|
||||
RemainingBatteryCapacity remaining_battery_capacity = 10019;
|
||||
FullBatteryCapacity full_battery_capacity = 10020;
|
||||
Temperature temperature = 10021;
|
||||
BinderCalls binder_calls = 10022;
|
||||
BinderCallsExceptions binder_calls_exceptions = 10023;
|
||||
DiskStats disk_stats = 10024;
|
||||
DirectoryUsage directory_usage = 10025;
|
||||
AppSize app_size = 10026;
|
||||
CategorySize category_size = 10027;
|
||||
}
|
||||
|
||||
// DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
|
||||
@@ -2167,3 +2171,83 @@ message BinderCallsExceptions {
|
||||
// Total number of exceptions.
|
||||
optional int64 exception_count = 2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pulls disk information, such as write speed and latency.
|
||||
*/
|
||||
message DiskStats {
|
||||
// Time taken to open, write 512B to, and close a file.
|
||||
// -1 if error performing the check.
|
||||
optional int64 data_write_latency_millis = 1;
|
||||
|
||||
optional bool file_based_encryption = 2;
|
||||
|
||||
// Recent disk write speed in kB/s.
|
||||
// -1 if error querying storageed.
|
||||
// 0 if data is unavailable.
|
||||
optional int32 recent_disk_write_speed = 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free and total bytes of the Data, Cache, and System partition.
|
||||
*/
|
||||
message DirectoryUsage {
|
||||
enum Directory {
|
||||
UNKNOWN = 0;
|
||||
DATA = 1;
|
||||
CACHE = 2;
|
||||
SYSTEM = 3;
|
||||
}
|
||||
optional Directory directory = 1;
|
||||
optional int64 free_bytes = 2;
|
||||
optional int64 total_bytes = 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Size of an application: apk size, data size, and cache size.
|
||||
* Reads from a cached file produced daily by DiskStatsLoggingService.java.
|
||||
* Information is only reported for apps with the primary user (user 0).
|
||||
* Sizes are aggregated by package name.
|
||||
*/
|
||||
message AppSize {
|
||||
// Including uids will involve modifying diskstats logic.
|
||||
optional string package_name = 1;
|
||||
// App size in bytes. -1 if unavailable.
|
||||
optional int64 app_size_bytes = 2;
|
||||
// App data size in bytes. -1 if unavailable.
|
||||
optional int64 app_data_size_bytes = 3;
|
||||
// App cache size in bytes. -1 if unavailable.
|
||||
optional int64 app_cache_size_bytes = 4;
|
||||
// Time that the cache file was produced.
|
||||
// Uses System.currentTimeMillis(), which is wall clock time.
|
||||
optional int64 cache_time_millis = 5;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Size of a particular category. Eg: photos, videos.
|
||||
* Reads from a cached file produced daily by DiskStatsLoggingService.java.
|
||||
*/
|
||||
message CategorySize {
|
||||
enum Category {
|
||||
UNKNOWN = 0;
|
||||
APP_SIZE = 1;
|
||||
APP_DATA_SIZE = 2;
|
||||
APP_CACHE_SIZE = 3;
|
||||
PHOTOS = 4;
|
||||
VIDEOS = 5;
|
||||
AUDIO = 6;
|
||||
DOWNLOADS = 7;
|
||||
SYSTEM = 8;
|
||||
OTHER = 9;
|
||||
}
|
||||
optional Category category = 1;
|
||||
// Category size in bytes.
|
||||
optional int64 size_bytes = 2;
|
||||
// Time that the cache file was produced.
|
||||
// Uses System.currentTimeMillis(), which is wall clock time.
|
||||
optional int64 cache_time_millis = 3;
|
||||
}
|
||||
|
||||
29
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
29
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
@@ -149,9 +149,6 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
|
||||
// system_uptime
|
||||
{android::util::SYSTEM_UPTIME,
|
||||
{{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
|
||||
// disk_space
|
||||
{android::util::DISK_SPACE,
|
||||
{{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_SPACE)}},
|
||||
// remaining_battery_capacity
|
||||
{android::util::REMAINING_BATTERY_CAPACITY,
|
||||
{{},
|
||||
@@ -183,7 +180,31 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
|
||||
{{},
|
||||
{},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}
|
||||
new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
|
||||
// Disk Stats
|
||||
{android::util::DISK_STATS,
|
||||
{{},
|
||||
{},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::DISK_STATS)}},
|
||||
// Directory usage
|
||||
{android::util::DIRECTORY_USAGE,
|
||||
{{},
|
||||
{},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
|
||||
// Size of app's code, data, and cache
|
||||
{android::util::APP_SIZE,
|
||||
{{},
|
||||
{},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::APP_SIZE)}},
|
||||
// Size of specific categories of files. Eg. Music.
|
||||
{android::util::CATEGORY_SIZE,
|
||||
{{},
|
||||
{},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
|
||||
};
|
||||
|
||||
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
|
||||
|
||||
@@ -120,6 +120,15 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
mStorage.write(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a boolean by adding either a 1 or 0 to the output.
|
||||
*/
|
||||
public void writeBoolean(boolean val) {
|
||||
int toWrite = val ? 1 : 0;
|
||||
mStorage.write(EVENT_TYPE_INT);
|
||||
write4Bytes(toWrite);
|
||||
}
|
||||
|
||||
private StatsLogEventWrapper(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import android.annotation.Nullable;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.AlarmManager.OnAlarmListener;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.ProcessMemoryState;
|
||||
import android.app.StatsManager;
|
||||
import android.bluetooth.BluetoothActivityEnergyInfo;
|
||||
@@ -44,6 +43,7 @@ import android.os.FileUtils;
|
||||
import android.os.IBinder;
|
||||
import android.os.IStatsCompanionService;
|
||||
import android.os.IStatsManager;
|
||||
import android.os.IStoraged;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
@@ -55,6 +55,7 @@ import android.os.SynchronousResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.telephony.ModemActivityInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArrayMap;
|
||||
@@ -65,10 +66,10 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.net.NetworkStatsFactory;
|
||||
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
|
||||
import com.android.internal.os.KernelCpuSpeedReader;
|
||||
import com.android.internal.os.KernelUidCpuTimeReader;
|
||||
import com.android.internal.os.KernelUidCpuClusterTimeReader;
|
||||
import com.android.internal.os.KernelUidCpuActiveTimeReader;
|
||||
import com.android.internal.os.KernelUidCpuClusterTimeReader;
|
||||
import com.android.internal.os.KernelUidCpuFreqTimeReader;
|
||||
import com.android.internal.os.KernelUidCpuTimeReader;
|
||||
import com.android.internal.os.KernelWakelockReader;
|
||||
import com.android.internal.os.KernelWakelockStats;
|
||||
import com.android.internal.os.PowerProfile;
|
||||
@@ -76,9 +77,18 @@ import com.android.internal.util.DumpUtils;
|
||||
import com.android.server.BinderCallsStatsService;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.storage.DiskStatsFileLogger;
|
||||
import com.android.server.storage.DiskStatsLoggingService;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -864,14 +874,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 3);
|
||||
e.writeLong(mStatFsData.getAvailableBytes());
|
||||
e.writeLong(mStatFsSystem.getAvailableBytes());
|
||||
e.writeLong(mStatFsTemp.getAvailableBytes());
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 1);
|
||||
e.writeLong(SystemClock.uptimeMillis());
|
||||
@@ -942,6 +944,183 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void pullDiskStats(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
// Run a quick-and-dirty performance test: write 512 bytes
|
||||
byte[] junk = new byte[512];
|
||||
for (int i = 0; i < junk.length; i++) junk[i] = (byte) i; // Write nonzero bytes
|
||||
|
||||
File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp");
|
||||
FileOutputStream fos = null;
|
||||
IOException error = null;
|
||||
|
||||
long before = SystemClock.elapsedRealtime();
|
||||
try {
|
||||
fos = new FileOutputStream(tmp);
|
||||
fos.write(junk);
|
||||
} catch (IOException e) {
|
||||
error = e;
|
||||
} finally {
|
||||
try {
|
||||
if (fos != null) fos.close();
|
||||
} catch (IOException e) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
long latency = SystemClock.elapsedRealtime() - before;
|
||||
if (tmp.exists()) tmp.delete();
|
||||
|
||||
if (error != null) {
|
||||
Slog.e(TAG, "Error performing diskstats latency test");
|
||||
latency = -1;
|
||||
}
|
||||
// File based encryption.
|
||||
boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
|
||||
|
||||
//Recent disk write speed. Binder call to storaged.
|
||||
int writeSpeed = -1;
|
||||
try {
|
||||
IBinder binder = ServiceManager.getService("storaged");
|
||||
if (binder == null) {
|
||||
Slog.e(TAG, "storaged not found");
|
||||
}
|
||||
IStoraged storaged = IStoraged.Stub.asInterface(binder);
|
||||
writeSpeed = storaged.getRecentPerf();
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "storaged not found");
|
||||
}
|
||||
|
||||
// Add info pulledData.
|
||||
long elapsedNanos = SystemClock.elapsedRealtimeNanos();
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeLong(latency);
|
||||
e.writeBoolean(fileBased);
|
||||
e.writeInt(writeSpeed);
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private void pullDirectoryUsage(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
long elapsedNanos = SystemClock.elapsedRealtimeNanos();
|
||||
StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
|
||||
StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
|
||||
StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
|
||||
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA);
|
||||
e.writeLong(statFsData.getAvailableBytes());
|
||||
e.writeLong(statFsData.getTotalBytes());
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE);
|
||||
e.writeLong(statFsCache.getAvailableBytes());
|
||||
e.writeLong(statFsCache.getTotalBytes());
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM);
|
||||
e.writeLong(statFsSystem.getAvailableBytes());
|
||||
e.writeLong(statFsSystem.getTotalBytes());
|
||||
pulledData.add(e);
|
||||
}
|
||||
|
||||
private void pullAppSize(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
long elapsedNanos = SystemClock.elapsedRealtimeNanos();
|
||||
try {
|
||||
String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
|
||||
JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
|
||||
JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
|
||||
JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY);
|
||||
JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
|
||||
// Sanity check: Ensure all 4 lists have the same length.
|
||||
int length = pkg_names.length();
|
||||
if (app_sizes.length() != length || app_data_sizes.length() != length
|
||||
|| app_cache_sizes.length() != length) {
|
||||
Slog.e(TAG, "formatting error in diskstats cache file!");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
StatsLogEventWrapper e =
|
||||
new StatsLogEventWrapper(elapsedNanos, tagId, 5 /* fields */);
|
||||
e.writeString(pkg_names.getString(i));
|
||||
e.writeLong(app_sizes.optLong(i, -1L));
|
||||
e.writeLong(app_data_sizes.optLong(i, -1L));
|
||||
e.writeLong(app_cache_sizes.optLong(i, -1L));
|
||||
e.writeLong(cache_time);
|
||||
pulledData.add(e);
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
Slog.e(TAG, "exception reading diskstats cache file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void pullCategorySize(int tagId, List<StatsLogEventWrapper> pulledData) {
|
||||
long elapsedNanos = SystemClock.elapsedRealtimeNanos();
|
||||
try {
|
||||
String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
long cacheTime = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
|
||||
|
||||
StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.PHOTOS_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.VIDEOS_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.AUDIO_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.SYSTEM_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
|
||||
e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
|
||||
e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER);
|
||||
e.writeLong(json.optLong(DiskStatsFileLogger.MISC_KEY, -1L));
|
||||
e.writeLong(cacheTime);
|
||||
pulledData.add(e);
|
||||
} catch (IOException | JSONException e) {
|
||||
Slog.e(TAG, "exception reading diskstats cache file", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls various data.
|
||||
*/
|
||||
@@ -1016,10 +1195,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
pullSystemElapsedRealtime(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DISK_SPACE: {
|
||||
pullDiskSpace(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.PROCESS_MEMORY_STATE: {
|
||||
pullProcessMemoryState(tagId, ret);
|
||||
break;
|
||||
@@ -1032,6 +1207,22 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
||||
pullBinderCallsStatsExceptions(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DISK_STATS: {
|
||||
pullDiskStats(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.DIRECTORY_USAGE: {
|
||||
pullDirectoryUsage(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.APP_SIZE: {
|
||||
pullAppSize(tagId, ret);
|
||||
break;
|
||||
}
|
||||
case StatsLog.CATEGORY_SIZE: {
|
||||
pullCategorySize(tagId, ret);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Slog.w(TAG, "No such tagId data as " + tagId);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user