aboutsummaryrefslogtreecommitdiff
path: root/input/autofill/AutofillFramework
diff options
context:
space:
mode:
authorDouglas Sigelbaum <sigelbaum@google.com>2017-11-28 16:18:42 -0800
committerDouglas Sigelbaum <sigelbaum@google.com>2018-01-04 23:09:20 +0000
commitcec0c701a6c2c00a66bd1c7ec6dd26d13d95d4fd (patch)
treeb621b2a75f77906f515ef07cf769f11568b36ead /input/autofill/AutofillFramework
parentc6d490dccbd465c91ca4280ad96ece1cd7720cdb (diff)
downloadandroid-cec0c701a6c2c00a66bd1c7ec6dd26d13d95d4fd.tar.gz
Save ClientViewMetadata between pages.
Bug: 69771916 Test: Manual Change-Id: I4ec1d73e727c6e98d007af234b9174e46c51a652
Diffstat (limited to 'input/autofill/AutofillFramework')
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java7
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/layout/fragment_edge_cases.xml2
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml3
-rw-r--r--input/autofill/AutofillFramework/afservice/build.gradle4
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java4
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java11
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java1
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java171
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadataBuilder.java79
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java145
10 files changed, 231 insertions, 196 deletions
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java
index d7395c40..9e09b45b 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java
@@ -47,19 +47,14 @@ public class MultiplePartitionsActivity extends AppCompatActivity {
private ScrollableCustomVirtualView mCustomVirtualView;
private AutofillManager mAutofillManager;
-
private CustomVirtualView.Partition mCredentialsPartition;
private CustomVirtualView.Partition mCcPartition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
setContentView(R.layout.multiple_partitions_activity);
-
mCustomVirtualView = findViewById(R.id.custom_view);
-
-
mCredentialsPartition =
mCustomVirtualView.addPartition(getString(R.string.partition_credentials));
mCredentialsPartition.addLine("username", View.AUTOFILL_TYPE_TEXT,
@@ -68,7 +63,6 @@ public class MultiplePartitionsActivity extends AppCompatActivity {
mCredentialsPartition.addLine("password", View.AUTOFILL_TYPE_TEXT,
getString(R.string.password_label),
" ", true, View.AUTOFILL_HINT_PASSWORD);
-
int ccExpirationType = View.AUTOFILL_TYPE_DATE;
// TODO: add a checkbox to switch between text / date instead
Intent intent = getIntent();
@@ -82,7 +76,6 @@ public class MultiplePartitionsActivity extends AppCompatActivity {
Toast.makeText(getApplicationContext(), typeMessage, Toast.LENGTH_LONG).show();
}
}
-
mCcPartition = mCustomVirtualView.addPartition(getString(R.string.partition_credit_card));
mCcPartition.addLine("ccNumber", View.AUTOFILL_TYPE_TEXT,
getString(R.string.credit_card_number_label),
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/fragment_edge_cases.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/fragment_edge_cases.xml
index cca506fa..ab7c32aa 100644
--- a/input/autofill/AutofillFramework/Application/src/main/res/layout/fragment_edge_cases.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/fragment_edge_cases.xml
@@ -72,7 +72,6 @@
android:id="@+id/multistepSignInButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"
app:imageColor="@android:color/holo_green_light"
app:infoText="@string/multi_step_signin_info"
app:itemLogo="@drawable/ic_person_black_24dp"
@@ -84,7 +83,6 @@
android:id="@+id/multistepCreditCardButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"
app:imageColor="@android:color/holo_purple"
app:infoText="@string/multi_step_cc_info"
app:itemLogo="@drawable/ic_spinners_logo_24dp"
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
index 8b99e6a4..e0fae460 100644
--- a/input/autofill/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/input/autofill/AutofillFramework/afservice/build.gradle b/input/autofill/AutofillFramework/afservice/build.gradle
index 65020f48..f341b57b 100644
--- a/input/autofill/AutofillFramework/afservice/build.gradle
+++ b/input/autofill/AutofillFramework/afservice/build.gradle
@@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 27
+ compileSdkVersion 26
defaultConfig {
minSdkVersion 26
- targetSdkVersion 27
+ targetSdkVersion 26
versionCode 1
versionName "1.0"
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
index 595643ff..65ca2e57 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
@@ -32,6 +32,7 @@ import android.widget.EditText;
import android.widget.RemoteViews;
import android.widget.Toast;
+import com.example.android.autofill.service.data.ClientViewMetadataBuilder;
import com.example.android.autofill.service.data.DataCallback;
import com.example.android.autofill.service.data.adapter.DatasetAdapter;
import com.example.android.autofill.service.data.adapter.ResponseAdapter;
@@ -140,7 +141,8 @@ public class AuthActivity extends AppCompatActivity {
Bundle clientState = intent.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
StructureParser structureParser = new StructureParser(structure);
- mClientViewMetadata = new ClientViewMetadata(structureParser);
+ ClientViewMetadataBuilder builder = new ClientViewMetadataBuilder(structureParser);
+ mClientViewMetadata = builder.buildClientViewMetadata();
mDatasetAdapter = new DatasetAdapter(structureParser);
mResponseAdapter = new ResponseAdapter(this, mClientViewMetadata, mPackageName,
mDatasetAdapter, clientState);
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
index 956b5217..4012dbe2 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
@@ -36,6 +36,7 @@ import android.widget.RemoteViews;
import com.example.android.autofill.service.data.AutofillDataBuilder;
import com.example.android.autofill.service.data.ClientAutofillDataBuilder;
import com.example.android.autofill.service.data.ClientViewMetadata;
+import com.example.android.autofill.service.data.ClientViewMetadataBuilder;
import com.example.android.autofill.service.data.DataCallback;
import com.example.android.autofill.service.data.adapter.DatasetAdapter;
import com.example.android.autofill.service.data.adapter.ResponseAdapter;
@@ -95,7 +96,8 @@ public class MyAutofillService extends AutofillService {
.get(request.getFillContexts().size() - 1).getStructure();
StructureParser parser = new StructureParser(structure);
mDatasetAdapter = new DatasetAdapter(parser);
- mClientViewMetadata = new ClientViewMetadata(parser);
+ ClientViewMetadataBuilder clientViewMetadataBuilder = new ClientViewMetadataBuilder(parser);
+ mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
mResponseAdapter = new ResponseAdapter(this, mClientViewMetadata,
getPackageName(), mDatasetAdapter, request.getClientState());
String packageName = structure.getActivityComponent().getPackageName();
@@ -150,7 +152,8 @@ public class MyAutofillService extends AutofillService {
AssistStructure structure = fillContexts.get(size - 1).getStructure();
StructureParser parser = new StructureParser(structure);
mAutofillDataBuilder = new ClientAutofillDataBuilder(parser);
- mClientViewMetadata = new ClientViewMetadata(parser);
+ ClientViewMetadataBuilder clientViewMetadataBuilder = new ClientViewMetadataBuilder(parser);
+ mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
String packageName = structure.getActivityComponent().getPackageName();
if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
callback.onFailure(getString(R.string.invalid_package_signature));
@@ -203,8 +206,8 @@ public class MyAutofillService extends AutofillService {
private void checkWebDomainAndBuildAutofillData(String packageName, SaveCallback callback) {
String webDomain;
try {
- webDomain = mClientViewMetadata.buildWebDomain();
- } catch (SecurityException e) {
+ webDomain = mClientViewMetadata.getWebDomain();
+ } catch(SecurityException e) {
logw(e.getMessage());
callback.onFailure(getString(R.string.security_exception));
return;
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java
index 54296f36..3e6676d8 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java
@@ -57,7 +57,6 @@ public final class StructureParser {
}
}
-
public interface NodeProcessor {
void processNode(ViewNode node);
}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java
index abc128f8..24de40c1 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java
@@ -16,143 +16,96 @@
package com.example.android.autofill.service.data;
-import android.app.assist.AssistStructure;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.service.autofill.SaveInfo;
import android.view.autofill.AutofillId;
-import com.example.android.autofill.service.AutofillHints;
-import com.example.android.autofill.service.StructureParser;
-
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
-import static com.example.android.autofill.service.util.Util.logd;
-
/**
- * In this simple implementation, the only view data we parse from the client are autofill hints
- * of the views in the view hierarchy, the hints of views that are focused, the corresponding
- * autofill IDs, and the {@link SaveInfo} based on the hints.
- * <p>
- * Note: this class is not thread safe.
+ * In this simple implementation, the only view data we collect from the client are autofill hints
+ * of the views in the view hierarchy, the corresponding autofill IDs, and the {@link SaveInfo}
+ * based on the hints.
*/
-public class ClientViewMetadata {
- private final StructureParser mStructureParser;
-
- private List<String> mCachedAllHints;
- private Integer mCachedSaveType;
- private SaveInfo mCachedSaveInfo;
- private List<AutofillId> mCachedAutofillIds;
-
- public ClientViewMetadata(StructureParser parser) {
- mStructureParser = parser;
- }
+public class ClientViewMetadata implements Parcelable {
- public List<String> getAllHints() {
- if (mCachedAllHints == null) {
- parseHints();
+ public static final Creator<ClientViewMetadata> CREATOR = new Creator<ClientViewMetadata>() {
+ @Override
+ public ClientViewMetadata createFromParcel(Parcel parcel) {
+ return new ClientViewMetadata(parcel);
}
- return mCachedAllHints;
- }
-
- private List<AutofillId> getAutofillIds() {
- if (mCachedAutofillIds == null) {
- AutofillSaveType autofillSaveType = new AutofillSaveType();
- List<AutofillId> autofillIds = new ArrayList<>();
- mStructureParser.parse((node) -> parseSaveTypeAndIds(node, autofillSaveType, autofillIds));
- mCachedSaveType = autofillSaveType.saveType;
- mCachedAutofillIds = autofillIds;
- }
- return mCachedAutofillIds;
- }
- public AutofillId[] getAutofillIdsArray() {
- List<AutofillId> autofillIds = getAutofillIds();
- if (autofillIds == null || autofillIds.isEmpty()) {
- return null;
+ @Override
+ public ClientViewMetadata[] newArray(int size) {
+ return new ClientViewMetadata[size];
}
- return autofillIds.toArray(new AutofillId[autofillIds.size()]);
+ };
+
+ private final List<String> mAllHints;
+ private final int mSaveType;
+ private final AutofillId[] mAutofillIds;
+ private final String mWebDomain;
+
+ public ClientViewMetadata(List<String> allHints, int saveType, AutofillId[] autofillIds,
+ String webDomain) {
+ mAllHints = allHints;
+ mSaveType = saveType;
+ mAutofillIds = autofillIds;
+ mWebDomain = webDomain;
}
- public SaveInfo getSaveInfo() {
- if (mCachedSaveInfo == null) {
- int saveType = getSaveType();
- AutofillId[] autofillIdsArray = getAutofillIdsArray();
- if (autofillIdsArray == null || autofillIdsArray.length == 0) {
- return null;
- }
- // TODO: on MR1, creates a new SaveType without required ids
- mCachedSaveInfo = new SaveInfo.Builder(saveType, autofillIdsArray).build();
+ private ClientViewMetadata(Parcel parcel) {
+ mAllHints = new ArrayList<>();
+ parcel.readList(mAllHints, String.class.getClassLoader());
+ mSaveType = parcel.readInt();
+ Parcelable[] ids = parcel.readParcelableArray(AutofillId.class.getClassLoader());
+ if (ids != null && ids.length > 0) {
+ mAutofillIds = Arrays.copyOf(ids, ids.length, AutofillId[].class);
+ } else {
+ mAutofillIds = null;
}
- return mCachedSaveInfo;
+ mWebDomain = parcel.readString();
}
- public int getSaveType() {
- if (mCachedSaveType == null) {
- AutofillSaveType autofillSaveType = new AutofillSaveType();
- List<AutofillId> autofillIds = new ArrayList<>();
- mStructureParser.parse((node) -> parseSaveTypeAndIds(node, autofillSaveType, autofillIds));
- mCachedSaveType = autofillSaveType.saveType;
- mCachedAutofillIds = autofillIds;
- }
- return mCachedSaveType;
+ public List<String> getAllHints() {
+ return mAllHints;
}
- public String buildWebDomain() {
- StringBuilder webDomainBuilder = new StringBuilder();
- mStructureParser.parse((node) -> parseWebDomain(node, webDomainBuilder));
- return webDomainBuilder.toString();
+ public AutofillId[] getAutofillIds() {
+ return mAutofillIds;
}
- private void parseWebDomain(AssistStructure.ViewNode viewNode, StringBuilder validWebDomain) {
- String webDomain = viewNode.getWebDomain();
- if (webDomain != null) {
- logd("child web domain: %s", webDomain);
- if (validWebDomain.length() > 0) {
- if (!webDomain.equals(validWebDomain.toString())) {
- throw new SecurityException("Found multiple web domains: valid= "
- + validWebDomain + ", child=" + webDomain);
- }
- } else {
- validWebDomain.append(webDomain);
- }
- }
- }
-
- private void parseSaveTypeAndIds(AssistStructure.ViewNode root,
- AutofillSaveType autofillSaveType, List<AutofillId> autofillIds) {
- String[] hints = root.getAutofillHints();
- if (hints != null) {
- for (String hint : hints) {
- if (AutofillHints.isValidHint(hint)) {
- autofillSaveType.saveType |= AutofillHints.getSaveTypeForHint(hint);
- autofillIds.add(root.getAutofillId());
- }
- }
- }
+ public int getSaveType() {
+ return mSaveType;
}
- private void parseHints() {
- List<String> allHints = new ArrayList<>();
- mStructureParser.parse((node) -> getHints(node, allHints));
- mCachedAllHints = allHints;
+ public String getWebDomain() {
+ return mWebDomain;
}
- private void getHints(AssistStructure.ViewNode node, List<String> allHints) {
- if (node.getAutofillHints() != null) {
- String[] hints = node.getAutofillHints();
- Collections.addAll(allHints, hints);
- }
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeList(mAllHints);
+ parcel.writeInt(mSaveType);
+ parcel.writeParcelableArray(mAutofillIds, 0);
+ parcel.writeString(mWebDomain);
}
- public void clearCache() {
- mCachedAllHints = null;
- mCachedSaveType = null;
- mCachedSaveInfo = null;
- mCachedAutofillIds = null;
+ @Override
+ public int describeContents() {
+ return 0;
}
- private class AutofillSaveType {
- int saveType;
+ @Override
+ public String toString() {
+ return "ClientViewMetadata{" +
+ "mAllHints=" + mAllHints +
+ ", mSaveType=" + mSaveType +
+ ", mAutofillIds=" + Arrays.toString(mAutofillIds) +
+ ", mWebDomain='" + mWebDomain + '\'' +
+ '}';
}
}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadataBuilder.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadataBuilder.java
new file mode 100644
index 00000000..394cd72d
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadataBuilder.java
@@ -0,0 +1,79 @@
+/*
+ * 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.example.android.autofill.service.data;
+
+
+import android.app.assist.AssistStructure;
+import android.util.MutableInt;
+import android.view.autofill.AutofillId;
+
+import com.example.android.autofill.service.AutofillHints;
+import com.example.android.autofill.service.StructureParser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.example.android.autofill.service.util.Util.logd;
+
+public class ClientViewMetadataBuilder {
+ private StructureParser mStructureParser;
+
+ public ClientViewMetadataBuilder(StructureParser parser) {
+ mStructureParser = parser;
+ }
+
+ public ClientViewMetadata buildClientViewMetadata() {
+ List<String> allHints = new ArrayList<>();
+ MutableInt saveType = new MutableInt(0);
+ List<AutofillId> autofillIds = new ArrayList<>();
+ StringBuilder webDomainBuilder = new StringBuilder();
+ mStructureParser.parse((node) -> parseNode(node, allHints, saveType, autofillIds));
+ mStructureParser.parse((node) -> parseWebDomain(node, webDomainBuilder));
+ String webDomain = webDomainBuilder.toString();
+ AutofillId[] autofillIdsArray = autofillIds.toArray(new AutofillId[autofillIds.size()]);
+ return new ClientViewMetadata(allHints, saveType.value, autofillIdsArray, webDomain);
+ }
+
+ private void parseWebDomain(AssistStructure.ViewNode viewNode, StringBuilder validWebDomain) {
+ String webDomain = viewNode.getWebDomain();
+ if (webDomain != null) {
+ logd("child web domain: %s", webDomain);
+ if (validWebDomain.length() > 0) {
+ if (!webDomain.equals(validWebDomain.toString())) {
+ throw new SecurityException("Found multiple web domains: valid= "
+ + validWebDomain + ", child=" + webDomain);
+ }
+ } else {
+ validWebDomain.append(webDomain);
+ }
+ }
+ }
+
+ private void parseNode(AssistStructure.ViewNode root, List<String> allHints,
+ MutableInt autofillSaveType, List<AutofillId> autofillIds) {
+ String[] hints = root.getAutofillHints();
+ if (hints != null) {
+ for (String hint : hints) {
+ if (AutofillHints.isValidHint(hint)) {
+ allHints.add(hint);
+ autofillSaveType.value |= AutofillHints.getSaveTypeForHint(hint);
+ autofillIds.add(root.getAutofillId());
+ }
+ }
+ }
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java
index 39ebf702..974288d2 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java
@@ -22,7 +22,6 @@ import android.os.Bundle;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
-import android.view.View;
import android.view.autofill.AutofillId;
import android.widget.RemoteViews;
@@ -31,24 +30,21 @@ import com.example.android.autofill.service.RemoteViewsHelper;
import com.example.android.autofill.service.data.ClientViewMetadata;
import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
-import static com.example.android.autofill.service.util.Util.bundleToString;
-import static com.example.android.autofill.service.util.Util.getSaveTypeAsString;
-import static com.example.android.autofill.service.util.Util.logDebugEnabled;
import static com.example.android.autofill.service.util.Util.logd;
public class ResponseAdapter {
public static final String CLIENT_STATE_PARTIAL_ID_TEMPLATE = "partial-%s";
// TODO: move to settings activity and document it
private static final boolean SUPPORT_MULTIPLE_STEPS = true;
-
+ static int pageno = 0;
private final Context mContext;
private final DatasetAdapter mDatasetAdapter;
private final String mPackageName;
private final ClientViewMetadata mClientViewMetadata;
- private final Bundle mPreviousClientState;
+ private final List<ClientViewMetadata> mPreviousClientViewMetadatas;
public ResponseAdapter(Context context, ClientViewMetadata clientViewMetadata,
String packageName, DatasetAdapter datasetAdapter, Bundle clientState) {
@@ -56,7 +52,15 @@ public class ResponseAdapter {
mClientViewMetadata = clientViewMetadata;
mDatasetAdapter = datasetAdapter;
mPackageName = packageName;
- mPreviousClientState = clientState;
+ mPreviousClientViewMetadatas = new ArrayList<>();
+ if (clientState != null) {
+ clientState.setClassLoader(getClass().getClassLoader());
+ for (int i = pageno - 1; i >= 0; i--) {
+ ClientViewMetadata previousPage = clientState.getParcelable("client-" + (pageno - 1));
+ mPreviousClientViewMetadatas.add(previousPage);
+ }
+ logd("previous client state == " + mPreviousClientViewMetadatas);
+ }
}
/**
@@ -91,74 +95,77 @@ public class ResponseAdapter {
}
}
}
-
+ Bundle clientState = new Bundle();
+ clientState.putParcelable("client-" + (pageno++), mClientViewMetadata);
int saveType = mClientViewMetadata.getSaveType();
- AutofillId[] autofillIds = mClientViewMetadata.getAutofillIdsArray();
- List<String> allHints = mClientViewMetadata.getAllHints();
- if (logDebugEnabled()) {
- logd("setPartialSaveInfo() for type %s: allHints=%s, ids=%s, clientState=%s",
- getSaveTypeAsString(saveType), allHints, Arrays.toString(autofillIds),
- bundleToString(mPreviousClientState));
- }
- // TODO: this should be more generic, but for now it's hardcode to support just activities
- // that have an username and a password in separate steps (like MultipleStepsSigninActivity)
- if ((saveType != SaveInfo.SAVE_DATA_TYPE_USERNAME
- && saveType != SaveInfo.SAVE_DATA_TYPE_PASSWORD)
- || autofillIds.length != 1 || allHints.size() != 1) {
- logd("Unsupported activity for partial info; returning full");
- SaveInfo saveInfo = mClientViewMetadata.getSaveInfo();
- if (saveInfo != null) {
- responseBuilder.setSaveInfo(mClientViewMetadata.getSaveInfo());
- return responseBuilder.build();
- } else {
- return null;
- }
- }
- int previousSaveType;
- String previousHint;
- if (saveType == SaveInfo.SAVE_DATA_TYPE_PASSWORD) {
- previousHint = View.AUTOFILL_HINT_USERNAME;
- previousSaveType = SaveInfo.SAVE_DATA_TYPE_USERNAME;
- } else {
- previousHint = View.AUTOFILL_HINT_PASSWORD;
- previousSaveType = SaveInfo.SAVE_DATA_TYPE_PASSWORD;
- }
- String previousKey = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, previousHint);
-
- AutofillId previousValue = mPreviousClientState == null ? null : mPreviousClientState
- .getParcelable(previousKey);
- logd("previous: %s=%s", previousKey, previousValue);
-
- Bundle newClientState = new Bundle();
- String key = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, allHints.get(0));
- AutofillId value = autofillIds[0];
- logd("New client state: %s = %s", key, value);
- newClientState.putParcelable(key, value);
-
- if (previousValue != null) {
- AutofillId[] newIds = new AutofillId[]{previousValue, value};
- int newSaveType = saveType | previousSaveType;
- logd("new values: type=%s, ids=%s",
- getSaveTypeAsString(newSaveType), Arrays.toString(newIds));
- newClientState.putAll(mPreviousClientState);
- responseBuilder.setSaveInfo(new SaveInfo.Builder(newSaveType, newIds)
- .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
- .build())
- .setClientState(newClientState);
-
- return responseBuilder.build();
- }
- responseBuilder.setClientState(newClientState);
- responseBuilder.setSaveInfo(mClientViewMetadata.getSaveInfo());
+ AutofillId[] autofillIds = mClientViewMetadata.getAutofillIds();
+ SaveInfo saveInfo = new SaveInfo.Builder(saveType, autofillIds).build();
+ responseBuilder.setSaveInfo(saveInfo);
+ responseBuilder.setClientState(clientState);
return responseBuilder.build();
+// int saveType = mClientViewMetadata.getSaveType();
+// AutofillId[] autofillIds = mClientViewMetadata.getAutofillIds();
+// List<String> allHints = mClientViewMetadata.getAllHints();
+// if (logDebugEnabled()) {
+// logd("setPartialSaveInfo() for type %s: allHints=%s, ids=%s, clientState=%s",
+// getSaveTypeAsString(saveType), allHints, Arrays.toString(autofillIds),
+// bundleToString(mPreviousClientState));
+// }
+// // TODO: this should be more generic, but for now it's hardcode to support just activities
+// // that have an username and a password in separate steps (like MultipleStepsSigninActivity)
+// if ((saveType != SaveInfo.SAVE_DATA_TYPE_USERNAME
+// && saveType != SaveInfo.SAVE_DATA_TYPE_PASSWORD)
+// || autofillIds.length != 1 || allHints.size() != 1) {
+// logd("Unsupported activity for partial info; returning full");
+// responseBuilder.setSaveInfo(mClientViewMetadata.getSaveInfo());
+// return responseBuilder.build();
+// }
+// int previousSaveType;
+// String previousHint;
+// if (saveType == SaveInfo.SAVE_DATA_TYPE_PASSWORD) {
+// previousHint = View.AUTOFILL_HINT_USERNAME;
+// previousSaveType = SaveInfo.SAVE_DATA_TYPE_USERNAME;
+// } else {
+// previousHint = View.AUTOFILL_HINT_PASSWORD;
+// previousSaveType = SaveInfo.SAVE_DATA_TYPE_PASSWORD;
+// }
+// String previousKey = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, previousHint);
+//
+// AutofillId previousValue = mPreviousClientState == null ? null : mPreviousClientState
+// .getParcelable(previousKey);
+// logd("previous: %s=%s", previousKey, previousValue);
+//
+// Bundle newClientState = new Bundle();
+// String key = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, allHints.get(0));
+// AutofillId value = autofillIds[0];
+// logd("New client state: %s = %s", key, value);
+// newClientState.putParcelable(key, value);
+//
+// if (previousValue != null) {
+// AutofillId[] newIds = new AutofillId[]{previousValue, value};
+// int newSaveType = saveType | previousSaveType;
+// logd("new values: type=%s, ids=%s",
+// getSaveTypeAsString(newSaveType), Arrays.toString(newIds));
+// newClientState.putAll(mPreviousClientState);
+// responseBuilder.setSaveInfo(new SaveInfo.Builder(newSaveType, newIds)
+// .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+// .build())
+// .setClientState(newClientState);
+//
+// return responseBuilder.build();
+// }
+// responseBuilder.setClientState(newClientState);
+// responseBuilder.setSaveInfo(mClientViewMetadata.getSaveInfo());
+// return responseBuilder.build();
}
public FillResponse buildResponse(IntentSender sender, RemoteViews remoteViews) {
FillResponse.Builder responseBuilder = new FillResponse.Builder();
- AutofillId[] autofillIds = mClientViewMetadata.getAutofillIdsArray();
- SaveInfo saveInfo = mClientViewMetadata.getSaveInfo();
- responseBuilder.setAuthentication(autofillIds, sender, remoteViews);
+ int saveType = mClientViewMetadata.getSaveType();
+ AutofillId[] autofillIds = mClientViewMetadata.getAutofillIds();
+ SaveInfo saveInfo = new SaveInfo.Builder(saveType, autofillIds).build();
responseBuilder.setSaveInfo(saveInfo);
+ responseBuilder.setAuthentication(autofillIds, sender, remoteViews);
return responseBuilder.build();
}
}