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

Commit b0c3147a authored by dimorinny's avatar dimorinny
Browse files

Add persistent uri permissions westworld reporting

Bug: 149370983
Test: Locally using statsd_testdrive and westworld IDE
Change-Id: Ia78c011bae7bdf5b8ff03a8e5638560b7ad3bad2
parent 34f56bf7
Loading
Loading
Loading
Loading
+42 −4
Original line number Original line Diff line number Diff line
@@ -104,7 +104,8 @@ import java.util.List;
import java.util.Objects;
import java.util.Objects;


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


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


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


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


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


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


@@ -1298,20 +1304,50 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
        return false;
        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() {
    private void writeGrantedUriPermissions() {
        if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");
        if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");


        final long startTime = SystemClock.uptimeMillis();
        final long startTime = SystemClock.uptimeMillis();


        int persistentUriPermissionsCount = 0;

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

                    if (perm.persistedModeFlags != 0) {
                final int permissionsForPackageSize = perms.size();
                        persist.add(perm.snapshot());
                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);
                mGrantFile.failWrite(fos);
            }
            }
        }
        }

        mMetricsHelper.reportPersistentUriFlushed(persistentUriPermissionsCount);
    }
    }


    final class H extends Handler {
    final class H extends Handler {
+101 −0
Original line number Original line 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();
    }
}