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

Commit 8e437d45 authored by atrost's avatar atrost
Browse files

Reset app reporting on app launch.

Store the reported changes by app and clear the app info on app launch.
This means that changes reported to the system server would be logged
once per app launch instead of once per device boot.

Bug: 138374585
Test: flash device, run test app
Change-Id: I24f5dc125488c6af3164b6503f236bc3a24e6292
parent 25e071c7
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ import android.util.StatsLog;

import com.android.internal.annotations.GuardedBy;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@@ -36,12 +38,10 @@ public final class ChangeReporter {
    private int mSource;

    private final class ChangeReport {
        int mUid;
        long mChangeId;
        int mState;

        ChangeReport(int uid, long changeId, int state) {
            mUid = uid;
        ChangeReport(long changeId, int state) {
            mChangeId = changeId;
            mState = state;
        }
@@ -51,41 +51,63 @@ public final class ChangeReporter {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ChangeReport that = (ChangeReport) o;
            return mUid == that.mUid
                    && mChangeId == that.mChangeId
            return mChangeId == that.mChangeId
                    && mState == that.mState;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mUid, mChangeId, mState);
            return Objects.hash(mChangeId, mState);
        }
    }

    // Maps uid to a set of ChangeReports (that were reported for that uid).
    @GuardedBy("mReportedChanges")
    private Set<ChangeReport> mReportedChanges =  new HashSet<>();
    private final Map<Integer, Set<ChangeReport>> mReportedChanges;

    public ChangeReporter(int source) {
        mSource = source;
        mReportedChanges =  new HashMap<>();
    }

    /**
     * Report the change to stats log.
     * Report the change to stats log and to the debug log if the change was not previously
     * logged already.
     *
     * @param uid      affected by the change
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     */
    public void reportChange(int uid, long changeId, int state) {
        ChangeReport report = new ChangeReport(uid, changeId, state);
        ChangeReport report = new ChangeReport(changeId, state);
        synchronized (mReportedChanges) {
            if (!mReportedChanges.contains(report)) {
            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
            if (reportedChangesForUid == null) {
                mReportedChanges.put(uid, new HashSet<ChangeReport>());
                reportedChangesForUid = mReportedChanges.get(uid);
            }
            if (!reportedChangesForUid.contains(report)) {
                debugLog(uid, changeId, state);
                StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                        state, mSource);
                mReportedChanges.add(report);
                reportedChangesForUid.add(report);
            }

        }
    }

    /**
     * Clears the saved information about a given uid. Requests to report uid again will be reported
     * regardless to the past reports.
     *
     * <p> Only intended to be called from PlatformCompat.
     *
     * @param uid to reset
     */
    public void resetReportedChanges(int uid) {
        synchronized (mReportedChanges) {
            mReportedChanges.remove(uid);
        }
    }

    private void debugLog(int uid, long changeId, int state) {
+10 −0
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@ import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.appop.AppOpsService;
import com.android.server.compat.CompatConfig;
import com.android.server.compat.PlatformCompat;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
@@ -1575,6 +1576,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    // Encapsulates the global setting "hidden_api_blacklist_exemptions"
    final HiddenApiSettings mHiddenApiBlacklist;
    private final PlatformCompat mPlatformCompat;
    PackageManagerInternal mPackageManagerInt;
    PermissionManagerServiceInternal mPermissionManagerInt;
@@ -2427,6 +2430,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mFactoryTest = FACTORY_TEST_OFF;
        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
        mInternal = new LocalService();
        mPlatformCompat = null;
    }
    // Note: This method is invoked on the main thread but may need to attach various
@@ -2563,6 +2567,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
        mPlatformCompat = (PlatformCompat) ServiceManager.getService(
                Context.PLATFORM_COMPAT_SERVICE);
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
@@ -5042,6 +5049,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
            if (mPlatformCompat != null) {
                mPlatformCompat.resetReporting(app.info);
            }
            if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
+9 −0
Original line number Diff line number Diff line
@@ -105,6 +105,15 @@ public class PlatformCompat extends IPlatformCompat.Stub {
        CompatConfig.get().dumpConfig(pw);
    }

    /**
     * Clears information stored about events reported on behalf of an app.
     * To be called once upon app start or end. A second call would be a no-op.
     * @param appInfo the app to reset
     */
    public void resetReporting(ApplicationInfo appInfo) {
        mChangeReporter.resetReportedChanges(appInfo.uid);
    }

    private ApplicationInfo getApplicationInfo(String packageName) {
        try {
            return mContext.getPackageManager().getApplicationInfo(packageName, 0);