Merge "Protect autofill UI against redressing" into oc-dev
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 8ffe8f5..4f90019 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -61,6 +61,8 @@
private final MetricsLogger mMetricsLogger = new MetricsLogger();
+ private final @NonNull OverlayControl mOverlayControl;
+
public interface AutoFillUiCallback {
void authenticate(int requestId, int datasetIndex, @NonNull IntentSender intent,
@Nullable Bundle extras);
@@ -75,6 +77,7 @@
public AutoFillUI(@NonNull Context context) {
mContext = context;
+ mOverlayControl = new OverlayControl(context);
}
public void setCallback(@NonNull AutoFillUiCallback callback) {
@@ -174,7 +177,7 @@
}
hideAllUiThread(callback);
mFillUi = new FillUi(mContext, response, focusedId,
- filterText, new FillUi.Callback() {
+ filterText, mOverlayControl, new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
@@ -255,7 +258,7 @@
}
hideAllUiThread(callback);
mSaveUi = new SaveUi(mContext, providerLabel, info,
- new SaveUi.OnSaveListener() {
+ mOverlayControl, new SaveUi.OnSaveListener() {
@Override
public void onSave() {
log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index e9c98e9..51a239f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -100,7 +100,7 @@
FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
- @NonNull Callback callback) {
+ @NonNull OverlayControl overlayControl, @NonNull Callback callback) {
mContext = context;
mCallback = callback;
@@ -146,7 +146,7 @@
mContentWidth = content.getMeasuredWidth();
mContentHeight = content.getMeasuredHeight();
- mWindow = new AnchoredWindow(decor);
+ mWindow = new AnchoredWindow(decor, overlayControl);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
} else {
final int datasetCount = response.getDatasets().size();
@@ -193,7 +193,7 @@
}
applyNewFilterText();
- mWindow = new AnchoredWindow(decor);
+ mWindow = new AnchoredWindow(decor, overlayControl);
}
}
@@ -366,6 +366,7 @@
}
final class AnchoredWindow implements View.OnTouchListener {
+ private final @NonNull OverlayControl mOverlayControl;
private final WindowManager mWm;
private final View mContentView;
private boolean mShowing;
@@ -375,9 +376,10 @@
*
* @param contentView content of the window
*/
- AnchoredWindow(View contentView) {
+ AnchoredWindow(View contentView, @NonNull OverlayControl overlayControl) {
mWm = contentView.getContext().getSystemService(WindowManager.class);
mContentView = contentView;
+ mOverlayControl = overlayControl;
}
/**
@@ -391,6 +393,7 @@
.getString(R.string.autofill_picker_accessibility_title);
mWm.addView(mContentView, params);
mContentView.setOnTouchListener(this);
+ mOverlayControl.hideOverlays();
mShowing = true;
} else {
mWm.updateViewLayout(mContentView, params);
@@ -423,6 +426,8 @@
// does, it should not crash the system.
Slog.e(TAG, "Exception hiding window ", e);
mCallback.onDestroy();
+ } finally {
+ mOverlayControl.showOverlays();
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/OverlayControl.java b/services/autofill/java/com/android/server/autofill/ui/OverlayControl.java
new file mode 100644
index 0000000..fe0611e
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/OverlayControl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.server.autofill.ui;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+
+/**
+ * This class controls showing/hiding overlays. We don't
+ * hide all overlays (toast/system alerts) while sensitive
+ * autofill UI is up.
+ */
+class OverlayControl {
+
+ private final IBinder mToken = new Binder();
+
+ private final @NonNull AppOpsManager mAppOpsManager;
+
+ OverlayControl(@NonNull Context context) {
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ }
+
+ void hideOverlays() {
+ setOverlayAllowed(false);
+ }
+
+ void showOverlays() {
+ setOverlayAllowed(true);
+ }
+
+ private void setOverlayAllowed(boolean allowed) {
+ if (mAppOpsManager != null) {
+ mAppOpsManager.setUserRestriction(
+ AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
+ mAppOpsManager.setUserRestriction(
+ AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
+ }
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 491af91..d1fbbf9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -99,14 +99,17 @@
private final @NonNull OneTimeListener mListener;
+ private final @NonNull OverlayControl mOverlayControl;
+
private final CharSequence mTitle;
private final CharSequence mSubTitle;
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
- @NonNull OnSaveListener listener) {
+ @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener) {
mListener = new OneTimeListener(listener);
+ mOverlayControl = overlayControl;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -197,16 +200,21 @@
Slog.i(TAG, "Showing save dialog: " + mTitle);
mDialog.show();
+ mOverlayControl.hideOverlays();
}
void destroy() {
- if (sDebug) Slog.d(TAG, "destroy()");
- throwIfDestroyed();
- mListener.onDestroy();
- mHandler.removeCallbacksAndMessages(mListener);
- if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
- mDialog.dismiss();
- mDestroyed = true;
+ try {
+ if (sDebug) Slog.d(TAG, "destroy()");
+ throwIfDestroyed();
+ mListener.onDestroy();
+ mHandler.removeCallbacksAndMessages(mListener);
+ if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
+ mDialog.dismiss();
+ mDestroyed = true;
+ } finally {
+ mOverlayControl.showOverlays();
+ }
}
private void throwIfDestroyed() {