1 /* <lambda>null2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * 17 */ 18 19 package com.android.healthconnect.controller.permissions.additionalaccess 20 21 import android.app.Dialog 22 import android.content.Intent.EXTRA_PACKAGE_NAME 23 import android.os.Bundle 24 import android.util.Log 25 import android.view.View 26 import android.widget.ImageView 27 import android.widget.RadioGroup 28 import android.widget.TextView 29 import androidx.annotation.IdRes 30 import androidx.core.os.bundleOf 31 import androidx.fragment.app.DialogFragment 32 import androidx.fragment.app.activityViewModels 33 import com.android.healthconnect.controller.R 34 import com.android.healthconnect.controller.permissions.additionalaccess.PermissionUiState.ALWAYS_ALLOW 35 import com.android.healthconnect.controller.permissions.additionalaccess.PermissionUiState.ASK_EVERY_TIME 36 import com.android.healthconnect.controller.permissions.additionalaccess.PermissionUiState.NEVER_ALLOW 37 import com.android.healthconnect.controller.permissions.app.AppPermissionViewModel 38 import com.android.healthconnect.controller.shared.dialog.AlertDialogBuilder 39 import com.android.healthconnect.controller.utils.logging.AdditionalAccessElement.EXERCISE_ROUTES_ALLOW_ALL_BUTTON 40 import com.android.healthconnect.controller.utils.logging.AdditionalAccessElement.EXERCISE_ROUTES_ASK_BUTTON 41 import com.android.healthconnect.controller.utils.logging.AdditionalAccessElement.EXERCISE_ROUTES_DIALOG_CONTAINER 42 import com.android.healthconnect.controller.utils.logging.AdditionalAccessElement.EXERCISE_ROUTES_DIALOG_DENY_BUTTON 43 import com.android.healthconnect.controller.utils.logging.HealthConnectLogger 44 import dagger.hilt.android.AndroidEntryPoint 45 import javax.inject.Inject 46 47 /** Dialog fragment to allow the user to change Exercise routes permission state. */ 48 @AndroidEntryPoint(DialogFragment::class) 49 class ExerciseRoutesPermissionDialogFragment : Hilt_ExerciseRoutesPermissionDialogFragment() { 50 51 @Inject lateinit var logger: HealthConnectLogger 52 53 private lateinit var permissionRadioGroup: RadioGroup 54 private lateinit var appIcon: ImageView 55 private lateinit var packageName: String 56 57 private val viewModel: AdditionalAccessViewModel by activityViewModels() 58 private val permissionsViewModel: AppPermissionViewModel by activityViewModels() 59 private val permissionChangedListener = 60 RadioGroup.OnCheckedChangeListener { _, selectedId -> 61 when (selectedId) { 62 R.id.radio_button_always_allow -> { 63 viewModel.updateExerciseRouteState(packageName, ALWAYS_ALLOW) 64 logger.logInteraction(EXERCISE_ROUTES_ALLOW_ALL_BUTTON) 65 } 66 R.id.radio_button_ask -> { 67 viewModel.updateExerciseRouteState(packageName, ASK_EVERY_TIME) 68 logger.logInteraction(EXERCISE_ROUTES_ASK_BUTTON) 69 } 70 R.id.radio_button_revoke -> { 71 viewModel.updateExerciseRouteState(packageName, NEVER_ALLOW) 72 logger.logInteraction(EXERCISE_ROUTES_DIALOG_DENY_BUTTON) 73 } 74 } 75 this.dismiss() 76 } 77 private val extraLogger = { 78 logger.logImpression(EXERCISE_ROUTES_ALLOW_ALL_BUTTON) 79 logger.logImpression(EXERCISE_ROUTES_ASK_BUTTON) 80 logger.logImpression(EXERCISE_ROUTES_DIALOG_DENY_BUTTON) 81 } 82 83 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { 84 val view = layoutInflater.inflate(R.layout.dialog_exercise_routes_permission, null) 85 86 val packageNameExtra = requireArguments().getString(EXTRA_PACKAGE_NAME) 87 if (packageNameExtra.isNullOrEmpty()) { 88 Log.e(TAG, "Invalid Intent Extras, finishing.") 89 return super.onCreateDialog(savedInstanceState) 90 } 91 packageName = packageNameExtra 92 93 setupMessage(view) 94 setupAppIcon(view) 95 setupPermissionRadioGroup(view) 96 97 return AlertDialogBuilder(this, EXERCISE_ROUTES_DIALOG_CONTAINER) 98 .setAdditionalLogging(extraLogger) 99 .setView(view) 100 .create() 101 } 102 103 private fun setupMessage(view: View) { 104 val dialogMessage = view.findViewById(R.id.dialog_message) as TextView 105 permissionsViewModel.appInfo.observe(this) { app -> 106 dialogMessage.text = getString(R.string.route_permissions_summary, app.appName) 107 } 108 } 109 110 private fun setupAppIcon(view: View) { 111 appIcon = view.findViewById(R.id.dialog_icon) 112 permissionsViewModel.appInfo.observe(this) { app -> appIcon.setImageDrawable(app.icon) } 113 } 114 115 private fun setupPermissionRadioGroup(view: View) { 116 permissionRadioGroup = view.findViewById(R.id.radio_group_route_permission) 117 permissionRadioGroup.apply { 118 val state = viewModel.additionalAccessState.value?.exerciseRoutePermissionUIState 119 if (state != null) { 120 setOnCheckedChangeListener(null) 121 check(getId(state)) 122 } 123 setOnCheckedChangeListener(permissionChangedListener) 124 } 125 } 126 127 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 128 super.onViewCreated(view, savedInstanceState) 129 viewModel.additionalAccessState.observe(viewLifecycleOwner) { screenState -> 130 permissionRadioGroup.check(getId(screenState.exerciseRoutePermissionUIState)) 131 } 132 } 133 134 fun setPackageName(packageName: String) { 135 this.packageName = packageName 136 } 137 138 @IdRes 139 private fun getId(currentState: PermissionUiState): Int { 140 return when (currentState) { 141 ALWAYS_ALLOW -> R.id.radio_button_always_allow 142 NEVER_ALLOW -> R.id.radio_button_revoke 143 else -> R.id.radio_button_ask 144 } 145 } 146 147 companion object { 148 private const val TAG = "ERPermissionDialog" 149 150 fun createDialog(packageName: String): ExerciseRoutesPermissionDialogFragment { 151 return ExerciseRoutesPermissionDialogFragment().apply { 152 arguments = bundleOf(EXTRA_PACKAGE_NAME to packageName) 153 } 154 } 155 } 156 } 157