diff options
3 files changed, 52 insertions, 11 deletions
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java index 8283eb749376..72b0ad7a02bc 100644 --- a/core/java/com/android/internal/compat/ChangeReporter.java +++ b/core/java/com/android/internal/compat/ChangeReporter.java @@ -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,40 +51,62 @@ 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); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d81fa01bf9fa..d0ace377b00d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -349,6 +349,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; @@ -1561,6 +1562,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Encapsulates the global setting "hidden_api_blacklist_exemptions" final HiddenApiSettings mHiddenApiBlacklist; + private final PlatformCompat mPlatformCompat; + PackageManagerInternal mPackageManagerInt; /** @@ -2429,6 +2432,7 @@ public class ActivityManagerService extends IActivityManager.Stub mProcStartHandler = null; mHiddenApiBlacklist = null; mFactoryTest = FACTORY_TEST_OFF; + mPlatformCompat = null; } // 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); + 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. diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 852b26d1ff07..a7378880a91d 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -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); |