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

Commit 893f84d3 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
Merged-In: I24f5dc125488c6af3164b6503f236bc3a24e6292
parent 90a84e26
Loading
Loading
Loading
Loading
+33 −11
Original line number Original line Diff line number Diff line
@@ -22,7 +22,9 @@ import android.util.StatsLog;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;


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


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


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


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


        @Override
        @Override
        public int hashCode() {
        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")
    @GuardedBy("mReportedChanges")
    private Set<ChangeReport> mReportedChanges =  new HashSet<>();
    private final Map<Integer, Set<ChangeReport>> mReportedChanges;


    public ChangeReporter(int source) {
    public ChangeReporter(int source) {
        mSource = 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 uid      affected by the change
     * @param changeId the reported change id
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     * @param state    of the reported change - enabled/disabled/only logged
     */
     */
    public void reportChange(int uid, long changeId, int state) {
    public void reportChange(int uid, long changeId, int state) {
        ChangeReport report = new ChangeReport(uid, changeId, state);
        ChangeReport report = new ChangeReport(changeId, state);
        synchronized (mReportedChanges) {
        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);
                debugLog(uid, changeId, state);
                StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                        state, mSource);
                        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) {
    private void debugLog(int uid, long changeId, int state) {
+10 −0
Original line number Original line Diff line number Diff line
@@ -349,6 +349,7 @@ import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.appop.AppOpsService;
import com.android.server.appop.AppOpsService;
import com.android.server.compat.CompatConfig;
import com.android.server.compat.CompatConfig;
import com.android.server.compat.PlatformCompat;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.firewall.IntentFirewall;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerInternal;
@@ -1561,6 +1562,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    // Encapsulates the global setting "hidden_api_blacklist_exemptions"
    // Encapsulates the global setting "hidden_api_blacklist_exemptions"
    final HiddenApiSettings mHiddenApiBlacklist;
    final HiddenApiSettings mHiddenApiBlacklist;
    private final PlatformCompat mPlatformCompat;
    PackageManagerInternal mPackageManagerInt;
    PackageManagerInternal mPackageManagerInt;
    /**
    /**
@@ -2429,6 +2432,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcStartHandler = null;
        mProcStartHandler = null;
        mHiddenApiBlacklist = null;
        mHiddenApiBlacklist = null;
        mFactoryTest = FACTORY_TEST_OFF;
        mFactoryTest = FACTORY_TEST_OFF;
        mPlatformCompat = null;
    }
    }
    // Note: This method is invoked on the main thread but may need to attach various
    // Note: This method is invoked on the main thread but may need to attach various
@@ -2565,6 +2569,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
        mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
        mPlatformCompat = (PlatformCompat) ServiceManager.getService(
                Context.PLATFORM_COMPAT_SERVICE);
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
        Watchdog.getInstance().addThread(mHandler);
@@ -5042,6 +5049,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
            if (mPlatformCompat != null) {
                mPlatformCompat.resetReporting(app.info);
            }
            if (app.isolatedEntryPoint != null) {
            if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                // being bound to an application.
+9 −0
Original line number Original line Diff line number Diff line
@@ -105,6 +105,15 @@ public class PlatformCompat extends IPlatformCompat.Stub {
        CompatConfig.get().dumpConfig(pw);
        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) {
    private ApplicationInfo getApplicationInfo(String packageName) {
        try {
        try {
            return mContext.getPackageManager().getApplicationInfo(packageName, 0);
            return mContext.getPackageManager().getApplicationInfo(packageName, 0);