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

Commit b1f8ccfb authored by Ruchir Rastogi's avatar Ruchir Rastogi Committed by Android (Google) Code Review
Browse files

Merge "Migrate ProcStats(PkgProc) pullers to new API"

parents 743032e0 92cf9a2d
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();
@@ -870,17 +778,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();

@@ -2562,7 +2660,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);

@@ -2678,7 +2776,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);