Loading services/core/java/com/android/server/appop/DiscreteRegistry.java +95 −17 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.appop; package com.android.server.appop; import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; Loading Loading @@ -58,7 +59,9 @@ import com.android.internal.util.XmlUtils; import java.io.File; import java.io.File; import java.io.FileInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.Duration; Loading Loading @@ -138,6 +141,7 @@ final class DiscreteRegistry { private static final String TAG_HISTORY = "h"; private static final String TAG_HISTORY = "h"; private static final String ATTR_VERSION = "v"; private static final String ATTR_VERSION = "v"; private static final String ATTR_LARGEST_CHAIN_ID = "lc"; private static final int CURRENT_VERSION = 1; private static final int CURRENT_VERSION = 1; private static final String TAG_UID = "u"; private static final String TAG_UID = "u"; Loading Loading @@ -182,6 +186,16 @@ final class DiscreteRegistry { DiscreteRegistry(Object inMemoryLock) { DiscreteRegistry(Object inMemoryLock) { mInMemoryLock = inMemoryLock; mInMemoryLock = inMemoryLock; synchronized (mOnDiskLock) { mDiscreteAccessDir = new File( new File(Environment.getDataSystemDirectory(), "appops"), "discrete"); createDiscreteAccessDirLocked(); int largestChainId = readLargestChainIdFromDiskLocked(); synchronized (mInMemoryLock) { mDiscreteOps = new DiscreteOps(largestChainId); } } } } void systemReady() { void systemReady() { Loading @@ -190,15 +204,6 @@ final class DiscreteRegistry { setDiscreteHistoryParameters(p); setDiscreteHistoryParameters(p); }); }); setDiscreteHistoryParameters(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_PRIVACY)); setDiscreteHistoryParameters(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_PRIVACY)); synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { mDiscreteAccessDir = new File( new File(Environment.getDataSystemDirectory(), "appops"), "discrete"); createDiscreteAccessDirLocked(); mDiscreteOps = new DiscreteOps(); } } } } private void setDiscreteHistoryParameters(DeviceConfig.Properties p) { private void setDiscreteHistoryParameters(DeviceConfig.Properties p) { Loading Loading @@ -251,7 +256,7 @@ final class DiscreteRegistry { DiscreteOps discreteOps; DiscreteOps discreteOps; synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { discreteOps = mDiscreteOps; discreteOps = mDiscreteOps; mDiscreteOps = new DiscreteOps(); mDiscreteOps = new DiscreteOps(discreteOps.mChainIdOffset); mCachedOps = null; mCachedOps = null; } } deleteOldDiscreteHistoryFilesLocked(); deleteOldDiscreteHistoryFilesLocked(); Loading @@ -275,6 +280,50 @@ final class DiscreteRegistry { return; return; } } private int readLargestChainIdFromDiskLocked() { final File[] files = mDiscreteAccessDir.listFiles(); if (files != null && files.length > 0) { File latestFile = null; long latestFileTimestamp = 0; for (File f : files) { final String fileName = f.getName(); if (!fileName.endsWith(DISCRETE_HISTORY_FILE_SUFFIX)) { continue; } long timestamp = Long.valueOf(fileName.substring(0, fileName.length() - DISCRETE_HISTORY_FILE_SUFFIX.length())); if (latestFileTimestamp < timestamp) { latestFile = f; latestFileTimestamp = timestamp; } } if (latestFile == null) { return 0; } FileInputStream stream; try { stream = new FileInputStream(latestFile); } catch (FileNotFoundException e) { return 0; } try { TypedXmlPullParser parser = Xml.resolvePullParser(stream); XmlUtils.beginDocument(parser, TAG_HISTORY); final int largestChainId = parser.getAttributeInt(null, ATTR_LARGEST_CHAIN_ID, 0); return largestChainId; } catch (Throwable t) { return 0; } finally { try { stream.close(); } catch (IOException e) { } } } else { return 0; } } private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) { private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) { synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff, long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff, Loading @@ -301,7 +350,7 @@ final class DiscreteRegistry { void clearHistory() { void clearHistory() { synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { mDiscreteOps = new DiscreteOps(); mDiscreteOps = new DiscreteOps(0); } } clearOnDiskHistoryLocked(); clearOnDiskHistoryLocked(); } } Loading Loading @@ -341,6 +390,10 @@ final class DiscreteRegistry { : new String[]{AppOpsManager.opToPublicName(dumpOp)}; : new String[]{AppOpsManager.opToPublicName(dumpOp)}; discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter, discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter, opNamesFilter, attributionTagFilter, OP_FLAGS_ALL); opNamesFilter, attributionTagFilter, OP_FLAGS_ALL); pw.print(prefix); pw.print("Largest chain id: "); pw.print(mDiscreteOps.mLargestChainId); pw.println(); discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps); discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps); } } Loading @@ -351,14 +404,14 @@ final class DiscreteRegistry { } } private DiscreteOps getAllDiscreteOps() { private DiscreteOps getAllDiscreteOps() { DiscreteOps discreteOps = new DiscreteOps(); DiscreteOps discreteOps = new DiscreteOps(0); synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { discreteOps.merge(mDiscreteOps); discreteOps.merge(mDiscreteOps); } } if (mCachedOps == null) { if (mCachedOps == null) { mCachedOps = new DiscreteOps(); mCachedOps = new DiscreteOps(0); readDiscreteOpsFromDisk(mCachedOps); readDiscreteOpsFromDisk(mCachedOps); } } discreteOps.merge(mCachedOps); discreteOps.merge(mCachedOps); Loading @@ -368,9 +421,13 @@ final class DiscreteRegistry { private final class DiscreteOps { private final class DiscreteOps { ArrayMap<Integer, DiscreteUidOps> mUids; ArrayMap<Integer, DiscreteUidOps> mUids; int mChainIdOffset; int mLargestChainId; DiscreteOps() { DiscreteOps(int chainIdOffset) { mUids = new ArrayMap<>(); mUids = new ArrayMap<>(); mChainIdOffset = chainIdOffset; mLargestChainId = chainIdOffset; } } boolean isEmpty() { boolean isEmpty() { Loading @@ -378,6 +435,7 @@ final class DiscreteRegistry { } } void merge(DiscreteOps other) { void merge(DiscreteOps other) { mLargestChainId = max(mLargestChainId, other.mLargestChainId); int nUids = other.mUids.size(); int nUids = other.mUids.size(); for (int i = 0; i < nUids; i++) { for (int i = 0; i < nUids; i++) { int uid = other.mUids.keyAt(i); int uid = other.mUids.keyAt(i); Loading @@ -390,6 +448,17 @@ final class DiscreteRegistry { @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { if (attributionChainId != ATTRIBUTION_CHAIN_ID_NONE) { attributionChainId += mChainIdOffset; if (attributionChainId < 0) { attributionChainId -= mChainIdOffset; mChainIdOffset = 0; mLargestChainId = attributionChainId; } if (attributionChainId > mLargestChainId) { mLargestChainId = attributionChainId; } } getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, uidState, accessTime, accessDuration, attributionFlags, attributionChainId); uidState, accessTime, accessDuration, attributionFlags, attributionChainId); } } Loading Loading @@ -442,6 +511,7 @@ final class DiscreteRegistry { out.startDocument(null, true); out.startDocument(null, true); out.startTag(null, TAG_HISTORY); out.startTag(null, TAG_HISTORY); out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION); out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION); out.attributeInt(null, ATTR_LARGEST_CHAIN_ID, mLargestChainId); int nUids = mUids.size(); int nUids = mUids.size(); for (int i = 0; i < nUids; i++) { for (int i = 0; i < nUids; i++) { Loading Loading @@ -476,8 +546,13 @@ final class DiscreteRegistry { } } private void readFromFile(File f, long beginTimeMillis) { private void readFromFile(File f, long beginTimeMillis) { FileInputStream stream; try { stream = new FileInputStream(f); } catch (FileNotFoundException e) { return; } try { try { FileInputStream stream = new FileInputStream(f); TypedXmlPullParser parser = Xml.resolvePullParser(stream); TypedXmlPullParser parser = Xml.resolvePullParser(stream); XmlUtils.beginDocument(parser, TAG_HISTORY); XmlUtils.beginDocument(parser, TAG_HISTORY); Loading @@ -487,7 +562,6 @@ final class DiscreteRegistry { if (version != CURRENT_VERSION) { if (version != CURRENT_VERSION) { throw new IllegalStateException("Dropping unsupported discrete history " + f); throw new IllegalStateException("Dropping unsupported discrete history " + f); } } int depth = parser.getDepth(); int depth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, depth)) { while (XmlUtils.nextElementWithin(parser, depth)) { if (TAG_UID.equals(parser.getName())) { if (TAG_UID.equals(parser.getName())) { Loading @@ -498,8 +572,12 @@ final class DiscreteRegistry { } catch (Throwable t) { } catch (Throwable t) { Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " " Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " " + Arrays.toString(t.getStackTrace())); + Arrays.toString(t.getStackTrace())); } finally { try { stream.close(); } catch (IOException e) { } } } } } } } Loading services/core/java/com/android/server/appop/HistoricalRegistry.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -209,6 +209,7 @@ final class HistoricalRegistry { mMode = other.mMode; mMode = other.mMode; mBaseSnapshotInterval = other.mBaseSnapshotInterval; mBaseSnapshotInterval = other.mBaseSnapshotInterval; mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier; mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier; mDiscreteRegistry = other.mDiscreteRegistry; } } void systemReady(@NonNull ContentResolver resolver) { void systemReady(@NonNull ContentResolver resolver) { Loading Loading
services/core/java/com/android/server/appop/DiscreteRegistry.java +95 −17 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.appop; package com.android.server.appop; import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE; import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; Loading Loading @@ -58,7 +59,9 @@ import com.android.internal.util.XmlUtils; import java.io.File; import java.io.File; import java.io.FileInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.Duration; Loading Loading @@ -138,6 +141,7 @@ final class DiscreteRegistry { private static final String TAG_HISTORY = "h"; private static final String TAG_HISTORY = "h"; private static final String ATTR_VERSION = "v"; private static final String ATTR_VERSION = "v"; private static final String ATTR_LARGEST_CHAIN_ID = "lc"; private static final int CURRENT_VERSION = 1; private static final int CURRENT_VERSION = 1; private static final String TAG_UID = "u"; private static final String TAG_UID = "u"; Loading Loading @@ -182,6 +186,16 @@ final class DiscreteRegistry { DiscreteRegistry(Object inMemoryLock) { DiscreteRegistry(Object inMemoryLock) { mInMemoryLock = inMemoryLock; mInMemoryLock = inMemoryLock; synchronized (mOnDiskLock) { mDiscreteAccessDir = new File( new File(Environment.getDataSystemDirectory(), "appops"), "discrete"); createDiscreteAccessDirLocked(); int largestChainId = readLargestChainIdFromDiskLocked(); synchronized (mInMemoryLock) { mDiscreteOps = new DiscreteOps(largestChainId); } } } } void systemReady() { void systemReady() { Loading @@ -190,15 +204,6 @@ final class DiscreteRegistry { setDiscreteHistoryParameters(p); setDiscreteHistoryParameters(p); }); }); setDiscreteHistoryParameters(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_PRIVACY)); setDiscreteHistoryParameters(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_PRIVACY)); synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { mDiscreteAccessDir = new File( new File(Environment.getDataSystemDirectory(), "appops"), "discrete"); createDiscreteAccessDirLocked(); mDiscreteOps = new DiscreteOps(); } } } } private void setDiscreteHistoryParameters(DeviceConfig.Properties p) { private void setDiscreteHistoryParameters(DeviceConfig.Properties p) { Loading Loading @@ -251,7 +256,7 @@ final class DiscreteRegistry { DiscreteOps discreteOps; DiscreteOps discreteOps; synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { discreteOps = mDiscreteOps; discreteOps = mDiscreteOps; mDiscreteOps = new DiscreteOps(); mDiscreteOps = new DiscreteOps(discreteOps.mChainIdOffset); mCachedOps = null; mCachedOps = null; } } deleteOldDiscreteHistoryFilesLocked(); deleteOldDiscreteHistoryFilesLocked(); Loading @@ -275,6 +280,50 @@ final class DiscreteRegistry { return; return; } } private int readLargestChainIdFromDiskLocked() { final File[] files = mDiscreteAccessDir.listFiles(); if (files != null && files.length > 0) { File latestFile = null; long latestFileTimestamp = 0; for (File f : files) { final String fileName = f.getName(); if (!fileName.endsWith(DISCRETE_HISTORY_FILE_SUFFIX)) { continue; } long timestamp = Long.valueOf(fileName.substring(0, fileName.length() - DISCRETE_HISTORY_FILE_SUFFIX.length())); if (latestFileTimestamp < timestamp) { latestFile = f; latestFileTimestamp = timestamp; } } if (latestFile == null) { return 0; } FileInputStream stream; try { stream = new FileInputStream(latestFile); } catch (FileNotFoundException e) { return 0; } try { TypedXmlPullParser parser = Xml.resolvePullParser(stream); XmlUtils.beginDocument(parser, TAG_HISTORY); final int largestChainId = parser.getAttributeInt(null, ATTR_LARGEST_CHAIN_ID, 0); return largestChainId; } catch (Throwable t) { return 0; } finally { try { stream.close(); } catch (IOException e) { } } } else { return 0; } } private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) { private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) { synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff, long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff, Loading @@ -301,7 +350,7 @@ final class DiscreteRegistry { void clearHistory() { void clearHistory() { synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { mDiscreteOps = new DiscreteOps(); mDiscreteOps = new DiscreteOps(0); } } clearOnDiskHistoryLocked(); clearOnDiskHistoryLocked(); } } Loading Loading @@ -341,6 +390,10 @@ final class DiscreteRegistry { : new String[]{AppOpsManager.opToPublicName(dumpOp)}; : new String[]{AppOpsManager.opToPublicName(dumpOp)}; discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter, discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter, opNamesFilter, attributionTagFilter, OP_FLAGS_ALL); opNamesFilter, attributionTagFilter, OP_FLAGS_ALL); pw.print(prefix); pw.print("Largest chain id: "); pw.print(mDiscreteOps.mLargestChainId); pw.println(); discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps); discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps); } } Loading @@ -351,14 +404,14 @@ final class DiscreteRegistry { } } private DiscreteOps getAllDiscreteOps() { private DiscreteOps getAllDiscreteOps() { DiscreteOps discreteOps = new DiscreteOps(); DiscreteOps discreteOps = new DiscreteOps(0); synchronized (mOnDiskLock) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { synchronized (mInMemoryLock) { discreteOps.merge(mDiscreteOps); discreteOps.merge(mDiscreteOps); } } if (mCachedOps == null) { if (mCachedOps == null) { mCachedOps = new DiscreteOps(); mCachedOps = new DiscreteOps(0); readDiscreteOpsFromDisk(mCachedOps); readDiscreteOpsFromDisk(mCachedOps); } } discreteOps.merge(mCachedOps); discreteOps.merge(mCachedOps); Loading @@ -368,9 +421,13 @@ final class DiscreteRegistry { private final class DiscreteOps { private final class DiscreteOps { ArrayMap<Integer, DiscreteUidOps> mUids; ArrayMap<Integer, DiscreteUidOps> mUids; int mChainIdOffset; int mLargestChainId; DiscreteOps() { DiscreteOps(int chainIdOffset) { mUids = new ArrayMap<>(); mUids = new ArrayMap<>(); mChainIdOffset = chainIdOffset; mLargestChainId = chainIdOffset; } } boolean isEmpty() { boolean isEmpty() { Loading @@ -378,6 +435,7 @@ final class DiscreteRegistry { } } void merge(DiscreteOps other) { void merge(DiscreteOps other) { mLargestChainId = max(mLargestChainId, other.mLargestChainId); int nUids = other.mUids.size(); int nUids = other.mUids.size(); for (int i = 0; i < nUids; i++) { for (int i = 0; i < nUids; i++) { int uid = other.mUids.keyAt(i); int uid = other.mUids.keyAt(i); Loading @@ -390,6 +448,17 @@ final class DiscreteRegistry { @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @Nullable String attributionTag, @AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.UidState int uidState, long accessTime, long accessDuration, @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) { if (attributionChainId != ATTRIBUTION_CHAIN_ID_NONE) { attributionChainId += mChainIdOffset; if (attributionChainId < 0) { attributionChainId -= mChainIdOffset; mChainIdOffset = 0; mLargestChainId = attributionChainId; } if (attributionChainId > mLargestChainId) { mLargestChainId = attributionChainId; } } getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags, uidState, accessTime, accessDuration, attributionFlags, attributionChainId); uidState, accessTime, accessDuration, attributionFlags, attributionChainId); } } Loading Loading @@ -442,6 +511,7 @@ final class DiscreteRegistry { out.startDocument(null, true); out.startDocument(null, true); out.startTag(null, TAG_HISTORY); out.startTag(null, TAG_HISTORY); out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION); out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION); out.attributeInt(null, ATTR_LARGEST_CHAIN_ID, mLargestChainId); int nUids = mUids.size(); int nUids = mUids.size(); for (int i = 0; i < nUids; i++) { for (int i = 0; i < nUids; i++) { Loading Loading @@ -476,8 +546,13 @@ final class DiscreteRegistry { } } private void readFromFile(File f, long beginTimeMillis) { private void readFromFile(File f, long beginTimeMillis) { FileInputStream stream; try { stream = new FileInputStream(f); } catch (FileNotFoundException e) { return; } try { try { FileInputStream stream = new FileInputStream(f); TypedXmlPullParser parser = Xml.resolvePullParser(stream); TypedXmlPullParser parser = Xml.resolvePullParser(stream); XmlUtils.beginDocument(parser, TAG_HISTORY); XmlUtils.beginDocument(parser, TAG_HISTORY); Loading @@ -487,7 +562,6 @@ final class DiscreteRegistry { if (version != CURRENT_VERSION) { if (version != CURRENT_VERSION) { throw new IllegalStateException("Dropping unsupported discrete history " + f); throw new IllegalStateException("Dropping unsupported discrete history " + f); } } int depth = parser.getDepth(); int depth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, depth)) { while (XmlUtils.nextElementWithin(parser, depth)) { if (TAG_UID.equals(parser.getName())) { if (TAG_UID.equals(parser.getName())) { Loading @@ -498,8 +572,12 @@ final class DiscreteRegistry { } catch (Throwable t) { } catch (Throwable t) { Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " " Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " " + Arrays.toString(t.getStackTrace())); + Arrays.toString(t.getStackTrace())); } finally { try { stream.close(); } catch (IOException e) { } } } } } } } Loading
services/core/java/com/android/server/appop/HistoricalRegistry.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -209,6 +209,7 @@ final class HistoricalRegistry { mMode = other.mMode; mMode = other.mMode; mBaseSnapshotInterval = other.mBaseSnapshotInterval; mBaseSnapshotInterval = other.mBaseSnapshotInterval; mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier; mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier; mDiscreteRegistry = other.mDiscreteRegistry; } } void systemReady(@NonNull ContentResolver resolver) { void systemReady(@NonNull ContentResolver resolver) { Loading