diff options
author | 2024-01-04 13:14:02 -0800 | |
---|---|---|
committer | 2024-01-09 20:31:23 +0000 | |
commit | 0c01d53e01fdee29ab71b8340778ba9abfe915e4 (patch) | |
tree | d8b2502aed7c038ba12e573514f3c2d7ae86a35d | |
parent | 8ec80176993a15e3c5c41389d1ea1285665b567b (diff) |
Save photo picker callback state on activity destroy
When the activity is destroyed, we should remember that we were showing
the photo picker. Otherwise, the dialog won't close when the photo
picker is closed.
Test: manual
Relnote: fix UI issue with permission grant dialog
Fixes: 308830728
Change-Id: Ibbf5466747e999f19e790c3b981976ff6369bb9a
Merged-In: Ibbf5466747e999f19e790c3b981976ff6369bb9a
2 files changed, 121 insertions, 73 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java index a6e521138..53f8fe712 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java @@ -66,7 +66,6 @@ import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; -import androidx.core.util.Consumer; import androidx.core.util.Preconditions; import com.android.modules.utils.build.SdkLevel; @@ -417,7 +416,7 @@ public class GrantPermissionsActivity extends SettingsActivity mViewModel.sendDirectlyToSettings(top, info.getGroupName()); return; } else if (info.getOpenPhotoPicker()) { - mViewModel.openPhotoPicker(top, GRANTED_USER_SELECTED); + mViewModel.openPhotoPicker(top); return; } @@ -604,16 +603,14 @@ public class GrantPermissionsActivity extends SettingsActivity @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - Consumer<Intent> callback = mViewModel.getActivityResultCallback(); - if (callback == null || (requestCode != APP_PERMISSION_REQUEST_CODE - && requestCode != PHOTO_PICKER_REQUEST_CODE)) { + if (requestCode != APP_PERMISSION_REQUEST_CODE + && requestCode != PHOTO_PICKER_REQUEST_CODE) { return; } if (requestCode == PHOTO_PICKER_REQUEST_CODE) { data = new Intent("").putExtra(INTENT_PHOTOS_SELECTED, resultCode == RESULT_OK); } - callback.accept(data); - mViewModel.setActivityResultCallback(null); + mViewModel.handleCallback(data, requestCode); } @Override @@ -633,11 +630,10 @@ public class GrantPermissionsActivity extends SettingsActivity mPreMergeShownGroupName = null; } - if (Objects.equals(READ_MEDIA_VISUAL, name) - && result == GrantPermissionsViewHandler.GRANTED_USER_SELECTED) { + if (Objects.equals(READ_MEDIA_VISUAL, name) && result == GRANTED_USER_SELECTED) { // Only the top activity can receive activity results Activity top = mFollowerActivities.isEmpty() ? this : mFollowerActivities.get(0); - mViewModel.openPhotoPicker(top, result); + mViewModel.openPhotoPicker(top); logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result); return; } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt index 3f19db475..d9fd7f2ea 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt @@ -186,6 +186,18 @@ class GrantPermissionsViewModel( private var appPermGroupLiveDatas = mutableMapOf<String, LightAppPermGroupLiveData>() + internal data class ResultCallback(val consumer: Consumer<Intent>, val requestCode: Int) + + private var activityResultCallback: ResultCallback? = null + + init { + if (storedState?.containsKey(SAVED_REQUEST_CODE_KEY) == true) { + if (storedState.getInt(SAVED_REQUEST_CODE_KEY) == PHOTO_PICKER_REQUEST_CODE) { + setPhotoPickerCallback() + } + } + } + /** * A class which represents a correctly requested permission group, and the buttons and messages * which should be shown with it. @@ -202,8 +214,6 @@ class GrantPermissionsViewModel( val groupName = groupInfo.name } - var activityResultCallback: Consumer<Intent>? = null - /** A LiveData which holds a list of the currently pending RequestInfos */ val requestInfosLiveData = object : SmartUpdateMediatorLiveData<List<RequestInfo>>() { @@ -1494,7 +1504,9 @@ class GrantPermissionsViewModel( Log.v( LOG_TAG, "Permission grant result requestId=$sessionId " + - "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " + + "callingUid=${packageInfo.uid} " + + "callingPackage=$packageName " + + "permission=$permission " + "isImplicit=$isImplicit result=$result " + "isPermissionRationaleShown=$isPermissionRationaleShown" ) @@ -1522,6 +1534,7 @@ class GrantPermissionsViewModel( val (groupName, isBackground) = groupKey outState.putInt(getInstanceStateKey(groupName, isBackground), groupState.state) } + activityResultCallback?.let { outState.putInt(SAVED_REQUEST_CODE_KEY, it.requestCode) } } /** @@ -1547,12 +1560,25 @@ class GrantPermissionsViewModel( } } + fun handleCallback(data: Intent?, requestCode: Int) { + val currCallback = activityResultCallback + if (currCallback == null || requestCode != currCallback.requestCode) { + return + } + currCallback.consumer.accept(data) + activityResultCallback = null + } + fun handleHealthConnectPermissions(activity: Activity) { if (activityResultCallback == null) { - activityResultCallback = Consumer { - permGroupsToSkip.add(HEALTH_PERMISSION_GROUP) - requestInfosLiveData.update() - } + activityResultCallback = + ResultCallback( + { + permGroupsToSkip.add(HEALTH_PERMISSION_GROUP) + requestInfosLiveData.update() + }, + APP_PERMISSION_REQUEST_CODE + ) val healthPermissions = unfilteredAffectedPermissions .filter { permission -> isHealthPermission(activity, permission) } @@ -1575,55 +1601,72 @@ class GrantPermissionsViewModel( */ fun sendDirectlyToSettings(activity: Activity, groupName: String) { if (activityResultCallback == null) { - activityResultCallback = Consumer { data -> - if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) { - // User didn't interact, count against rate limit - val group = - groupStates[groupName to false]?.group - ?: groupStates[groupName to true]?.group ?: return@Consumer - if (group.background.isUserSet) { - KotlinUtils.setGroupFlags( - app, - group, - FLAG_PERMISSION_USER_FIXED to true, - filterPermissions = group.backgroundPermNames - ) - } else { - KotlinUtils.setGroupFlags( - app, - group, - FLAG_PERMISSION_USER_SET to true, - filterPermissions = group.backgroundPermNames - ) - } - } + activityResultCallback = + ResultCallback( + Consumer { data -> + if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) { + // User didn't interact, count against rate limit + val group = + groupStates[groupName to false]?.group + ?: groupStates[groupName to true]?.group + ?: return@Consumer + if (group.background.isUserSet) { + KotlinUtils.setGroupFlags( + app, + group, + FLAG_PERMISSION_USER_FIXED to true, + filterPermissions = group.backgroundPermNames + ) + } else { + KotlinUtils.setGroupFlags( + app, + group, + FLAG_PERMISSION_USER_SET to true, + filterPermissions = group.backgroundPermNames + ) + } + } - permGroupsToSkip.add(groupName) - // Update our liveData now that there is a new skipped group - requestInfosLiveData.update() - } + permGroupsToSkip.add(groupName) + // Update our liveData now that there is a new skipped group + requestInfosLiveData.update() + }, + APP_PERMISSION_REQUEST_CODE + ) startAppPermissionFragment(activity, groupName) } } - fun openPhotoPicker(activity: Activity, result: Int) { + fun openPhotoPicker(activity: Activity) { if (activityResultCallback != null) { return } if (groupStates[READ_MEDIA_VISUAL to false]?.affectedPermissions == null) { return } - activityResultCallback = Consumer { data -> - val anySelected = data?.getBooleanExtra(INTENT_PHOTOS_SELECTED, true) == true - if (anySelected) { - onPermissionGrantResult(READ_MEDIA_VISUAL, null, result) - } else { - onPermissionGrantResult(READ_MEDIA_VISUAL, null, CANCELED) - } - requestInfosLiveData.update() - } - openPhotoPickerForApp(activity, packageInfo.uid, unfilteredAffectedPermissions, - PHOTO_PICKER_REQUEST_CODE) + setPhotoPickerCallback() + openPhotoPickerForApp( + activity, + packageInfo.uid, + unfilteredAffectedPermissions, + PHOTO_PICKER_REQUEST_CODE + ) + } + + private fun setPhotoPickerCallback() { + activityResultCallback = + ResultCallback( + { data -> + val anySelected = data?.getBooleanExtra(INTENT_PHOTOS_SELECTED, true) == true + if (anySelected) { + onPermissionGrantResult(READ_MEDIA_VISUAL, null, GRANTED_USER_SELECTED) + } else { + onPermissionGrantResult(READ_MEDIA_VISUAL, null, CANCELED) + } + requestInfosLiveData.update() + }, + PHOTO_PICKER_REQUEST_CODE + ) } /** @@ -1634,15 +1677,19 @@ class GrantPermissionsViewModel( */ fun sendToSettingsFromLink(activity: Activity, groupName: String) { startAppPermissionFragment(activity, groupName) - activityResultCallback = Consumer { data -> - val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) - if (returnGroupName != null) { - permGroupsToSkip.add(returnGroupName) - val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, -1) - logSettingsInteraction(returnGroupName, result) - requestInfosLiveData.update() - } - } + activityResultCallback = + ResultCallback( + { data -> + val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) + if (returnGroupName != null) { + permGroupsToSkip.add(returnGroupName) + val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, -1) + logSettingsInteraction(returnGroupName, result) + requestInfosLiveData.update() + } + }, + APP_PERMISSION_REQUEST_CODE + ) } /** @@ -1662,15 +1709,19 @@ class GrantPermissionsViewModel( putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName) putExtra(Constants.EXTRA_SESSION_ID, sessionId) } - activityResultCallback = Consumer { data -> - val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) - if (returnGroupName != null) { - permGroupsToSkip.add(returnGroupName) - val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, CANCELED) - logSettingsInteraction(returnGroupName, result) - requestInfosLiveData.update() - } - } + activityResultCallback = + ResultCallback( + { data -> + val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) + if (returnGroupName != null) { + permGroupsToSkip.add(returnGroupName) + val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, CANCELED) + logSettingsInteraction(returnGroupName, result) + requestInfosLiveData.update() + } + }, + APP_PERMISSION_REQUEST_CODE + ) activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE) } @@ -1836,6 +1887,7 @@ class GrantPermissionsViewModel( companion object { const val APP_PERMISSION_REQUEST_CODE = 1 const val PHOTO_PICKER_REQUEST_CODE = 2 + const val SAVED_REQUEST_CODE_KEY = "saved_request_code" private const val STATE_UNKNOWN = 0 private const val STATE_ALLOWED = 1 private const val STATE_DENIED = 2 |