Loading services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java +77 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.pm.permission; import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerInternal; Loading @@ -23,6 +25,8 @@ import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IUidObserver; import android.app.UidObserver; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading @@ -30,14 +34,24 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; import android.os.SystemClock; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.PermissionThread; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Class that handles one-time permissions for a user Loading @@ -56,6 +70,8 @@ public class OneTimePermissionUserManager { private final @NonNull ActivityManagerInternal mActivityManagerInternal; private final @NonNull AlarmManager mAlarmManager; private final @NonNull PermissionControllerManager mPermissionControllerManager; private final @NonNull PermissionManager mPermissionManager; private final VirtualDeviceManagerInternal mVirtualDeviceManagerInternal; private final Object mLock = new Object(); Loading @@ -72,6 +88,7 @@ public class OneTimePermissionUserManager { } listener.cancel(); mListeners.remove(uid); mHandler.post(() -> logOneTimeSessionEvent(listener)); } } } Loading @@ -90,6 +107,9 @@ public class OneTimePermissionUserManager { mAlarmManager = context.getSystemService(AlarmManager.class); mPermissionControllerManager = new PermissionControllerManager( mContext, PermissionThread.getHandler()); mPermissionManager = mContext.getSystemService(PermissionManager.class); mVirtualDeviceManagerInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); mHandler = context.getMainThreadHandler(); } Loading Loading @@ -136,8 +156,10 @@ public class OneTimePermissionUserManager { if (listener != null) { mListeners.remove(uid); listener.cancel(); mHandler.post(() -> logOneTimeSessionEvent(listener)); } } } /** Loading @@ -148,6 +170,19 @@ public class OneTimePermissionUserManager { mContext.registerReceiver(mUninstallListener, new IntentFilter(Intent.ACTION_UID_REMOVED)); } /** * Log the session duration when the session is finished. * * @param listener listener for which the one time session is finished/expired. */ private void logOneTimeSessionEvent(@NonNull PackageInactivityListener listener) { if (Flags.permissionOneTimeSessionLoggingEnabled()) { long durationMillis = SystemClock.elapsedRealtime() - listener.mSessionStartMillis; FrameworkStatsLog.write(FrameworkStatsLog.PERMISSION_ONE_TIME_SESSION_EVENT_REPORTED, listener.mUid, listener.mPermissions.toArray(new String[0]), durationMillis); } } /** * A class which watches a package for inactivity and notifies the permission controller when * the package becomes inactive Loading @@ -173,6 +208,11 @@ public class OneTimePermissionUserManager { private final Object mInnerLock = new Object(); private final Object mToken = new Object(); // timestamp to track when the one time session starts. private final long mSessionStartMillis = SystemClock.elapsedRealtime(); // Permissions for which the session is started, used in logging private final ArraySet<String> mPermissions = new ArraySet<>(); private final IUidObserver mObserver = new UidObserver() { @Override public void onUidGone(int uid, boolean disabled) { Loading Loading @@ -211,6 +251,10 @@ public class OneTimePermissionUserManager { DEFAULT_KILLED_DELAY_MILLIS) : revokeAfterkilledDelay; if (Flags.permissionOneTimeSessionLoggingEnabled()) { mPermissions.addAll(getOneTimePermissions(packageName, deviceId)); } try { mIActivityManager.registerUidObserver(mObserver, ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE, Loading @@ -227,6 +271,33 @@ public class OneTimePermissionUserManager { updateUidState(); } private @NonNull List<String> getOneTimePermissions(@NonNull String packageName, int deviceId) { List<String> permissions = new ArrayList<>(); Map<String, PermissionManager.PermissionState> permissionStates = mPermissionManager.getAllPermissionStates(packageName, getPersistentDeviceId(deviceId)); for (Map.Entry<String, PermissionManager.PermissionState> entry : permissionStates.entrySet()) { PermissionManager.PermissionState permissionState = entry.getValue(); if (permissionState.isGranted() && (permissionState.getFlags() & FLAG_PERMISSION_ONE_TIME) != 0) { permissions.add(entry.getKey()); } } return permissions; } private @NonNull String getPersistentDeviceId(int deviceId) { VirtualDevice virtualDevice = mVirtualDeviceManagerInternal.getVirtualDevice(deviceId); String persistentDeviceId = null; if (virtualDevice != null) { persistentDeviceId = virtualDevice.getPersistentDeviceId(); } return persistentDeviceId != null ? persistentDeviceId : VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT; } public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis) { synchronized (mInnerLock) { mTimeout = Math.min(mTimeout, timeoutMillis); Loading @@ -242,6 +313,9 @@ public class OneTimePermissionUserManager { + " killedDelay=" + mRevokeAfterKilledDelay); updateUidState(); } if (Flags.permissionOneTimeSessionLoggingEnabled()) { mPermissions.addAll(getOneTimePermissions(mPackageName, mDeviceId)); } } private int getCurrentState() { Loading Loading @@ -394,6 +468,7 @@ public class OneTimePermissionUserManager { synchronized (mLock) { mListeners.remove(mUid); } mHandler.post(() -> logOneTimeSessionEvent(this)); } @Override Loading Loading
services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java +77 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.pm.permission; import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerInternal; Loading @@ -23,6 +25,8 @@ import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IUidObserver; import android.app.UidObserver; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading @@ -30,14 +34,24 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; import android.os.SystemClock; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.permission.flags.Flags; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.PermissionThread; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Class that handles one-time permissions for a user Loading @@ -56,6 +70,8 @@ public class OneTimePermissionUserManager { private final @NonNull ActivityManagerInternal mActivityManagerInternal; private final @NonNull AlarmManager mAlarmManager; private final @NonNull PermissionControllerManager mPermissionControllerManager; private final @NonNull PermissionManager mPermissionManager; private final VirtualDeviceManagerInternal mVirtualDeviceManagerInternal; private final Object mLock = new Object(); Loading @@ -72,6 +88,7 @@ public class OneTimePermissionUserManager { } listener.cancel(); mListeners.remove(uid); mHandler.post(() -> logOneTimeSessionEvent(listener)); } } } Loading @@ -90,6 +107,9 @@ public class OneTimePermissionUserManager { mAlarmManager = context.getSystemService(AlarmManager.class); mPermissionControllerManager = new PermissionControllerManager( mContext, PermissionThread.getHandler()); mPermissionManager = mContext.getSystemService(PermissionManager.class); mVirtualDeviceManagerInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); mHandler = context.getMainThreadHandler(); } Loading Loading @@ -136,8 +156,10 @@ public class OneTimePermissionUserManager { if (listener != null) { mListeners.remove(uid); listener.cancel(); mHandler.post(() -> logOneTimeSessionEvent(listener)); } } } /** Loading @@ -148,6 +170,19 @@ public class OneTimePermissionUserManager { mContext.registerReceiver(mUninstallListener, new IntentFilter(Intent.ACTION_UID_REMOVED)); } /** * Log the session duration when the session is finished. * * @param listener listener for which the one time session is finished/expired. */ private void logOneTimeSessionEvent(@NonNull PackageInactivityListener listener) { if (Flags.permissionOneTimeSessionLoggingEnabled()) { long durationMillis = SystemClock.elapsedRealtime() - listener.mSessionStartMillis; FrameworkStatsLog.write(FrameworkStatsLog.PERMISSION_ONE_TIME_SESSION_EVENT_REPORTED, listener.mUid, listener.mPermissions.toArray(new String[0]), durationMillis); } } /** * A class which watches a package for inactivity and notifies the permission controller when * the package becomes inactive Loading @@ -173,6 +208,11 @@ public class OneTimePermissionUserManager { private final Object mInnerLock = new Object(); private final Object mToken = new Object(); // timestamp to track when the one time session starts. private final long mSessionStartMillis = SystemClock.elapsedRealtime(); // Permissions for which the session is started, used in logging private final ArraySet<String> mPermissions = new ArraySet<>(); private final IUidObserver mObserver = new UidObserver() { @Override public void onUidGone(int uid, boolean disabled) { Loading Loading @@ -211,6 +251,10 @@ public class OneTimePermissionUserManager { DEFAULT_KILLED_DELAY_MILLIS) : revokeAfterkilledDelay; if (Flags.permissionOneTimeSessionLoggingEnabled()) { mPermissions.addAll(getOneTimePermissions(packageName, deviceId)); } try { mIActivityManager.registerUidObserver(mObserver, ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE, Loading @@ -227,6 +271,33 @@ public class OneTimePermissionUserManager { updateUidState(); } private @NonNull List<String> getOneTimePermissions(@NonNull String packageName, int deviceId) { List<String> permissions = new ArrayList<>(); Map<String, PermissionManager.PermissionState> permissionStates = mPermissionManager.getAllPermissionStates(packageName, getPersistentDeviceId(deviceId)); for (Map.Entry<String, PermissionManager.PermissionState> entry : permissionStates.entrySet()) { PermissionManager.PermissionState permissionState = entry.getValue(); if (permissionState.isGranted() && (permissionState.getFlags() & FLAG_PERMISSION_ONE_TIME) != 0) { permissions.add(entry.getKey()); } } return permissions; } private @NonNull String getPersistentDeviceId(int deviceId) { VirtualDevice virtualDevice = mVirtualDeviceManagerInternal.getVirtualDevice(deviceId); String persistentDeviceId = null; if (virtualDevice != null) { persistentDeviceId = virtualDevice.getPersistentDeviceId(); } return persistentDeviceId != null ? persistentDeviceId : VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT; } public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis) { synchronized (mInnerLock) { mTimeout = Math.min(mTimeout, timeoutMillis); Loading @@ -242,6 +313,9 @@ public class OneTimePermissionUserManager { + " killedDelay=" + mRevokeAfterKilledDelay); updateUidState(); } if (Flags.permissionOneTimeSessionLoggingEnabled()) { mPermissions.addAll(getOneTimePermissions(mPackageName, mDeviceId)); } } private int getCurrentState() { Loading Loading @@ -394,6 +468,7 @@ public class OneTimePermissionUserManager { synchronized (mLock) { mListeners.remove(mUid); } mHandler.post(() -> logOneTimeSessionEvent(this)); } @Override Loading