OSDN Git Service

Checks if mResponses is null before using it.
authorFelipe Leme <felipeal@google.com>
Mon, 24 Jul 2017 18:25:56 +0000 (11:25 -0700)
committerFelipe Leme <felipeal@google.com>
Mon, 24 Jul 2017 19:38:47 +0000 (12:38 -0700)
Test: cts-tradefed run commandAndExit cts-dev -m CtsAutoFillServiceTestCases -t android.autofillservice.cts.LoginActivityTest#testFillResponseAuthWhenAppCallsCancel
Test: cts-tradefed run commandAndExit cts-dev -m CtsAutoFillServiceTestCases

Fixes: 63806922
Bug: 63985284

Change-Id: I8d7cfa34ba88a1d351967e17717b387c805dd00d

core/java/android/view/autofill/AutofillManager.java
services/autofill/java/com/android/server/autofill/Session.java

index 4f9f7e1..e2ad1e0 100644 (file)
@@ -694,8 +694,13 @@ public final class AutofillManager {
     /**
      * Called to indicate the current autofill context should be commited.
      *
-     * <p>For example, when a virtual view is rendering an {@code HTML} page with a form, it should
-     * call this method after the form is submitted and another page is rendered.
+     * <p>This method is typically called by {@link View Views} that manage virtual views; for
+     * example, when the view is rendering an {@code HTML} page with a form and virtual views
+     * that represent the HTML elements, it should call this method after the form is submitted and
+     * another page is rendered.
+     *
+     * <p><b>Note:</b> This method does not need to be called on regular application lifecycle
+     * methods such as {@link android.app.Activity#finish()}.
      */
     public void commit() {
         if (!hasAutofillFeature()) {
@@ -713,8 +718,13 @@ public final class AutofillManager {
     /**
      * Called to indicate the current autofill context should be cancelled.
      *
-     * <p>For example, when a virtual view is rendering an {@code HTML} page with a form, it should
-     * call this method if the user does not post the form but moves to another form in this page.
+     * <p>This method is typically called by {@link View Views} that manage virtual views; for
+     * example, when the view is rendering an {@code HTML} page with a form and virtual views
+     * that represent the HTML elements, it should call this method if the user does not post the
+     * form but moves to another form in this page.
+     *
+     * <p><b>Note:</b> This method does not need to be called on regular application lifecycle
+     * methods such as {@link android.app.Activity#finish()}.
      */
     public void cancel() {
         if (!hasAutofillFeature()) {
index a38b9d3..af47f0c 100644 (file)
@@ -715,7 +715,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                     + id + " destroyed");
             return;
         }
-
+        if (mResponses == null) {
+            // Typically happens when app explicitly called cancel() while the service was showing
+            // the auth UI.
+            Slog.w(TAG, "setAuthenticationResultLocked(" + authenticationId + "): no responses");
+            removeSelf();
+            return;
+        }
         final int requestId = AutofillManager.getRequestIdFromAuthenticationId(authenticationId);
         final FillResponse authenticatedResponse = mResponses.get(requestId);
         if (authenticatedResponse == null || data == null) {
@@ -781,7 +787,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
             return true;
         }
 
-        final int lastResponseIdx = getLastResponseIndex();
+        final int lastResponseIdx = getLastResponseIndexLocked();
         if (lastResponseIdx < 0) {
             Slog.w(TAG, "showSaveLocked(): did not get last response. mResponses=" + mResponses
                     + ", mViewStates=" + mViewStates);
@@ -1265,7 +1271,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
 
         // Only track the views of the last response as only those are reported back to the
         // service, see #showSaveLocked
-        final FillResponse response = mResponses.valueAt(getLastResponseIndex());
+        final FillResponse response = mResponses.valueAt(getLastResponseIndexLocked());
 
         ArraySet<AutofillId> trackedViews = null;
         boolean saveOnAllViewsInvisible = false;
@@ -1642,17 +1648,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         }
     }
 
-    private int getLastResponseIndex() {
+    private int getLastResponseIndexLocked() {
         // The response ids are monotonically increasing so
         // we just find the largest id which is the last. We
         // do not rely on the internal ordering in sparse
         // array to avoid - wow this stopped working!?
         int lastResponseIdx = -1;
         int lastResponseId = -1;
-        final int responseCount = mResponses.size();
-        for (int i = 0; i < responseCount; i++) {
-            if (mResponses.keyAt(i) > lastResponseId) {
-                lastResponseIdx = i;
+        if (mResponses != null) {
+            final int responseCount = mResponses.size();
+            for (int i = 0; i < responseCount; i++) {
+                if (mResponses.keyAt(i) > lastResponseId) {
+                    lastResponseIdx = i;
+                }
             }
         }
         return lastResponseIdx;