Loading src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java +28 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,12 @@ package com.android.permissioncontroller.permission.ui.handheld; import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID; import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_DO_NOT_ASK_AGAIN; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_ALWAYS; Loading Loading @@ -272,29 +278,36 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { } mAllowButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW); setResult(GRANTED_ALWAYS); }); mAllowAlwaysButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS); setResult(GRANTED_ALWAYS); }); mAllowForegroundButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BACKGROUND); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BACKGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND); setResult(GRANTED_FOREGROUND_ONLY); }); // mAskOneTimeButton only shows if checked hence should do nothing mAskButton.setOnClickListener((v) -> { mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME); setResult(DENIED); }); mDenyButton.setOnClickListener((v) -> { mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY); setResult(DENIED_DO_NOT_ASK_AGAIN); }); mDenyForegroundButton.setOnClickListener((v) -> { mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND); setResult(DENIED_DO_NOT_ASK_AGAIN); }); Loading Loading @@ -393,13 +406,16 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { * @param changeTarget Whether background or foreground should be changed * @param messageId The Id of the string message to show * @param userFixed Whether the permission state should be user fixed * @param buttonPressed Button which was pressed to initiate the dialog, one of * AppPermissionFragmentActionReported.button_pressed constants */ void showDefaultDenyDialog(ChangeTarget changeTarget, @StringRes int messageId, boolean userFixed) { boolean userFixed, int buttonPressed) { Bundle args = getArguments().deepCopy(); args.putInt(DefaultDenyDialog.MSG, messageId); args.putSerializable(DefaultDenyDialog.CHANGE_TARGET, changeTarget); args.putBoolean(DefaultDenyDialog.USER_FIXED, userFixed); args.putInt(DefaultDenyDialog.BUTTON, buttonPressed); DefaultDenyDialog defaultDenyDialog = new DefaultDenyDialog(); defaultDenyDialog.setCancelable(true); defaultDenyDialog.setArguments(args); Loading @@ -411,13 +427,14 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { * A dialog warning the user that they are about to deny a permission that was granted by * default, or that they are denying a permission on a Pre-M app * * @see #showDefaultDenyDialog(ChangeTarget, int, boolean) * @see #showDefaultDenyDialog(ChangeTarget, int, boolean, int) */ public static class DefaultDenyDialog extends DialogFragment { static final String MSG = DefaultDenyDialog.class.getName() + ".arg.msg"; static final String CHANGE_TARGET = DefaultDenyDialog.class.getName() + ".arg.changeTarget"; private static final String KEY = DefaultDenyDialog.class.getName() + ".arg.key"; private static final String BUTTON = DefaultDenyDialog.class.getName() + ".arg.button"; static final String USER_FIXED = DefaultDenyDialog.class.getName() + ".arg.userFixed"; Loading @@ -432,7 +449,8 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { (DialogInterface dialog, int which) -> fragment.mViewModel.onDenyAnyWay((ChangeTarget) getArguments().getSerializable(CHANGE_TARGET), getArguments().getBoolean(USER_FIXED, false))); getArguments().getBoolean(USER_FIXED, false), getArguments().getInt(BUTTON))); Dialog d = b.create(); d.setCanceledOnTouchOutside(true); return d; Loading src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionViewModel.kt +44 −48 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveDat import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData import com.android.permissioncontroller.permission.data.get import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.LocationUtils import com.android.permissioncontroller.permission.utils.SafetyNetLogger Loading @@ -50,8 +51,6 @@ import com.android.permissioncontroller.permission.ui.handheld.AppPermissionView import com.android.permissioncontroller.permission.utils.Utils import com.android.settingslib.RestrictedLockUtils import java.util.Random import kotlin.collections.ArrayList import kotlin.collections.List import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.filter Loading Loading @@ -345,6 +344,8 @@ class AppPermissionViewModel( * * @param requestGrant If this group should be granted * @param changeTarget Which permission group (foreground/background/both) should be changed * @param buttonClicked button which was pressed to initiate the change, one of * AppPermissionFragmentActionReported.button_pressed constants * * @return The dialogue to show, if applicable, or if the request was processed. */ Loading @@ -352,7 +353,8 @@ class AppPermissionViewModel( requestGrant: Boolean, userFixed: Boolean, fragment: AppPermissionFragment, changeTarget: ChangeTarget changeTarget: ChangeTarget, buttonClicked: Int ) { val context = fragment.context ?: return val group = lightAppPermGroup ?: return Loading @@ -368,22 +370,23 @@ class AppPermissionViewModel( val shouldChangeBackground = changeTarget andValue ChangeTarget.CHANGE_BACKGROUND != 0 if (requestGrant) { val stateBefore = createPermissionSnapshot()!! var newGroup = group val oldGroup = group if (shouldChangeForeground) { val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group) newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, newGroup) if (!wasForegroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) } } if (shouldChangeBackground && group.hasBackgroundGroup) { val newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, group) newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup) if (!wasBackgroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup, true) } } logPermissionChanges(stateBefore) logPermissionChanges(oldGroup, newGroup, buttonClicked) } else { var showDefaultDenyDialog = false var showGrantedByDefaultWarning = false Loading @@ -406,17 +409,19 @@ class AppPermissionViewModel( } if (showDefaultDenyDialog && !hasConfirmedRevoke && showGrantedByDefaultWarning) { fragment.showDefaultDenyDialog(changeTarget, R.string.system_warning, userFixed) fragment.showDefaultDenyDialog(changeTarget, R.string.system_warning, userFixed, buttonClicked) return } else if (showDefaultDenyDialog && !hasConfirmedRevoke) { fragment.showDefaultDenyDialog(changeTarget, R.string.old_sdk_deny_warning, userFixed) userFixed, buttonClicked) return } else { val stateBefore = createPermissionSnapshot()!! var newGroup = group val oldGroup = group if (shouldChangeForeground && (wasForegroundGranted || userFixed != group.isUserFixed)) { val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, userFixed) // only log if we have actually denied permissions, not if we switch from Loading @@ -427,8 +432,8 @@ class AppPermissionViewModel( } if (shouldChangeBackground && group.hasBackgroundGroup && (wasBackgroundGranted || userFixed != group.isUserFixed)) { val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup, userFixed) // only log if we have actually denied permissions, not if we switch from // "ask every time" to denied Loading @@ -436,7 +441,7 @@ class AppPermissionViewModel( SafetyNetLogger.logPermissionToggled(newGroup, true) } } logPermissionChanges(stateBefore) logPermissionChanges(oldGroup, newGroup, buttonClicked) } } } Loading @@ -448,24 +453,27 @@ class AppPermissionViewModel( * @param changeTarget whether to change foreground, background, or both. * @param userFixed whether the user has stated they do not wish to be prompted about the * permission any more. * @param buttonPressed button pressed to initiate the change, one of * AppPermissionFragmentActionReported.button_pressed constants * */ fun onDenyAnyWay(changeTarget: ChangeTarget, userFixed: Boolean) { fun onDenyAnyWay(changeTarget: ChangeTarget, userFixed: Boolean, buttonPressed: Int) { val group = lightAppPermGroup ?: return val wasForegroundGranted = group.foreground.isGranted val wasBackgroundGranted = group.background.isGranted var hasDefaultPermissions = false val stateBefore = createPermissionSnapshot() var newGroup = group val oldGroup = group if (changeTarget andValue ChangeTarget.CHANGE_FOREGROUND != 0) { val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, userFixed) if (wasForegroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) } hasDefaultPermissions = group.foreground.isGrantedByDefault } if (changeTarget andValue ChangeTarget.CHANGE_BACKGROUND != 0 && group.hasBackgroundGroup) { val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup, userFixed) if (wasBackgroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) Loading @@ -473,24 +481,13 @@ class AppPermissionViewModel( hasDefaultPermissions = hasDefaultPermissions || group.background.isGrantedByDefault } logPermissionChanges(stateBefore!!) logPermissionChanges(oldGroup, newGroup, buttonPressed) if (hasDefaultPermissions || !group.supportsRuntimePerms) { hasConfirmedRevoke = true } } private fun createPermissionSnapshot(): List<PermissionState>? { val group = lightAppPermGroup ?: return null val permissionSnapshot = ArrayList<PermissionState>() for ((permName, permission) in group.permissions) { permissionSnapshot.add(PermissionState(permName, permission.isGrantedIncludingAppOp)) } return permissionSnapshot } /** * Show the All App Permissions screen with the proper filter group, package name, and user. * Loading Loading @@ -562,37 +559,36 @@ class AppPermissionViewModel( return 0 } data class PermissionState(val permissionName: String, val permissionGranted: Boolean) private fun logPermissionChanges(previousPermissionSnapshot: List<PermissionState>) { val lightGroup = lightAppPermGroup ?: return private fun logPermissionChanges( oldGroup: LightAppPermGroup, newGroup: LightAppPermGroup, buttonPressed: Int ) { val changeId = Random().nextLong() for ((permissionName, wasGranted) in previousPermissionSnapshot) { val permission = lightGroup.permissions[permissionName] ?: continue val isGranted = permission.isGrantedIncludingAppOp for ((permName, permission) in oldGroup.permissions) { val newPermission = newGroup.permissions[permName] ?: continue if (wasGranted != isGranted) { logAppPermissionFragmentActionReported(changeId, permissionName, isGranted) if (permission.isGrantedIncludingAppOp != newPermission.isGrantedIncludingAppOp || permission.flags != newPermission.flags) { logAppPermissionFragmentActionReported(changeId, newPermission, buttonPressed) } } } private fun logAppPermissionFragmentActionReported( changeId: Long, permissionName: String, isGranted: Boolean permission: LightPermission, buttonPressed: Int ) { val uid = KotlinUtils.getPackageUid(app, packageName, user) ?: return PermissionControllerStatsLog.write(APP_PERMISSION_FRAGMENT_ACTION_REPORTED, sessionId, changeId, uid, packageName, permissionName, isGranted) changeId, uid, packageName, permission.permInfo.name, permission.isGrantedIncludingAppOp, permission.flags, buttonPressed) Log.v(LOG_TAG, "Permission changed via UI with sessionId=$sessionId changeId=" + "$changeId uid=$uid packageName=" + "$packageName permission=$permissionName isGranted=$isGranted") "$changeId uid=$uid packageName=$packageName permission=" + permission.permInfo.name + " isGranted=" + permission.isGrantedIncludingAppOp + " permissionFlags=" + permission.flags + " buttonPressed=$buttonPressed") } /** Loading Loading
src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java +28 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,12 @@ package com.android.permissioncontroller.permission.ui.handheld; import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID; import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY; import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_DO_NOT_ASK_AGAIN; import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_ALWAYS; Loading Loading @@ -272,29 +278,36 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { } mAllowButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW); setResult(GRANTED_ALWAYS); }); mAllowAlwaysButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS); setResult(GRANTED_ALWAYS); }); mAllowForegroundButton.setOnClickListener((v) -> { mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BACKGROUND); mViewModel.requestChange(true, false, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BACKGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND); setResult(GRANTED_FOREGROUND_ONLY); }); // mAskOneTimeButton only shows if checked hence should do nothing mAskButton.setOnClickListener((v) -> { mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(false, false, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME); setResult(DENIED); }); mDenyButton.setOnClickListener((v) -> { mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_BOTH); mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY); setResult(DENIED_DO_NOT_ASK_AGAIN); }); mDenyForegroundButton.setOnClickListener((v) -> { mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_FOREGROUND); mViewModel.requestChange(false, true, this, ChangeTarget.CHANGE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND); setResult(DENIED_DO_NOT_ASK_AGAIN); }); Loading Loading @@ -393,13 +406,16 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { * @param changeTarget Whether background or foreground should be changed * @param messageId The Id of the string message to show * @param userFixed Whether the permission state should be user fixed * @param buttonPressed Button which was pressed to initiate the dialog, one of * AppPermissionFragmentActionReported.button_pressed constants */ void showDefaultDenyDialog(ChangeTarget changeTarget, @StringRes int messageId, boolean userFixed) { boolean userFixed, int buttonPressed) { Bundle args = getArguments().deepCopy(); args.putInt(DefaultDenyDialog.MSG, messageId); args.putSerializable(DefaultDenyDialog.CHANGE_TARGET, changeTarget); args.putBoolean(DefaultDenyDialog.USER_FIXED, userFixed); args.putInt(DefaultDenyDialog.BUTTON, buttonPressed); DefaultDenyDialog defaultDenyDialog = new DefaultDenyDialog(); defaultDenyDialog.setCancelable(true); defaultDenyDialog.setArguments(args); Loading @@ -411,13 +427,14 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { * A dialog warning the user that they are about to deny a permission that was granted by * default, or that they are denying a permission on a Pre-M app * * @see #showDefaultDenyDialog(ChangeTarget, int, boolean) * @see #showDefaultDenyDialog(ChangeTarget, int, boolean, int) */ public static class DefaultDenyDialog extends DialogFragment { static final String MSG = DefaultDenyDialog.class.getName() + ".arg.msg"; static final String CHANGE_TARGET = DefaultDenyDialog.class.getName() + ".arg.changeTarget"; private static final String KEY = DefaultDenyDialog.class.getName() + ".arg.key"; private static final String BUTTON = DefaultDenyDialog.class.getName() + ".arg.button"; static final String USER_FIXED = DefaultDenyDialog.class.getName() + ".arg.userFixed"; Loading @@ -432,7 +449,8 @@ public class AppPermissionFragment extends SettingsWithLargeHeader { (DialogInterface dialog, int which) -> fragment.mViewModel.onDenyAnyWay((ChangeTarget) getArguments().getSerializable(CHANGE_TARGET), getArguments().getBoolean(USER_FIXED, false))); getArguments().getBoolean(USER_FIXED, false), getArguments().getInt(BUTTON))); Dialog d = b.create(); d.setCanceledOnTouchOutside(true); return d; Loading
src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionViewModel.kt +44 −48 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveDat import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData import com.android.permissioncontroller.permission.data.get import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.LocationUtils import com.android.permissioncontroller.permission.utils.SafetyNetLogger Loading @@ -50,8 +51,6 @@ import com.android.permissioncontroller.permission.ui.handheld.AppPermissionView import com.android.permissioncontroller.permission.utils.Utils import com.android.settingslib.RestrictedLockUtils import java.util.Random import kotlin.collections.ArrayList import kotlin.collections.List import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.filter Loading Loading @@ -345,6 +344,8 @@ class AppPermissionViewModel( * * @param requestGrant If this group should be granted * @param changeTarget Which permission group (foreground/background/both) should be changed * @param buttonClicked button which was pressed to initiate the change, one of * AppPermissionFragmentActionReported.button_pressed constants * * @return The dialogue to show, if applicable, or if the request was processed. */ Loading @@ -352,7 +353,8 @@ class AppPermissionViewModel( requestGrant: Boolean, userFixed: Boolean, fragment: AppPermissionFragment, changeTarget: ChangeTarget changeTarget: ChangeTarget, buttonClicked: Int ) { val context = fragment.context ?: return val group = lightAppPermGroup ?: return Loading @@ -368,22 +370,23 @@ class AppPermissionViewModel( val shouldChangeBackground = changeTarget andValue ChangeTarget.CHANGE_BACKGROUND != 0 if (requestGrant) { val stateBefore = createPermissionSnapshot()!! var newGroup = group val oldGroup = group if (shouldChangeForeground) { val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group) newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, newGroup) if (!wasForegroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) } } if (shouldChangeBackground && group.hasBackgroundGroup) { val newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, group) newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup) if (!wasBackgroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup, true) } } logPermissionChanges(stateBefore) logPermissionChanges(oldGroup, newGroup, buttonClicked) } else { var showDefaultDenyDialog = false var showGrantedByDefaultWarning = false Loading @@ -406,17 +409,19 @@ class AppPermissionViewModel( } if (showDefaultDenyDialog && !hasConfirmedRevoke && showGrantedByDefaultWarning) { fragment.showDefaultDenyDialog(changeTarget, R.string.system_warning, userFixed) fragment.showDefaultDenyDialog(changeTarget, R.string.system_warning, userFixed, buttonClicked) return } else if (showDefaultDenyDialog && !hasConfirmedRevoke) { fragment.showDefaultDenyDialog(changeTarget, R.string.old_sdk_deny_warning, userFixed) userFixed, buttonClicked) return } else { val stateBefore = createPermissionSnapshot()!! var newGroup = group val oldGroup = group if (shouldChangeForeground && (wasForegroundGranted || userFixed != group.isUserFixed)) { val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, userFixed) // only log if we have actually denied permissions, not if we switch from Loading @@ -427,8 +432,8 @@ class AppPermissionViewModel( } if (shouldChangeBackground && group.hasBackgroundGroup && (wasBackgroundGranted || userFixed != group.isUserFixed)) { val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup, userFixed) // only log if we have actually denied permissions, not if we switch from // "ask every time" to denied Loading @@ -436,7 +441,7 @@ class AppPermissionViewModel( SafetyNetLogger.logPermissionToggled(newGroup, true) } } logPermissionChanges(stateBefore) logPermissionChanges(oldGroup, newGroup, buttonClicked) } } } Loading @@ -448,24 +453,27 @@ class AppPermissionViewModel( * @param changeTarget whether to change foreground, background, or both. * @param userFixed whether the user has stated they do not wish to be prompted about the * permission any more. * @param buttonPressed button pressed to initiate the change, one of * AppPermissionFragmentActionReported.button_pressed constants * */ fun onDenyAnyWay(changeTarget: ChangeTarget, userFixed: Boolean) { fun onDenyAnyWay(changeTarget: ChangeTarget, userFixed: Boolean, buttonPressed: Int) { val group = lightAppPermGroup ?: return val wasForegroundGranted = group.foreground.isGranted val wasBackgroundGranted = group.background.isGranted var hasDefaultPermissions = false val stateBefore = createPermissionSnapshot() var newGroup = group val oldGroup = group if (changeTarget andValue ChangeTarget.CHANGE_FOREGROUND != 0) { val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, userFixed) if (wasForegroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) } hasDefaultPermissions = group.foreground.isGrantedByDefault } if (changeTarget andValue ChangeTarget.CHANGE_BACKGROUND != 0 && group.hasBackgroundGroup) { val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, userFixed) newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup, userFixed) if (wasBackgroundGranted) { SafetyNetLogger.logPermissionToggled(newGroup) Loading @@ -473,24 +481,13 @@ class AppPermissionViewModel( hasDefaultPermissions = hasDefaultPermissions || group.background.isGrantedByDefault } logPermissionChanges(stateBefore!!) logPermissionChanges(oldGroup, newGroup, buttonPressed) if (hasDefaultPermissions || !group.supportsRuntimePerms) { hasConfirmedRevoke = true } } private fun createPermissionSnapshot(): List<PermissionState>? { val group = lightAppPermGroup ?: return null val permissionSnapshot = ArrayList<PermissionState>() for ((permName, permission) in group.permissions) { permissionSnapshot.add(PermissionState(permName, permission.isGrantedIncludingAppOp)) } return permissionSnapshot } /** * Show the All App Permissions screen with the proper filter group, package name, and user. * Loading Loading @@ -562,37 +559,36 @@ class AppPermissionViewModel( return 0 } data class PermissionState(val permissionName: String, val permissionGranted: Boolean) private fun logPermissionChanges(previousPermissionSnapshot: List<PermissionState>) { val lightGroup = lightAppPermGroup ?: return private fun logPermissionChanges( oldGroup: LightAppPermGroup, newGroup: LightAppPermGroup, buttonPressed: Int ) { val changeId = Random().nextLong() for ((permissionName, wasGranted) in previousPermissionSnapshot) { val permission = lightGroup.permissions[permissionName] ?: continue val isGranted = permission.isGrantedIncludingAppOp for ((permName, permission) in oldGroup.permissions) { val newPermission = newGroup.permissions[permName] ?: continue if (wasGranted != isGranted) { logAppPermissionFragmentActionReported(changeId, permissionName, isGranted) if (permission.isGrantedIncludingAppOp != newPermission.isGrantedIncludingAppOp || permission.flags != newPermission.flags) { logAppPermissionFragmentActionReported(changeId, newPermission, buttonPressed) } } } private fun logAppPermissionFragmentActionReported( changeId: Long, permissionName: String, isGranted: Boolean permission: LightPermission, buttonPressed: Int ) { val uid = KotlinUtils.getPackageUid(app, packageName, user) ?: return PermissionControllerStatsLog.write(APP_PERMISSION_FRAGMENT_ACTION_REPORTED, sessionId, changeId, uid, packageName, permissionName, isGranted) changeId, uid, packageName, permission.permInfo.name, permission.isGrantedIncludingAppOp, permission.flags, buttonPressed) Log.v(LOG_TAG, "Permission changed via UI with sessionId=$sessionId changeId=" + "$changeId uid=$uid packageName=" + "$packageName permission=$permissionName isGranted=$isGranted") "$changeId uid=$uid packageName=$packageName permission=" + permission.permInfo.name + " isGranted=" + permission.isGrantedIncludingAppOp + " permissionFlags=" + permission.flags + " buttonPressed=$buttonPressed") } /** Loading