Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 008ecd3d authored by Tej Singh's avatar Tej Singh Committed by Android (Google) Code Review
Browse files

Merge "DiskStats Westworld Migration"

parents e99f7d74 f154cf01
Loading
Loading
Loading
Loading
+85 −1
Original line number Diff line number Diff line
@@ -151,12 +151,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
@@ -2182,3 +2186,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;
}
+25 −4
Original line number Diff line number Diff line
@@ -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) {
+9 −0
Original line number Diff line number Diff line
@@ -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);
    }
+206 −15
Original line number Diff line number Diff line
@@ -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;