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

Commit 92cf9a2d authored by Ruchir Rastogi's avatar Ruchir Rastogi
Browse files

Migrate ProcStats(PkgProc) pullers to new API

Test: adb shell cmd stats pull-source 10029
Test: adb shell cmd stats pull-source 10034
Bug: 145565211
Change-Id: I40c770d750f03ec179b266cd480bc2bc12666df6
parent 108ac3af
Loading
Loading
Loading
Loading
+0 −103
Original line number Diff line number Diff line
@@ -714,98 +714,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
        }
    }

    // read high watermark for section
    private long readProcStatsHighWaterMark(int section) {
        try {
            File[] files = mBaseDir.listFiles((d, name) -> {
                return name.toLowerCase().startsWith(String.valueOf(section) + '_');
            });
            if (files == null || files.length == 0) {
                return 0;
            }
            if (files.length > 1) {
                Log.e(TAG, "Only 1 file expected for high water mark. Found " + files.length);
            }
            return Long.valueOf(files[0].getName().split("_")[1]);
        } catch (SecurityException e) {
            Log.e(TAG, "Failed to get procstats high watermark file.", e);
        } catch (NumberFormatException e) {
            Log.e(TAG, "Failed to parse file name.", e);
        }
        return 0;
    }

    private IProcessStats mProcessStats =
            IProcessStats.Stub.asInterface(ServiceManager.getService(ProcessStats.SERVICE_NAME));

    private void pullProcessStats(int section, int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        synchronized (this) {
            try {
                long lastHighWaterMark = readProcStatsHighWaterMark(section);
                List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
                long highWaterMark = mProcessStats.getCommittedStats(
                        lastHighWaterMark, section, true, statsFiles);
                if (statsFiles.size() != 1) {
                    return;
                }
                unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
                new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
                        + lastHighWaterMark).delete();
                new File(
                        mBaseDir.getAbsolutePath() + "/" + section + "_"
                                + highWaterMark).createNewFile();
            } catch (IOException e) {
                Log.e(TAG, "Getting procstats failed: ", e);
            } catch (RemoteException e) {
                Log.e(TAG, "Getting procstats failed: ", e);
            } catch (SecurityException e) {
                Log.e(TAG, "Getting procstats failed: ", e);
            }
        }
    }

    static void unpackStreamedData(int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData, List<ParcelFileDescriptor> statsFiles)
            throws IOException {
        InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
                statsFiles.get(0));
        int[] len = new int[1];
        byte[] stats = readFully(stream, len);
        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
                wallClockNanos);
        e.writeStorage(Arrays.copyOf(stats, len[0]));
        pulledData.add(e);
    }

    static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
        int pos = 0;
        final int initialAvail = stream.available();
        byte[] data = new byte[initialAvail > 0 ? (initialAvail + 1) : 16384];
        while (true) {
            int amt = stream.read(data, pos, data.length - pos);
            if (DEBUG) {
                Slog.i(TAG, "Read " + amt + " bytes at " + pos + " of avail " + data.length);
            }
            if (amt < 0) {
                if (DEBUG) {
                    Slog.i(TAG, "**** FINISHED READING: pos=" + pos + " len=" + data.length);
                }
                outLen[0] = pos;
                return data;
            }
            pos += amt;
            if (pos >= data.length) {
                byte[] newData = new byte[pos + 16384];
                if (DEBUG) {
                    Slog.i(TAG, "Copying " + pos + " bytes to new array len " + newData.length);
                }
                System.arraycopy(data, 0, newData, 0, pos);
                data = newData;
            }
        }
    }

    private void pullDebugElapsedClock(int tagId,
            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
        final long elapsedMillis = SystemClock.elapsedRealtime();
@@ -907,17 +815,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
        long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
        switch (tagId) {

            case StatsLog.PROC_STATS: {
                pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.PROC_STATS_PKG_PROC: {
                pullProcessStats(ProcessStats.REPORT_PKG_PROC_STATS, tagId, elapsedNanos,
                        wallClockNanos, ret);
                break;
            }

            case StatsLog.DEBUG_ELAPSED_CLOCK: {
                pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
                break;
+0 −8
Original line number Diff line number Diff line
@@ -86,14 +86,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
        {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},

        // ProcStats.
        {{.atomTag = android::util::PROC_STATS},
         {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}},

        // ProcStatsPkgProc.
        {{.atomTag = android::util::PROC_STATS_PKG_PROC},
         {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},

        // DebugElapsedClock.
        {{.atomTag = android::util::DEBUG_ELAPSED_CLOCK},
         {.additiveFields = {1, 2, 3, 4},
+110 −12
Original line number Diff line number Diff line
@@ -196,16 +196,23 @@ public class StatsPullAtomService extends SystemService {
    private final Object mNetworkStatsLock = new Object();
    @GuardedBy("mNetworkStatsLock")
    private INetworkStatsService mNetworkStatsService;

    private final Object mThermalLock = new Object();
    @GuardedBy("mThermalLock")
    private IThermalService mThermalService;

    private final Object mStoragedLock = new Object();
    @GuardedBy("mStoragedLock")
    private IStoraged mStorageService;

    private final Object mNotificationStatsLock = new Object();
    @GuardedBy("mNotificationStatsLock")
    private INotificationManager mNotificationManagerService;

    private final Object mProcessStatsLock = new Object();
    @GuardedBy("mProcessStatsLock")
    private IProcessStats mProcessStatsService;

    private final Context mContext;
    private StatsManager mStatsManager;
    private StorageManager mStorageManager;
@@ -222,7 +229,7 @@ public class StatsPullAtomService extends SystemService {
        mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);

        // Used to initialize the CPU Frequency atom.
        // Initialize state for CPU_TIME_PER_FREQ atom
        PowerProfile powerProfile = new PowerProfile(mContext);
        final int numClusters = powerProfile.getNumCpuClusters();
        mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
@@ -237,6 +244,9 @@ public class StatsPullAtomService extends SystemService {
        // Used for CPU_TIME_PER_THREAD_FREQ
        mKernelCpuThreadReader =
                KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);

        // Used by PROC_STATS and PROC_STATS_PKG_PROC atoms
        mBaseDir.mkdirs();
    }

    @Override
@@ -403,6 +413,28 @@ public class StatsPullAtomService extends SystemService {
        return mNotificationManagerService;
    }

    private IProcessStats getIProcessStatsService() {
        synchronized (mProcessStatsLock) {
            if (mProcessStatsService == null) {
                mProcessStatsService = IProcessStats.Stub.asInterface(
                        ServiceManager.getService(ProcessStats.SERVICE_NAME));
            }
            if (mProcessStatsService != null) {
                try {
                    mProcessStatsService.asBinder().linkToDeath(() -> {
                        synchronized (mProcessStatsLock) {
                            mProcessStatsService = null;
                        }
                    }, /* flags */ 0);
                } catch (RemoteException e) {
                    Slog.e(TAG, "linkToDeath with ProcessStats failed", e);
                    mProcessStatsService = null;
                }
            }
        }
        return mProcessStatsService;
    }

    private void registerWifiBytesTransfer() {
        int tagId = StatsLog.WIFI_BYTES_TRANSFER;
        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
@@ -1868,22 +1900,88 @@ public class StatsPullAtomService extends SystemService {
        return StatsManager.PULL_SUCCESS;
    }

    private File mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_companion");

    private void registerProcStats() {
        // No op.
        int tagId = StatsLog.PROC_STATS;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_ALL, atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullProcStats() {
        // No op.
    private void registerProcStatsPkgProc() {
        int tagId = StatsLog.PROC_STATS_PKG_PROC;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void registerProcStatsPkgProc() {
        // No op.
    private int pullProcStats(int section, int atomTag, List<StatsEvent> pulledData) {
        IProcessStats processStatsService = getIProcessStatsService();
        if (processStatsService == null) {
            return StatsManager.PULL_SKIP;
        }

    private void pullProcStatsPkgProc() {
        // No op.
        synchronized (mProcessStatsLock) {
            final long token = Binder.clearCallingIdentity();
            try {
                long lastHighWaterMark = readProcStatsHighWaterMark(section);
                List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
                long highWaterMark = processStatsService.getCommittedStats(
                        lastHighWaterMark, section, true, statsFiles);
                if (statsFiles.size() != 1) {
                    return StatsManager.PULL_SKIP;
                }
                unpackStreamedData(atomTag, pulledData, statsFiles);
                new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
                        .delete();
                new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
                        .createNewFile();
            } catch (IOException e) {
                Slog.e(TAG, "Getting procstats failed: ", e);
                return StatsManager.PULL_SKIP;
            } catch (RemoteException e) {
                Slog.e(TAG, "Getting procstats failed: ", e);
                return StatsManager.PULL_SKIP;
            } catch (SecurityException e) {
                Slog.e(TAG, "Getting procstats failed: ", e);
                return StatsManager.PULL_SKIP;
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        return StatsManager.PULL_SUCCESS;
    }

    // read high watermark for section
    private long readProcStatsHighWaterMark(int section) {
        try {
            File[] files = mBaseDir.listFiles((d, name) -> {
                return name.toLowerCase().startsWith(String.valueOf(section) + '_');
            });
            if (files == null || files.length == 0) {
                return 0;
            }
            if (files.length > 1) {
                Slog.e(TAG, "Only 1 file expected for high water mark. Found " + files.length);
            }
            return Long.valueOf(files[0].getName().split("_")[1]);
        } catch (SecurityException e) {
            Slog.e(TAG, "Failed to get procstats high watermark file.", e);
        } catch (NumberFormatException e) {
            Slog.e(TAG, "Failed to parse file name.", e);
        }
        return 0;
    }


    private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
            new StoragedUidIoStatsReader();

@@ -2516,7 +2614,7 @@ public class StatsPullAtomService extends SystemService {
    }

    private int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
        long token = Binder.clearCallingIdentity();
        final long token = Binder.clearCallingIdentity();
        try {
            AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);

@@ -2632,7 +2730,7 @@ public class StatsPullAtomService extends SystemService {
        }
        final long callingToken = Binder.clearCallingIdentity();
        try {
            // determine last pull tine. Copy file trick from pullProcessStats?
            // determine last pull tine. Copy file trick from pullProcStats?
            long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
            long lastNotificationStatsNs = wallClockNanos -
                    TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);