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

Commit 1bf07d71 authored by Dmitrii Merkurev's avatar Dmitrii Merkurev Committed by Android (Google) Code Review
Browse files

Merge "Add persistent uri permissions westworld reporting"

parents 9dff8fca b0c3147a
Loading
Loading
Loading
Loading
+42 −4
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ import java.util.List;
import java.util.Objects;

/** Manages uri grants. */
public class UriGrantsManagerService extends IUriGrantsManager.Stub {
public class UriGrantsManagerService extends IUriGrantsManager.Stub implements
        UriMetricsHelper.PersistentUriGrantsProvider {
    private static final boolean DEBUG = false;
    private static final String TAG = "UriGrantsManagerService";
    // Maximum number of persisted Uri grants a package is allowed
@@ -115,6 +116,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
    private final H mH;
    ActivityManagerInternal mAmInternal;
    PackageManagerInternal mPmInternal;
    UriMetricsHelper mMetricsHelper;

    /** File storing persisted {@link #mGrantedUriPermissions}. */
    private final AtomicFile mGrantFile;
@@ -168,16 +170,19 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
    }

    public static final class Lifecycle extends SystemService {
        private final Context mContext;
        private final UriGrantsManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mContext = context;
            mService = new UriGrantsManagerService();
        }

        @Override
        public void onStart() {
            publishBinderService(Context.URI_GRANTS_SERVICE, mService);
            mService.mMetricsHelper = new UriMetricsHelper(mContext, mService);
            mService.start();
        }

@@ -186,6 +191,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
            if (phase == PHASE_SYSTEM_SERVICES_READY) {
                mService.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
                mService.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
                mService.mMetricsHelper.registerPuller();
            }
        }

@@ -1298,20 +1304,50 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
        return false;
    }

    @Override
    public ArrayList<UriPermission> providePersistentUriGrants() {
        final ArrayList<UriPermission> result = new ArrayList<>();

        synchronized (mLock) {
            final int size = mGrantedUriPermissions.size();
            for (int i = 0; i < size; i++) {
                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);

                final int permissionsForPackageSize = perms.size();
                for (int j = 0; j < permissionsForPackageSize; j++) {
                    final UriPermission permission = perms.valueAt(j);

                    if (permission.persistedModeFlags != 0) {
                        result.add(permission);
                    }
                }
            }
        }

        return result;
    }

    private void writeGrantedUriPermissions() {
        if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");

        final long startTime = SystemClock.uptimeMillis();

        int persistentUriPermissionsCount = 0;

        // Snapshot permissions so we can persist without lock
        ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
        synchronized (mLock) {
            final int size = mGrantedUriPermissions.size();
            for (int i = 0; i < size; i++) {
                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
                for (UriPermission perm : perms.values()) {
                    if (perm.persistedModeFlags != 0) {
                        persist.add(perm.snapshot());

                final int permissionsForPackageSize = perms.size();
                for (int j = 0; j < permissionsForPackageSize; j++) {
                    final UriPermission permission = perms.valueAt(j);

                    if (permission.persistedModeFlags != 0) {
                        persistentUriPermissionsCount++;
                        persist.add(permission.snapshot());
                    }
                }
            }
@@ -1345,6 +1381,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
                mGrantFile.failWrite(fos);
            }
        }

        mMetricsHelper.reportPersistentUriFlushed(persistentUriPermissionsCount);
    }

    final class H extends Handler {
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.uri;

import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;

import android.app.StatsManager;
import android.content.Context;
import android.util.SparseArray;
import android.util.StatsEvent;

import com.android.internal.util.FrameworkStatsLog;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

final class UriMetricsHelper {

    private static final StatsManager.PullAtomMetadata DAILY_PULL_METADATA =
            new StatsManager.PullAtomMetadata.Builder()
                    .setCoolDownMillis(TimeUnit.DAYS.toMillis(1))
                    .build();


    private final Context mContext;
    private final PersistentUriGrantsProvider mPersistentUriGrantsProvider;

    UriMetricsHelper(Context context, PersistentUriGrantsProvider provider) {
        mContext = context;
        mPersistentUriGrantsProvider = provider;
    }

    void registerPuller() {
        final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
        statsManager.setPullAtomCallback(
                FrameworkStatsLog.PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE,
                DAILY_PULL_METADATA,
                DIRECT_EXECUTOR,
                (atomTag, data) -> {
                    reportPersistentUriPermissionsPerPackage(data);
                    return StatsManager.PULL_SUCCESS;
                });
    }

    void reportPersistentUriFlushed(int amount) {
        FrameworkStatsLog.write(
                FrameworkStatsLog.PERSISTENT_URI_PERMISSIONS_FLUSHED,
                amount
        );
    }

    private void reportPersistentUriPermissionsPerPackage(List<StatsEvent> data) {
        final ArrayList<UriPermission> persistentUriGrants =
                mPersistentUriGrantsProvider.providePersistentUriGrants();

        final SparseArray<Integer> perUidCount = new SparseArray<>();

        final int persistentUriGrantsSize = persistentUriGrants.size();
        for (int i = 0; i < persistentUriGrantsSize; i++) {
            final UriPermission uriPermission = persistentUriGrants.get(i);

            perUidCount.put(
                    uriPermission.targetUid,
                    perUidCount.get(uriPermission.targetUid, 0) + 1
            );
        }

        final int perUidCountSize = perUidCount.size();
        for (int i = 0; i < perUidCountSize; i++) {
            final int uid = perUidCount.keyAt(i);
            final int amount = perUidCount.valueAt(i);

            data.add(
                    FrameworkStatsLog.buildStatsEvent(
                            FrameworkStatsLog.PERSISTENT_URI_PERMISSIONS_AMOUNT_PER_PACKAGE,
                            uid,
                            amount
                    )
            );
        }
    }

    interface PersistentUriGrantsProvider {
        ArrayList<UriPermission> providePersistentUriGrants();
    }
}