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

Commit c4c45a8b authored by Marcin Oczeretko's avatar Marcin Oczeretko
Browse files

LooperStats - convert UIDs to package names in dump

Test: Manually called adb shell dumpsys looper_stats and UTs
Change-Id: I9e5e4560172da92a4a313af0207486a4dd7e64d3
parent 37fa1033
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.os;


import android.app.AppGlobals;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.UserHandle;

import com.android.internal.annotations.VisibleForTesting;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Maps AppIds to their package names. */
public final class AppIdToPackageMap {
    private final Map<Integer, String> mAppIdToPackageMap;

    @VisibleForTesting
    public AppIdToPackageMap(Map<Integer, String> appIdToPackageMap) {
        mAppIdToPackageMap = appIdToPackageMap;
    }

    /** Creates a new {@link AppIdToPackageMap} for currently installed packages. */
    public static AppIdToPackageMap getSnapshot() {
        List<PackageInfo> packages;
        try {
            packages = AppGlobals.getPackageManager()
                    .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE,
                            UserHandle.USER_SYSTEM).getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        final Map<Integer, String> map = new HashMap<>();
        for (PackageInfo pkg : packages) {
            final int uid = pkg.applicationInfo.uid;
            if (pkg.sharedUserId != null && map.containsKey(uid)) {
                // Use sharedUserId string as package name if there are collisions
                map.put(uid, "shared:" + pkg.sharedUserId);
            } else {
                map.put(uid, pkg.packageName);
            }
        }
        return new AppIdToPackageMap(map);
    }

    /** Maps the AppId to a package name. */
    public String mapAppId(int appId) {
        String pkgName = mAppIdToPackageMap.get(appId);
        return pkgName == null ? String.valueOf(appId) : pkgName;
    }

    /** Maps the UID to a package name. */
    public String mapUid(int uid) {
        final int appId = UserHandle.getAppId(uid);
        final String pkgName = mAppIdToPackageMap.get(appId);
        final String uidStr = UserHandle.formatUid(uid);
        return pkgName == null ? uidStr : pkgName + '/' + uidStr;
    }
}
+6 −15
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.os.Binder;
import android.os.Process;
import android.os.SystemClock;
import android.os.ThreadLocalWorkSource;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.Pair;
@@ -356,14 +355,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
    }

    /** Writes the collected statistics to the supplied {@link PrintWriter}.*/
    public void dump(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap, boolean verbose) {
    public void dump(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
        synchronized (mLock) {
            dumpLocked(pw, appIdToPkgNameMap, verbose);
            dumpLocked(pw, packageMap, verbose);
        }
    }

    private void dumpLocked(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap,
            boolean verbose) {
    private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
        long totalCallsCount = 0;
        long totalRecordedCallsCount = 0;
        long totalCpuTime = 0;
@@ -397,9 +395,9 @@ public class BinderCallsStats implements BinderInternal.Observer {
        for (ExportedCallStat e : exportedCallStats) {
            sb.setLength(0);
            sb.append("    ")
                    .append(uidToString(e.callingUid, appIdToPkgNameMap))
                    .append(packageMap.mapUid(e.callingUid))
                    .append(',')
                    .append(uidToString(e.workSourceUid, appIdToPkgNameMap))
                    .append(packageMap.mapUid(e.workSourceUid))
                    .append(',').append(e.className)
                    .append('#').append(e.methodName)
                    .append(',').append(e.screenInteractive)
@@ -420,7 +418,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
        final List<UidEntry> summaryEntries = verbose ? entries
                : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
        for (UidEntry entry : summaryEntries) {
            String uidStr = uidToString(entry.workSourceUid, appIdToPkgNameMap);
            String uidStr = packageMap.mapUid(entry.workSourceUid);
            pw.println(String.format("  %10d %3.0f%% %8d %8d %s",
                    entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
                    entry.recordedCallCount, entry.callCount, uidStr));
@@ -448,13 +446,6 @@ public class BinderCallsStats implements BinderInternal.Observer {
        }
    }

    private static String uidToString(int uid, Map<Integer, String> pkgNameMap) {
        final int appId = UserHandle.getAppId(uid);
        final String pkgName = pkgNameMap == null ? null : pkgNameMap.get(appId);
        final String uidStr = UserHandle.formatUid(uid);
        return pkgName == null ? uidStr : pkgName + '/' + uidStr;
    }

    protected long getThreadTimeMicro() {
        return SystemClock.currentThreadTimeMicro();
    }
+1 −1
Original line number Diff line number Diff line
@@ -484,7 +484,7 @@ public class BinderCallsStatsTest {
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        PrintWriter pw = new PrintWriter(new StringWriter());
        bcs.dump(pw, new HashMap<>(), true);
        bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), true);
    }

    @Test
+5 −30
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;

import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -28,7 +27,6 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.ThreadLocalWorkSource;
import android.os.UserHandle;
@@ -39,6 +37,7 @@ import android.util.KeyValueListParser;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AppIdToPackageMap;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
@@ -48,9 +47,7 @@ import com.android.internal.os.CachedDeviceState;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BinderCallsStatsService extends Binder {

@@ -82,11 +79,11 @@ public class BinderCallsStatsService extends Binder {
            mAppIdWhitelist = createAppidWhitelist(context);
        }

        public void dump(PrintWriter pw, Map<Integer, String> appIdToPackageName) {
        public void dump(PrintWriter pw, AppIdToPackageMap packageMap) {
            pw.println("AppIds of apps that can set the work source:");
            final ArraySet<Integer> whitelist = mAppIdWhitelist;
            for (Integer appId : whitelist) {
                pw.println("\t- " + appIdToPackageName.getOrDefault(appId, String.valueOf(appId)));
                pw.println("\t- " + packageMap.mapAppId(appId));
            }
        }

@@ -361,7 +358,7 @@ public class BinderCallsStatsService extends Binder {
                    pw.println("Detailed tracking disabled");
                    return;
                } else if ("--dump-worksource-provider".equals(arg)) {
                    mWorkSourceProvider.dump(pw, getAppIdToPackagesMap());
                    mWorkSourceProvider.dump(pw, AppIdToPackageMap.getSnapshot());
                    return;
                } else if ("-h".equals(arg)) {
                    pw.println("binder_calls_stats commands:");
@@ -377,28 +374,6 @@ public class BinderCallsStatsService extends Binder {
                }
            }
        }
        mBinderCallsStats.dump(pw, getAppIdToPackagesMap(), verbose);
    }

    private Map<Integer, String> getAppIdToPackagesMap() {
        List<PackageInfo> packages;
        try {
            packages = AppGlobals.getPackageManager()
                    .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES,
                            UserHandle.USER_SYSTEM).getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        Map<Integer,String> map = new HashMap<>();
        for (PackageInfo pkg : packages) {
            String name = pkg.packageName;
            int uid = pkg.applicationInfo.uid;
            // Use sharedUserId string as package name if there are collisions
            if (pkg.sharedUserId != null && map.containsKey(uid)) {
                name = "shared:" + pkg.sharedUserId;
            }
            map.put(uid, name);
        }
        return map;
        mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), verbose);
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.text.format.DateFormat;
import android.util.KeyValueListParser;
import android.util.Slog;

import com.android.internal.os.AppIdToPackageMap;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.CachedDeviceState;
import com.android.internal.os.LooperStats;
@@ -92,6 +93,7 @@ public class LooperStatsService extends Binder {
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        AppIdToPackageMap packageMap = AppIdToPackageMap.getSnapshot();
        pw.print("Start time: ");
        pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStats.getStartTimeMillis()));
        pw.print("On battery time (ms): ");
@@ -121,7 +123,7 @@ public class LooperStatsService extends Binder {
        pw.println(header);
        for (LooperStats.ExportedEntry entry : entries) {
            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
                    entry.workSourceUid,
                    packageMap.mapUid(entry.workSourceUid),
                    entry.threadName,
                    entry.handlerClassName,
                    entry.messageName,