Merge "Set verified stamps to be trusted" into rvc-dev
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 0000000..b77d6fa
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_dialog_pin.xml
@@ -0,0 +1,36 @@
+<!--
+ ~ 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="?android:attr/dialogPreferredPadding"
+ android:paddingRight="?android:attr/dialogPreferredPadding">
+ <EditText
+ android:id="@+id/controls_pin_input"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/controls_pin_instructions"
+ android:inputType="numberPassword" />
+ <CheckBox
+ android:id="@+id/controls_pin_use_alpha"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:text="@string/controls_pin_use_alphanumeric" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5b28479..caf22fe 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2646,4 +2646,11 @@
<string name="controls_dialog_ok">Add to favorites</string>
<!-- Controls dialog message [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message"><xliff:g id="app" example="System UI">%s</xliff:g> suggested this control to add to your favorites.</string>
+
+ <!-- Controls PIN entry dialog, switch to alphanumeric keyboard [CHAR LIMIT=100] -->
+ <string name="controls_pin_use_alphanumeric">PIN contains letters or symbols</string>
+ <!-- Controls PIN entry dialog, title [CHAR LIMIT=30] -->
+ <string name="controls_pin_verify">Verify device PIN</string>
+ <!-- Controls PIN entry dialog, text hint [CHAR LIMIT=30] -->
+ <string name="controls_pin_instructions">Enter PIN</string>
</resources>
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 0000000..2494fd1
--- /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<EditText>(R.id.controls_pin_input)
+ val pin = dialog.requireViewById<EditText>(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<EditText>(R.id.controls_pin_input)
+ requireViewById<CheckBox>(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 d56428d..b1b98bc 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.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 @@
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 @@
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 @@
}
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 eaf57ff..ca6619b 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 @@
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.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.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 @@
private lateinit var parent: ViewGroup
private lateinit var lastItems: List<SelectionItem>
private var popup: ListPopupWindow? = null
-
+ private var activeDialog: Dialog? = null
private val addControlsItem: SelectionItem
init {
@@ -388,6 +390,7 @@
override fun hide() {
Log.d(ControlsUiController.TAG, "hide()")
popup?.dismiss()
+ activeDialog?.dismiss()
controlsController.get().unsubscribe()
context.unbindService(tokenProviderConnection)
@@ -418,7 +421,15 @@
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)
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 968528c..7c3cab1 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -951,18 +951,18 @@
|| isVpnServicePreConsented(context, packageName);
}
- private int getAppUid(String app, int userHandle) {
+ private int getAppUid(final String app, final int userHandle) {
if (VpnConfig.LEGACY_VPN.equals(app)) {
return Process.myUid();
}
PackageManager pm = mContext.getPackageManager();
- int result;
- try {
- result = pm.getPackageUidAsUser(app, userHandle);
- } catch (NameNotFoundException e) {
- result = -1;
- }
- return result;
+ return Binder.withCleanCallingIdentity(() -> {
+ try {
+ return pm.getPackageUidAsUser(app, userHandle);
+ } catch (NameNotFoundException e) {
+ return -1;
+ }
+ });
}
private boolean doesPackageTargetAtLeastQ(String packageName) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 7dd2e55..83fe556 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -331,7 +331,8 @@
}
// Reverts apex sessions and user data (if checkpoint is supported). Also reboots the device.
- private void abortCheckpoint() {
+ private void abortCheckpoint(String errorMsg) {
+ Slog.e(TAG, "Aborting checkpoint: " + errorMsg);
try {
if (supportsCheckpoint() && needsCheckpoint()) {
mApexManager.revertActiveSessions();
@@ -504,6 +505,8 @@
// mode. If not, we fail all sessions.
if (supportsCheckpoint() && !needsCheckpoint()) {
// TODO(b/146343545): Persist failure reason across checkpoint reboot
+ Slog.d(TAG, "Reverting back to safe state. Marking " + session.sessionId
+ + " as failed.");
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN,
"Reverting back to safe state");
return;
@@ -524,26 +527,29 @@
if (hasApex) {
if (apexSessionInfo == null) {
+ String errorMsg = "apexd did not know anything about a staged session supposed to"
+ + " be activated";
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- "apexd did not know anything about a staged session supposed to be"
- + "activated");
- abortCheckpoint();
+ errorMsg);
+ abortCheckpoint(errorMsg);
return;
}
if (isApexSessionFailed(apexSessionInfo)) {
+ String errorMsg = "APEX activation failed. Check logcat messages from apexd for "
+ + "more information.";
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- "APEX activation failed. Check logcat messages from apexd for "
- + "more information.");
- abortCheckpoint();
+ errorMsg);
+ abortCheckpoint(errorMsg);
return;
}
if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) {
// Apexd did not apply the session for some unknown reason. There is no guarantee
// that apexd will install it next time. Safer to proactively mark as failed.
+ String errorMsg = "Staged session " + session.sessionId + "at boot didn't "
+ + "activate nor fail. Marking it as failed anyway.";
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- "Staged session " + session.sessionId + "at boot didn't "
- + "activate nor fail. Marking it as failed anyway.");
- abortCheckpoint();
+ errorMsg);
+ abortCheckpoint(errorMsg);
return;
}
snapshotAndRestoreForApexSession(session);
@@ -556,7 +562,7 @@
installApksInSession(session);
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
- abortCheckpoint();
+ abortCheckpoint(e.getMessage());
// If checkpoint is not supported, we have to handle failure for one staged session.
if (!hasApex) {