From b7da66c80d1f7e5e9632ffa91603dd01430ac13f Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Fri, 6 Mar 2020 10:49:31 -0500 Subject: [PATCH] Controls UI - Add PIN dialog Support 'ControlAction.RESPONSE_CHALLENGE_PIN' response types. When detected, prompt the user for the PIN, copy the action with the user's response, and send it all over again. Bug: 150849062 Test: visual Change-Id: I5cf8391125a3dfe235895192b2663851f37eed11 --- .../res/layout/controls_dialog_pin.xml | 36 +++++++ packages/SystemUI/res/values/strings.xml | 7 ++ .../systemui/controls/ui/ChallengeDialogs.kt | 102 ++++++++++++++++++ .../systemui/controls/ui/ControlViewHolder.kt | 4 +- .../controls/ui/ControlsUiControllerImpl.kt | 17 ++- 5 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 packages/SystemUI/res/layout/controls_dialog_pin.xml create mode 100644 packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt diff --git a/packages/SystemUI/res/layout/controls_dialog_pin.xml b/packages/SystemUI/res/layout/controls_dialog_pin.xml new file mode 100644 index 0000000000000..b77d6fa6a9567 --- /dev/null +++ b/packages/SystemUI/res/layout/controls_dialog_pin.xml @@ -0,0 +1,36 @@ + + + + + + diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 5b28479ab5caf..caf22fe16bebc 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2646,4 +2646,11 @@ Add to favorites %s suggested this control to add to your favorites. + + + PIN contains letters or symbols + + Verify device PIN + + Enter PIN diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt new file mode 100644 index 0000000000000..2494fd119670c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 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.systemui.controls.ui + +import android.app.AlertDialog +import android.app.Dialog +import android.content.DialogInterface +import android.service.controls.actions.BooleanAction +import android.service.controls.actions.CommandAction +import android.service.controls.actions.ControlAction +import android.service.controls.actions.FloatAction +import android.service.controls.actions.ModeAction +import android.text.InputType +import android.util.Log +import android.view.WindowManager +import android.widget.CheckBox +import android.widget.EditText + +import com.android.systemui.R + +/** + * Creates all dialogs for challengeValues that can occur from a call to + * {@link ControlsProviderService#performControlAction}. The types of challenge + * responses are listed in {@link ControlAction.ResponseResult}. + */ +object ChallengeDialogs { + + fun createPinDialog(cvh: ControlViewHolder): Dialog? { + val lastAction = cvh.lastAction + if (lastAction == null) { + Log.e(ControlsUiController.TAG, + "PIN Dialog attempted but no last action is set. Will not show") + return null + } + val builder = AlertDialog.Builder( + cvh.context, + android.R.style.Theme_DeviceDefault_Dialog_Alert + ).apply { + setTitle(R.string.controls_pin_verify) + setView(R.layout.controls_dialog_pin) + setPositiveButton( + android.R.string.ok, + DialogInterface.OnClickListener { dialog, _ -> + if (dialog is Dialog) { + dialog.requireViewById(R.id.controls_pin_input) + val pin = dialog.requireViewById(R.id.controls_pin_input) + .getText().toString() + cvh.action(addChallengeValue(lastAction, pin)) + dialog.dismiss() + } + }) + setNegativeButton( + android.R.string.cancel, + DialogInterface.OnClickListener { dialog, _ -> dialog.cancel() } + ) + } + return builder.create().apply { + getWindow().apply { + setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY) + setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) + } + setOnShowListener(DialogInterface.OnShowListener { _ -> + val editText = requireViewById(R.id.controls_pin_input) + requireViewById(R.id.controls_pin_use_alpha).setOnClickListener { v -> + if ((v as CheckBox).isChecked) { + editText.setInputType( + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD) + } else { + editText.setInputType( + InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD) + } + } + editText.requestFocus() + }) + } + } + + private fun addChallengeValue(action: ControlAction, challengeValue: String): ControlAction { + val id = action.getTemplateId() + return when (action) { + is BooleanAction -> BooleanAction(id, action.getNewState(), challengeValue) + is FloatAction -> FloatAction(id, action.getNewValue(), challengeValue) + is CommandAction -> CommandAction(id, challengeValue) + is ModeAction -> ModeAction(id, action.getNewMode(), challengeValue) + else -> throw IllegalStateException("'action' is not a known type: $action") + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index d56428dbcdbe8..b1b98bc7d044e 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -27,7 +27,6 @@ import android.service.controls.templates.ControlTemplate import android.service.controls.templates.TemperatureControlTemplate import android.service.controls.templates.ToggleRangeTemplate import android.service.controls.templates.ToggleTemplate -import android.util.Log import android.view.View import android.view.ViewGroup import android.widget.ImageView @@ -57,6 +56,7 @@ class ControlViewHolder( lateinit var cws: ControlWithState var cancelUpdate: Runnable? = null var behavior: Behavior? = null + var lastAction: ControlAction? = null init { val ld = layout.getBackground() as LayerDrawable @@ -98,7 +98,6 @@ class ControlViewHolder( fun actionResponse(@ControlAction.ResponseResult response: Int) { // TODO: b/150931809 - handle response codes - Log.d(ControlsUiController.TAG, "Received response code: $response") } fun setTransientStatus(tempStatus: String) { @@ -115,6 +114,7 @@ class ControlViewHolder( } fun action(action: ControlAction) { + lastAction = action controlsController.action(cws.componentName, cws.ci, action) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index eaf57ff208e5e..ca6619b59c4dc 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -18,6 +18,7 @@ package com.android.systemui.controls.ui import android.accounts.Account import android.accounts.AccountManager +import android.app.Dialog import android.content.ComponentName import android.content.Context import android.content.Intent @@ -28,6 +29,7 @@ import android.graphics.drawable.LayerDrawable import android.os.IBinder import android.service.controls.Control import android.service.controls.TokenProvider +import android.service.controls.actions.ControlAction import android.util.Log import android.view.ContextThemeWrapper import android.view.LayoutInflater @@ -49,8 +51,8 @@ import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.R import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.R import dagger.Lazy @@ -152,7 +154,7 @@ class ControlsUiControllerImpl @Inject constructor ( private lateinit var parent: ViewGroup private lateinit var lastItems: List private var popup: ListPopupWindow? = null - + private var activeDialog: Dialog? = null private val addControlsItem: SelectionItem init { @@ -388,6 +390,7 @@ class ControlsUiControllerImpl @Inject constructor ( override fun hide() { Log.d(ControlsUiController.TAG, "hide()") popup?.dismiss() + activeDialog?.dismiss() controlsController.get().unsubscribe() context.unbindService(tokenProviderConnection) @@ -418,7 +421,15 @@ class ControlsUiControllerImpl @Inject constructor ( override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) { val key = ControlKey(componentName, controlId) uiExecutor.execute { - controlViewsById.get(key)?.actionResponse(response) + controlViewsById.get(key)?.let { cvh -> + when (response) { + ControlAction.RESPONSE_CHALLENGE_PIN -> { + activeDialog = ChallengeDialogs.createPinDialog(cvh) + activeDialog?.show() + } + else -> cvh.actionResponse(response) + } + } } }