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

Commit b6336ddc authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement to log the status of enabling/disabling launcher components" into main

parents 8c0f3860 29e45bb8
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -3984,6 +3984,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService

        // packageName -> list of components to send broadcasts now
        final ArrayMap<String, ArrayList<String>> sendNowBroadcasts = new ArrayMap<>(targetSize);
        final List<PackageMetrics.ComponentStateMetrics> componentStateMetricsList =
                new ArrayList<PackageMetrics.ComponentStateMetrics>();
        synchronized (mLock) {
            Computer computer = snapshotComputer();
            boolean scheduleBroadcastMessage = false;
@@ -3997,11 +3999,17 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                // update enabled settings
                final ComponentEnabledSetting setting = settings.get(i);
                final String packageName = setting.getPackageName();
                if (!setEnabledSettingInternalLocked(computer, pkgSettings.get(packageName),
                        setting, userId, callingPackage)) {
                final PackageSetting packageSetting = pkgSettings.get(packageName);
                final PackageMetrics.ComponentStateMetrics componentStateMetrics =
                        new PackageMetrics.ComponentStateMetrics(setting,
                                UserHandle.getUid(userId, packageSetting.getAppId()),
                                packageSetting.getEnabled(userId));
                if (!setEnabledSettingInternalLocked(computer, packageSetting, setting, userId,
                        callingPackage)) {
                    continue;
                }
                anyChanged = true;
                componentStateMetricsList.add(componentStateMetrics);

                if ((setting.getEnabledFlags() & PackageManager.SYNCHRONOUS) != 0) {
                    isSynchronous = true;
@@ -4029,6 +4037,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                return;
            }

            // Log the metrics when the component state is changed.
            PackageMetrics.reportComponentStateChanged(computer, componentStateMetricsList, userId);

            if (isSynchronous) {
                flushPackageRestrictionsAsUserInternalLocked(userId);
            } else {
+83 −0
Original line number Diff line number Diff line
@@ -19,12 +19,21 @@ package com.android.server.pm;
import static android.os.Process.INVALID_UID;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.SecurityLog;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.Flags;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.util.FrameworkStatsLog;
@@ -41,12 +50,14 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Metrics class for reporting stats to logging infrastructures like statsd
 */
final class PackageMetrics {
    private static final String TAG = "PackageMetrics";
    public static final int STEP_PREPARE = 1;
    public static final int STEP_SCAN = 2;
    public static final int STEP_RECONCILE = 3;
@@ -344,4 +355,76 @@ final class PackageMetrics {
        SecurityLog.writeEvent(SecurityLog.TAG_PACKAGE_UNINSTALLED, packageName, versionCode,
                userId);
    }

    public static class ComponentStateMetrics {
        public int mUid;
        public int mComponentOldState;
        public int mComponentNewState;
        public boolean mIsForWholeApp;
        @NonNull private String mPackageName;
        @Nullable private String mClassName;

        ComponentStateMetrics(@NonNull PackageManager.ComponentEnabledSetting setting, int uid,
                int componentOldState) {
            mUid = uid;
            mComponentOldState = componentOldState;
            mComponentNewState = setting.getEnabledState();
            mIsForWholeApp = !setting.isComponent();
            mPackageName = setting.getPackageName();
            mClassName = setting.getClassName();
        }

        public boolean isSameComponent(ActivityInfo activityInfo) {
            if (activityInfo == null) {
                return false;
            }
            return mIsForWholeApp ? TextUtils.equals(activityInfo.packageName, mPackageName)
                    : activityInfo.getComponentName().equals(
                            new ComponentName(mPackageName, mClassName));
        }
    }

    public static void reportComponentStateChanged(@NonNull Computer computer,
            List<ComponentStateMetrics> componentStateMetricsList, @UserIdInt int userId) {
        if (!Flags.componentStateChangedMetrics()) {
            return;
        }
        if (componentStateMetricsList == null || componentStateMetricsList.isEmpty()) {
            Slog.d(TAG, "Fail to report component state due to metrics is empty");
            return;
        }
        boolean isLauncher = false;
        final List<ResolveInfo> resolveInfosForLauncher = getHomeActivitiesResolveInfoAsUser(
                computer, userId);
        final int resolveInfosForLauncherSize =
                resolveInfosForLauncher != null ? resolveInfosForLauncher.size() : 0;
        final int metricsSize = componentStateMetricsList.size();
        for (int i = 0; i < metricsSize; i++) {
            final ComponentStateMetrics componentStateMetrics = componentStateMetricsList.get(i);
            for (int j = 0; j < resolveInfosForLauncherSize; j++) {
                ResolveInfo resolveInfo = resolveInfosForLauncher.get(j);
                if (componentStateMetrics.isSameComponent(resolveInfo.activityInfo)) {
                    isLauncher = true;
                    break;
                }
            }
            reportComponentStateChanged(componentStateMetrics.mUid,
                    componentStateMetrics.mComponentOldState,
                    componentStateMetrics.mComponentNewState,
                    isLauncher,
                    componentStateMetrics.mIsForWholeApp);
        }
    }

    private static void reportComponentStateChanged(int uid, int componentOldState,
            int componentNewState, boolean isLauncher, boolean isForWholeApp) {
        FrameworkStatsLog.write(FrameworkStatsLog.COMPONENT_STATE_CHANGED_REPORTED,
                uid, componentOldState, componentNewState, isLauncher, isForWholeApp);
    }

    private static List<ResolveInfo> getHomeActivitiesResolveInfoAsUser(@NonNull Computer computer,
            @UserIdInt int userId) {
        return computer.queryIntentActivitiesInternal(computer.getHomeIntent(), /* resolvedType */
                null, /* flags */ 0, userId);
    }
}