Loading services/core/java/com/android/server/uri/UriGrantsManagerService.java +42 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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(); } } Loading Loading @@ -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()); } } } Loading Loading @@ -1345,6 +1381,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { mGrantFile.failWrite(fos); } } mMetricsHelper.reportPersistentUriFlushed(persistentUriPermissionsCount); } final class H extends Handler { Loading services/core/java/com/android/server/uri/UriMetricsHelper.java 0 → 100644 +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(); } } Loading
services/core/java/com/android/server/uri/UriGrantsManagerService.java +42 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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(); } } Loading Loading @@ -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()); } } } Loading Loading @@ -1345,6 +1381,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { mGrantFile.failWrite(fos); } } mMetricsHelper.reportPersistentUriFlushed(persistentUriPermissionsCount); } final class H extends Handler { Loading
services/core/java/com/android/server/uri/UriMetricsHelper.java 0 → 100644 +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(); } }