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

Commit 3450ece8 authored by Nate Myren's avatar Nate Myren Committed by Automerger Merge Worker
Browse files

Merge "Keep track of and persist largest AttributionChainId." into sc-dev am: c1f345fe

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15028971

Change-Id: Icceae4b7c839f28bd9c9d0eb8e37c5a33145718b
parents 91480647 c1f345fe
Loading
Loading
Loading
Loading
+95 −17
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

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_OP_NAMES;
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
@@ -58,7 +59,9 @@ import com.android.internal.util.XmlUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.time.Duration;
@@ -138,6 +141,7 @@ final class DiscreteRegistry {

    private static final String TAG_HISTORY = "h";
    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 String TAG_UID = "u";
@@ -182,6 +186,16 @@ final class DiscreteRegistry {

    DiscreteRegistry(Object 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() {
@@ -190,15 +204,6 @@ final class DiscreteRegistry {
                    setDiscreteHistoryParameters(p);
                });
        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) {
@@ -251,7 +256,7 @@ final class DiscreteRegistry {
            DiscreteOps discreteOps;
            synchronized (mInMemoryLock) {
                discreteOps = mDiscreteOps;
                mDiscreteOps = new DiscreteOps();
                mDiscreteOps = new DiscreteOps(discreteOps.mChainIdOffset);
                mCachedOps = null;
            }
            deleteOldDiscreteHistoryFilesLocked();
@@ -275,6 +280,50 @@ final class DiscreteRegistry {
        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) {
        synchronized (mOnDiskLock) {
            long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff,
@@ -301,7 +350,7 @@ final class DiscreteRegistry {
    void clearHistory() {
        synchronized (mOnDiskLock) {
            synchronized (mInMemoryLock) {
                mDiscreteOps = new DiscreteOps();
                mDiscreteOps = new DiscreteOps(0);
            }
            clearOnDiskHistoryLocked();
        }
@@ -341,6 +390,10 @@ final class DiscreteRegistry {
                : new String[]{AppOpsManager.opToPublicName(dumpOp)};
        discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter,
                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);
    }

@@ -351,14 +404,14 @@ final class DiscreteRegistry {
    }

    private DiscreteOps getAllDiscreteOps() {
        DiscreteOps discreteOps = new DiscreteOps();
        DiscreteOps discreteOps = new DiscreteOps(0);

        synchronized (mOnDiskLock) {
            synchronized (mInMemoryLock) {
                discreteOps.merge(mDiscreteOps);
            }
            if (mCachedOps == null) {
                mCachedOps = new DiscreteOps();
                mCachedOps = new DiscreteOps(0);
                readDiscreteOpsFromDisk(mCachedOps);
            }
            discreteOps.merge(mCachedOps);
@@ -368,9 +421,13 @@ final class DiscreteRegistry {

    private final class DiscreteOps {
        ArrayMap<Integer, DiscreteUidOps> mUids;
        int mChainIdOffset;
        int mLargestChainId;

        DiscreteOps() {
        DiscreteOps(int chainIdOffset) {
            mUids = new ArrayMap<>();
            mChainIdOffset = chainIdOffset;
            mLargestChainId = chainIdOffset;
        }

        boolean isEmpty() {
@@ -378,6 +435,7 @@ final class DiscreteRegistry {
        }

        void merge(DiscreteOps other) {
            mLargestChainId = max(mLargestChainId, other.mLargestChainId);
            int nUids = other.mUids.size();
            for (int i = 0; i < nUids; i++) {
                int uid = other.mUids.keyAt(i);
@@ -390,6 +448,17 @@ final class DiscreteRegistry {
                @Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
                @AppOpsManager.UidState int uidState, long accessTime, long accessDuration,
                @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,
                    uidState, accessTime, accessDuration, attributionFlags, attributionChainId);
        }
@@ -442,6 +511,7 @@ final class DiscreteRegistry {
            out.startDocument(null, true);
            out.startTag(null, TAG_HISTORY);
            out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION);
            out.attributeInt(null, ATTR_LARGEST_CHAIN_ID, mLargestChainId);

            int nUids = mUids.size();
            for (int i = 0; i < nUids; i++) {
@@ -476,8 +546,13 @@ final class DiscreteRegistry {
        }

        private void readFromFile(File f, long beginTimeMillis) {
            FileInputStream stream;
            try {
                stream = new FileInputStream(f);
            } catch (FileNotFoundException e) {
                return;
            }
            try {
                FileInputStream stream = new FileInputStream(f);
                TypedXmlPullParser parser = Xml.resolvePullParser(stream);
                XmlUtils.beginDocument(parser, TAG_HISTORY);

@@ -487,7 +562,6 @@ final class DiscreteRegistry {
                if (version != CURRENT_VERSION) {
                    throw new IllegalStateException("Dropping unsupported discrete history " + f);
                }

                int depth = parser.getDepth();
                while (XmlUtils.nextElementWithin(parser, depth)) {
                    if (TAG_UID.equals(parser.getName())) {
@@ -498,8 +572,12 @@ final class DiscreteRegistry {
            } catch (Throwable t) {
                Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " "
                        + Arrays.toString(t.getStackTrace()));
            } finally {
                try {
                    stream.close();
                } catch (IOException e) {
                }
            }

        }
    }

+1 −0
Original line number Diff line number Diff line
@@ -209,6 +209,7 @@ final class HistoricalRegistry {
        mMode = other.mMode;
        mBaseSnapshotInterval = other.mBaseSnapshotInterval;
        mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier;
        mDiscreteRegistry = other.mDiscreteRegistry;
    }

    void systemReady(@NonNull ContentResolver resolver) {