diff options
| author | 2021-03-21 22:56:05 +0000 | |
|---|---|---|
| committer | 2021-03-21 22:56:05 +0000 | |
| commit | 41ec7a8e38b8dc297b31e8f31a543a300adf14ca (patch) | |
| tree | bdbd5f634ebcf2ee012888c4d0c7c17abc975595 | |
| parent | 80e8713490d1567d4e0de354414698744f5a5933 (diff) | |
| parent | 3c46aca4901efed151be0a7f950723fdd2073651 (diff) | |
Merge "Add device config parameters to DiscreteRegistry." into sc-dev
3 files changed, 72 insertions, 12 deletions
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index e9bbcc79e9df..e68f330a2129 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -646,7 +646,7 @@ public final class DeviceConfig { * @param name The name of the property to look up. * @param defaultValue The value to return if the property does not exist or has no non-null * value. - * @return the corresponding value, or defaultValue if none exists. + * @return the correspondfing value, or defaultValue if none exists. * @hide */ @SystemApi diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java index 2b0157c88136..e16a6cc6fefc 100644 --- a/services/core/java/com/android/server/appop/DiscreteRegistry.java +++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java @@ -31,14 +31,18 @@ import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.flagsToString; import static android.app.AppOpsManager.getUidStateName; +import static java.lang.Long.min; import static java.lang.Math.max; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; +import android.os.AsyncTask; +import android.os.Build; import android.os.Environment; import android.os.FileUtils; import android.os.Process; +import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.Slog; import android.util.TypedXmlPullParser; @@ -82,8 +86,16 @@ final class DiscreteRegistry { static final String TIMELINE_FILE_SUFFIX = "tl"; private static final String TAG = DiscreteRegistry.class.getSimpleName(); - private static final long TIMELINE_HISTORY_CUTOFF = Duration.ofHours(24).toMillis(); - private static final long TIMELINE_QUANTIZATION = Duration.ofMinutes(1).toMillis(); + private static final String PROPERTY_DISCRETE_HISTORY_CUTOFF = "discrete_history_cutoff_millis"; + private static final String PROPERTY_DISCRETE_HISTORY_QUANTIZATION = + "discrete_history_quantization_millis"; + private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofHours(24).toMillis(); + private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis(); + private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION = + Duration.ofMinutes(1).toMillis(); + + private static long sDiscreteHistoryCutoff; + private static long sDiscreteHistoryQuantization; private static final String TAG_HISTORY = "h"; private static final String ATTR_VERSION = "v"; @@ -116,7 +128,7 @@ final class DiscreteRegistry { private final @NonNull Object mInMemoryLock; @GuardedBy("mOnDiskLock") - private final File mDiscreteAccessDir; + private File mDiscreteAccessDir; @GuardedBy("mInMemoryLock") private DiscreteOps mDiscreteOps; @@ -126,10 +138,42 @@ final class DiscreteRegistry { DiscreteRegistry(Object inMemoryLock) { mInMemoryLock = inMemoryLock; - mDiscreteAccessDir = new File(new File(Environment.getDataSystemDirectory(), "appops"), - "discrete"); - createDiscreteAccessDir(); - mDiscreteOps = new DiscreteOps(); + } + + void systemReady() { + synchronized (mOnDiskLock) { + mDiscreteAccessDir = new File(new File(Environment.getDataSystemDirectory(), "appops"), + "discrete"); + createDiscreteAccessDirLocked(); + mDiscreteOps = new DiscreteOps(); + } + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY, + AsyncTask.THREAD_POOL_EXECUTOR, (DeviceConfig.Properties p) -> { + setDiscreteHistoryParameters(p); + }); + sDiscreteHistoryCutoff = DeviceConfig.getLong(DeviceConfig.NAMESPACE_PRIVACY, + PROPERTY_DISCRETE_HISTORY_CUTOFF, DEFAULT_DISCRETE_HISTORY_CUTOFF); + sDiscreteHistoryQuantization = DeviceConfig.getLong(DeviceConfig.NAMESPACE_PRIVACY, + PROPERTY_DISCRETE_HISTORY_QUANTIZATION, DEFAULT_DISCRETE_HISTORY_QUANTIZATION); + } + + private void setDiscreteHistoryParameters(DeviceConfig.Properties p) { + if (p.getKeyset().contains(PROPERTY_DISCRETE_HISTORY_CUTOFF)) { + sDiscreteHistoryCutoff = p.getLong(PROPERTY_DISCRETE_HISTORY_CUTOFF, + DEFAULT_DISCRETE_HISTORY_CUTOFF); + if (!Build.IS_DEBUGGABLE) { + sDiscreteHistoryCutoff = min(MAXIMUM_DISCRETE_HISTORY_CUTOFF, + sDiscreteHistoryCutoff); + } + } + if (p.getKeyset().contains(PROPERTY_DISCRETE_HISTORY_QUANTIZATION)) { + sDiscreteHistoryQuantization = p.getLong(PROPERTY_DISCRETE_HISTORY_QUANTIZATION, + DEFAULT_DISCRETE_HISTORY_QUANTIZATION); + if (!Build.IS_DEBUGGABLE) { + sDiscreteHistoryQuantization = max(DEFAULT_DISCRETE_HISTORY_QUANTIZATION, + sDiscreteHistoryQuantization); + } + } } private void createDiscreteAccessDir() { @@ -142,6 +186,7 @@ final class DiscreteRegistry { } } + /* can be called only after HistoricalRegistry.isPersistenceInitialized() check */ void recordDiscreteAccess(int uid, String packageName, int op, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration) { @@ -156,6 +201,10 @@ final class DiscreteRegistry { void writeAndClearAccessHistory() { synchronized (mOnDiskLock) { + if (mDiscreteAccessDir == null) { + Slog.e(TAG, "State not saved - persistence not initialized."); + return; + } final File[] files = mDiscreteAccessDir.listFiles(); if (files != null && files.length > 0) { for (File f : files) { @@ -166,7 +215,7 @@ final class DiscreteRegistry { try { long timestamp = Long.valueOf(fileName.substring(0, fileName.length() - TIMELINE_FILE_SUFFIX.length())); - if (Instant.now().minus(TIMELINE_HISTORY_CUTOFF, + if (Instant.now().minus(sDiscreteHistoryCutoff, ChronoUnit.MILLIS).toEpochMilli() > timestamp) { f.delete(); Slog.e(TAG, "Deleting file " + fileName); @@ -229,7 +278,7 @@ final class DiscreteRegistry { private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) { synchronized (mOnDiskLock) { - long beginTimeMillis = Instant.now().minus(TIMELINE_HISTORY_CUTOFF, + long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff, ChronoUnit.MILLIS).toEpochMilli(); final File[] files = mDiscreteAccessDir.listFiles(); @@ -423,6 +472,16 @@ final class DiscreteRegistry { } } + private void createDiscreteAccessDirLocked() { + if (!mDiscreteAccessDir.exists()) { + if (!mDiscreteAccessDir.mkdirs()) { + Slog.e(TAG, "Failed to create DiscreteRegistry directory"); + } + FileUtils.setPermissions(mDiscreteAccessDir.getPath(), + FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH, -1, -1); + } + } + private final class DiscreteUidOps { ArrayMap<String, DiscretePackageOps> mPackages; @@ -663,7 +722,7 @@ final class DiscreteRegistry { long accessTime, long accessDuration) { List<DiscreteOpEvent> attributedOps = getOrCreateDiscreteOpEventsList( attributionTag); - accessTime = accessTime / TIMELINE_QUANTIZATION * TIMELINE_QUANTIZATION; + accessTime = accessTime / sDiscreteHistoryQuantization * sDiscreteHistoryQuantization; int nAttributedOps = attributedOps.size(); int i = nAttributedOps; @@ -674,7 +733,7 @@ final class DiscreteRegistry { } if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState) { if (accessDuration != previousOp.mNoteDuration - && accessDuration > TIMELINE_QUANTIZATION) { + && accessDuration > sDiscreteHistoryQuantization) { break; } else { return; diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index 4435c4795730..9ff54926df3a 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -246,6 +246,7 @@ final class HistoricalRegistry { + " by which to push history on next write"); } } + mDiscreteRegistry.systemReady(); } } } |