aboutsummaryrefslogtreecommitdiff
path: root/input/autofill
diff options
context:
space:
mode:
authorDouglas Sigelbaum <sigelbaum@google.com>2017-11-20 21:31:01 -0800
committerDouglas Sigelbaum <sigelbaum@google.com>2017-12-12 11:33:12 -0800
commitacb2cfd0dc0c23cb503cf62e610522862e887a5e (patch)
treea5a8d45d510436be76803717b445469a5d8a07e4 /input/autofill
parent1d98b1ebf59343c868a430be5fc68020c2b985d4 (diff)
downloadandroid-acb2cfd0dc0c23cb503cf62e610522862e887a5e.tar.gz
Refactoring AssistStructure parsing and models.
Bug: 69441672 Test: still manual Change-Id: I0d7b098f7e3e8bbb728e72016bf26b33dd439293
Diffstat (limited to 'input/autofill')
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/edgecases/MultiplePartitionsActivity.java12
-rw-r--r--input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/AutofillDaoTest.java (renamed from input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/datasource/local/AutofillDaoTest.java)67
-rw-r--r--input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/LocalDataSourceTest.java64
-rw-r--r--input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/util/SingleExecutors.java30
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java104
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java83
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java74
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java197
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java6
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java375
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java156
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/RemoteViewsHelper.java44
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java153
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/AutofillDataBuilder.java25
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientAutofillDataBuilder.java157
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java155
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/DataCallback.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DataCallback.java)2
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/FakeAutofillDataBuilder.java63
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/DatasetAdapter.java167
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java159
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/AutofillDataSource.java50
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DalService.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DalService.java)3
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DigitalAssetLinksDataSource.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java)7
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/PackageVerificationDataSource.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java)2
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/DigitalAssetLinksRepository.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/DigitalAssetLinksRepository.java)29
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/LocalAutofillDataSource.java148
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/SharedPrefsPackageVerificationRepository.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/SharedPrefsPackageVerificationRepository.java)6
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/dao/AutofillDao.java71
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/db/AutofillDatabase.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/db/AutofillDatabase.java)4
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java43
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/LocalAutofillDataSource.java121
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/dao/AutofillDao.java98
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/AutofillDataset.java6
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DalInfo.java2
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DatasetWithFilledAutofillFields.java60
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java85
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java138
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java47
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/SecurityHelper.java (renamed from input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java)5
-rw-r--r--input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/Util.java7
40 files changed, 1633 insertions, 1392 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 23131602..3f4031ce 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
@@ -15,7 +15,6 @@
*/
package com.example.android.autofill.app.edgecases;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
@@ -104,13 +103,10 @@ public class MultiplePartitionsActivity extends AppCompatActivity {
getString(R.string.credit_card_security_code_label),
" ", true, View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
- findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- resetFields();
- mCustomVirtualView.resetPositions();
- mAutofillManager.cancel();
- }
+ findViewById(R.id.clear).setOnClickListener((view) -> {
+ resetFields();
+ mCustomVirtualView.resetPositions();
+ mAutofillManager.cancel();
});
mAutofillManager = getSystemService(AutofillManager.class);
}
diff --git a/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/datasource/local/AutofillDaoTest.java b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/AutofillDaoTest.java
index c24e2720..dc62a298 100644
--- a/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/datasource/local/AutofillDaoTest.java
+++ b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/AutofillDaoTest.java
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource.local;
+package com.example.android.autofill.service.data.source.local;
import android.arch.persistence.room.Room;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import com.example.android.autofill.service.datasource.local.dao.AutofillDao;
-import com.example.android.autofill.service.datasource.local.db.AutofillDatabase;
+import com.example.android.autofill.service.data.source.local.db.AutofillDatabase;
import com.example.android.autofill.service.model.AutofillDataset;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
import com.example.android.autofill.service.model.FilledAutofillField;
import com.google.common.collect.ImmutableList;
@@ -32,13 +32,12 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
-import java.util.Comparator;
import java.util.List;
import java.util.UUID;
-import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.hasSize;
@RunWith(AndroidJUnit4.class)
public class AutofillDaoTest {
@@ -49,15 +48,10 @@ public class AutofillDaoTest {
private final FilledAutofillField mPasswordField =
new FilledAutofillField(mDataset.getId(), View.AUTOFILL_HINT_PASSWORD, "password");
- private List<FilledAutofillField> mAutofillFields;
private AutofillDatabase mDatabase;
@Before
public void setup() {
- mAutofillFields = new ArrayList<>();
- mAutofillFields.add(mUsernameField);
- mAutofillFields.add(mPasswordField);
-
// using an in-memory database because the information stored here disappears when the
// process is killed
mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
@@ -72,50 +66,23 @@ public class AutofillDaoTest {
@Test
public void insertFilledAutofillFieldAndGet() {
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields =
+ new DatasetWithFilledAutofillFields();
+ datasetWithFilledAutofillFields.autofillDataset = mDataset;
+ datasetWithFilledAutofillFields.filledAutofillFields =
+ ImmutableList.of(mUsernameField, mPasswordField);
+
// When inserting a page's autofill fields.
mDatabase.autofillDao().saveAutofillDataset(mDataset);
- mDatabase.autofillDao().saveFilledAutofillFields(mAutofillFields);
+ mDatabase.autofillDao().saveFilledAutofillFields(
+ datasetWithFilledAutofillFields.filledAutofillFields);
// Represents all hints of all fields on page.
List<String> allHints = ImmutableList.of(View.AUTOFILL_HINT_USERNAME,
View.AUTOFILL_HINT_PASSWORD);
-
- // When loading the autofill fields we just saved, while focused on 'username'.
- List<String> usernameFocusedHints = ImmutableList.of(View.AUTOFILL_HINT_USERNAME);
- List<AutofillDao.AutofillDatasetField> loadedOnUsername = mDatabase.autofillDao()
- .getFilledAutofillFields(usernameFocusedHints, allHints);
-
- // When loading the autofill fields, while focused on 'password'.
- List<String> passwordFocusedHints = ImmutableList.of(View.AUTOFILL_HINT_PASSWORD);
-
- List<AutofillDao.AutofillDatasetField> loadedOnPassword = mDatabase.autofillDao()
- .getFilledAutofillFields(passwordFocusedHints, allHints);
-
- AutofillDatasetFieldComparator comparator = new AutofillDatasetFieldComparator();
- loadedOnPassword.sort(comparator);
- loadedOnUsername.sort(comparator);
- assertThat(loadedOnUsername, is(loadedOnPassword));
- }
-
- private class AutofillDatasetFieldComparator implements
- Comparator<AutofillDao.AutofillDatasetField> {
- @Override
- public int compare(AutofillDao.AutofillDatasetField o1,
- AutofillDao.AutofillDatasetField o2) {
- if (o1 == null) {
- return -1;
- } else if (o2 == null) {
- return 1;
- }
-
- int first = o1.filledAutofillField.getHint().compareTo(
- o2.filledAutofillField.getHint());
- if (first == 0) {
- return o1.filledAutofillField.getDatasetId().compareTo(
- o2.filledAutofillField.getDatasetId());
- } else {
- return first;
- }
- }
+ List<DatasetWithFilledAutofillFields> loadedDatasets = mDatabase.autofillDao()
+ .getFilledAutofillFields(allHints);
+ assertThat(loadedDatasets, contains(datasetWithFilledAutofillFields));
+ assertThat(loadedDatasets, hasSize(1));
}
}
diff --git a/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/LocalDataSourceTest.java b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/LocalDataSourceTest.java
new file mode 100644
index 00000000..2f445c54
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/data/source/local/LocalDataSourceTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.source.local;
+
+import android.arch.persistence.room.Room;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
+import com.example.android.autofill.service.data.source.local.db.AutofillDatabase;
+import com.example.android.autofill.service.util.SingleExecutors;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class LocalDataSourceTest {
+
+ private LocalAutofillDataSource mLocalDataSource;
+ private AutofillDatabase mDatabase;
+
+ @Before
+ public void setup() {
+ // using an in-memory database for testing, since it doesn't survive killing the process
+ mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
+ AutofillDatabase.class)
+ .build();
+ AutofillDao tasksDao = mDatabase.autofillDao();
+ SharedPreferences sharedPreferences = InstrumentationRegistry.getContext()
+ .getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ // Make sure that we're not keeping a reference to the wrong instance.
+ LocalAutofillDataSource.clearInstance();
+ mLocalDataSource = LocalAutofillDataSource.getInstance(sharedPreferences,
+ tasksDao, new SingleExecutors());
+ }
+
+ @After
+ public void cleanUp() {
+ try {
+ mDatabase.close();
+ } finally {
+ LocalAutofillDataSource.clearInstance();
+ }
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/util/SingleExecutors.java b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/util/SingleExecutors.java
new file mode 100644
index 00000000..baac2b19
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/androidTest/java/com/example/android/autofill/service/util/SingleExecutors.java
@@ -0,0 +1,30 @@
+/*
+ * 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.util;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Allow instant execution of tasks.
+ */
+public final class SingleExecutors extends AppExecutors {
+ private static Executor sInstance = Runnable::run;
+
+ public SingleExecutors() {
+ super(sInstance, sInstance, sInstance);
+ }
+} \ No newline at end of file
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 9f526fb3..710bb42f 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
@@ -20,6 +20,7 @@ import android.app.assist.AssistStructure;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
@@ -28,16 +29,22 @@ import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.view.autofill.AutofillManager;
import android.widget.EditText;
+import android.widget.RemoteViews;
import android.widget.Toast;
-import com.example.android.autofill.service.datasource.DataCallback;
-import com.example.android.autofill.service.datasource.local.DigitalAssetLinksRepository;
-import com.example.android.autofill.service.datasource.local.LocalAutofillDataSource;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+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;
+import com.example.android.autofill.service.data.ClientViewMetadata;
+import com.example.android.autofill.service.data.source.local.DigitalAssetLinksRepository;
+import com.example.android.autofill.service.data.source.local.LocalAutofillDataSource;
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
+import com.example.android.autofill.service.data.source.local.db.AutofillDatabase;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
import com.example.android.autofill.service.settings.MyPreferences;
import com.example.android.autofill.service.util.AppExecutors;
-import java.util.HashMap;
+import java.util.List;
import static android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE;
import static android.view.autofill.AutofillManager.EXTRA_AUTHENTICATION_RESULT;
@@ -59,19 +66,24 @@ public class AuthActivity extends AppCompatActivity {
private LocalAutofillDataSource mLocalAutofillDataSource;
private DigitalAssetLinksRepository mDalRepository;
private EditText mMasterPassword;
+ private DatasetAdapter mDatasetAdapter;
+ private ResponseAdapter mResponseAdapter;
+ private ClientViewMetadata mClientViewMetadata;
+ private String mPackageName;
private Intent mReplyIntent;
- static IntentSender getAuthIntentSenderForResponse(Context context) {
+ public static IntentSender getAuthIntentSenderForResponse(Context context) {
final Intent intent = new Intent(context, AuthActivity.class);
- return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
- .getIntentSender();
+ return PendingIntent.getActivity(context, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
}
- static IntentSender getAuthIntentSenderForDataset(Context context, String datasetName) {
- final Intent intent = new Intent(context, AuthActivity.class);
+ public static IntentSender getAuthIntentSenderForDataset(Context originContext,
+ String datasetName) {
+ Intent intent = new Intent(originContext, AuthActivity.class);
intent.putExtra(EXTRA_DATASET_NAME, datasetName);
intent.putExtra(EXTRA_FOR_RESPONSE, false);
- return PendingIntent.getActivity(context, ++sDatasetPendingIntentId, intent,
+ return PendingIntent.getActivity(originContext, ++sDatasetPendingIntentId, intent,
PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
}
@@ -79,10 +91,14 @@ public class AuthActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multidataset_service_auth_activity);
- mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(this,
- new AppExecutors());
- mDalRepository = DigitalAssetLinksRepository.getInstance(this);
+ SharedPreferences sharedPreferences =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ AutofillDao autofillDao = AutofillDatabase.getInstance(this).autofillDao();
+ mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(sharedPreferences,
+ autofillDao, new AppExecutors());
+ mDalRepository = DigitalAssetLinksRepository.getInstance(getPackageManager());
mMasterPassword = findViewById(R.id.master_password);
+ mPackageName = getPackageName();
findViewById(R.id.login).setOnClickListener((view) -> login());
findViewById(R.id.cancel).setOnClickListener((view) -> {
onFailure();
@@ -92,8 +108,8 @@ public class AuthActivity extends AppCompatActivity {
private void login() {
Editable password = mMasterPassword.getText();
- if (password.toString()
- .equals(MyPreferences.getInstance(AuthActivity.this).getMasterPassword())) {
+ String correctPassword = MyPreferences.getInstance(AuthActivity.this).getMasterPassword();
+ if (password.toString().equals(correctPassword)) {
onSuccess();
} else {
Toast.makeText(this, "Password incorrect", Toast.LENGTH_SHORT).show();
@@ -122,29 +138,45 @@ public class AuthActivity extends AppCompatActivity {
boolean forResponse = intent.getBooleanExtra(EXTRA_FOR_RESPONSE, true);
Bundle clientState = intent.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
- StructureParser parser = new StructureParser(getApplicationContext(), structure,
- mLocalAutofillDataSource, mDalRepository);
- parser.parseForFill();
- AutofillFieldMetadataCollection autofillFields = parser.getAutofillFields();
- int saveTypes = autofillFields.getSaveType();
+ StructureParser structureParser = new StructureParser(structure);
+ mClientViewMetadata = new ClientViewMetadata(structureParser);
+ mDatasetAdapter = new DatasetAdapter(structureParser);
+ mResponseAdapter = new ResponseAdapter(this, mClientViewMetadata, mPackageName,
+ mDatasetAdapter, clientState);
mReplyIntent = new Intent();
+ if (forResponse) {
+ fetchAllDatasetsAndSetIntent();
+ } else {
+ String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
+ fetchDatasetAndSetIntent(datasetName);
+ }
+ }
+
+ private void fetchDatasetAndSetIntent(String datasetName) {
+ mLocalAutofillDataSource.getAutofillDataset(mClientViewMetadata.getAllHints(),
+ datasetName, new DataCallback<DatasetWithFilledAutofillFields>() {
+ @Override
+ public void onLoaded(DatasetWithFilledAutofillFields dataset) {
+ String datasetName = dataset.autofillDataset.getDatasetName();
+ RemoteViews remoteViews = RemoteViewsHelper.viewsWithNoAuth(
+ mPackageName, datasetName);
+ setDatasetIntent(mDatasetAdapter.buildDataset(dataset, remoteViews));
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ }
+ });
+ }
- mLocalAutofillDataSource.getFilledAutofillFieldCollection(
- autofillFields.getFocusedHints(), autofillFields.getAllHints(),
- new DataCallback<HashMap<String, FilledAutofillFieldCollection>>() {
+ private void fetchAllDatasetsAndSetIntent() {
+ mLocalAutofillDataSource.getAutofillDatasets(mClientViewMetadata.getAllHints(),
+ new DataCallback<List<DatasetWithFilledAutofillFields>>() {
@Override
- public void onLoaded(HashMap<String, FilledAutofillFieldCollection>
- clientFormDataMap) {
- if (forResponse) {
- setResponseIntent(AutofillHelper.newResponse
- (AuthActivity.this, clientState, false,
- autofillFields, clientFormDataMap));
- } else {
- String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
- setDatasetIntent(AutofillHelper.newDataset
- (AuthActivity.this, autofillFields,
- clientFormDataMap.get(datasetName), false));
- }
+ public void onLoaded(List<DatasetWithFilledAutofillFields> datasets) {
+ FillResponse fillResponse = mResponseAdapter.buildResponse(datasets, false);
+ setResponseIntent(fillResponse);
}
@Override
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java
deleted file mode 100644
index ab15e3f1..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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;
-
-import android.app.assist.AssistStructure.ViewNode;
-import android.view.autofill.AutofillId;
-
-/**
- * A stripped down version of a {@link ViewNode} that contains only autofill-relevant metadata. It
- * also contains a {@code mSaveType} flag that is calculated based on the {@link ViewNode}]'s
- * autofill hints.
- */
-public class AutofillFieldMetadata {
- private int mSaveType = 0;
- private String[] mAutofillHints;
- private AutofillId mAutofillId;
- private int mAutofillType;
- private CharSequence[] mAutofillOptions;
- private boolean mFocused;
-
- public AutofillFieldMetadata(ViewNode view) {
- mAutofillId = view.getAutofillId();
- mAutofillType = view.getAutofillType();
- mAutofillOptions = view.getAutofillOptions();
- mFocused = view.isFocused();
- String[] hints = AutofillHints.filterForSupportedHints(view.getAutofillHints());
- if (hints != null) {
- AutofillHints.convertToStoredHintNames(hints);
- setHints(hints);
- }
- }
-
- public String[] getHints() {
- return mAutofillHints;
- }
-
- public void setHints(String[] hints) {
- mAutofillHints = hints;
- mSaveType = AutofillHints.getSaveTypeForHints(hints);
- }
-
- public int getSaveType() {
- return mSaveType;
- }
-
- public AutofillId getId() {
- return mAutofillId;
- }
-
- public int getAutofillType() {
- return mAutofillType;
- }
-
- /**
- * When the {@link ViewNode} is a list that the user needs to choose a string from (i.e. a
- * spinner), this is called to return the index of a specific item in the list.
- */
- public int getAutofillOptionIndex(String value) {
- for (int i = 0; i < mAutofillOptions.length; i++) {
- if (mAutofillOptions[i].toString().equals(value)) {
- return i;
- }
- }
- return -1;
- }
-
- public boolean isFocused() {
- return mFocused;
- }
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java
deleted file mode 100644
index d343ff2f..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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;
-
-import android.view.autofill.AutofillId;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Data structure that stores a collection of {@code AutofillFieldMetadata}s. Contains all of the
- * client's {@code View} hierarchy autofill-relevant metadata.
- */
-public final class AutofillFieldMetadataCollection {
-
- private final List<AutofillId> mAutofillIds = new ArrayList<>();
- private final HashMap<String, List<AutofillFieldMetadata>> mAutofillHintsToFieldsMap = new HashMap<>();
- private final List<String> mAllAutofillHints = new ArrayList<>();
- private final List<String> mFocusedAutofillHints = new ArrayList<>();
- private int mSize = 0;
- private int mSaveType = 0;
-
- public void add(AutofillFieldMetadata autofillFieldMetadata) {
- mSaveType |= autofillFieldMetadata.getSaveType();
- mSize++;
- mAutofillIds.add(autofillFieldMetadata.getId());
- List<String> hintsList = Arrays.asList(autofillFieldMetadata.getHints());
- mAllAutofillHints.addAll(hintsList);
- if (autofillFieldMetadata.isFocused()) {
- mFocusedAutofillHints.addAll(hintsList);
- }
- for (String hint : autofillFieldMetadata.getHints()) {
- if (!mAutofillHintsToFieldsMap.containsKey(hint)) {
- mAutofillHintsToFieldsMap.put(hint, new ArrayList<>());
- }
- mAutofillHintsToFieldsMap.get(hint).add(autofillFieldMetadata);
- }
- }
-
- public int getSaveType() {
- return mSaveType;
- }
-
- public AutofillId[] getAutofillIds() {
- return mAutofillIds.toArray(new AutofillId[mSize]);
- }
-
- public List<AutofillFieldMetadata> getFieldsForHint(String hint) {
- return mAutofillHintsToFieldsMap.get(hint);
- }
-
- public List<String> getFocusedHints() {
- return mFocusedAutofillHints;
- }
-
- public List<String> getAllHints() {
- return mAllAutofillHints;
- }
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java
deleted file mode 100644
index 6005aff4..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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;
-
-import android.content.Context;
-import android.content.IntentSender;
-import android.os.Bundle;
-import android.service.autofill.Dataset;
-import android.service.autofill.FillResponse;
-import android.service.autofill.SaveInfo;
-import android.support.annotation.DrawableRes;
-import android.view.View;
-import android.view.autofill.AutofillId;
-import android.widget.RemoteViews;
-
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-import com.example.android.autofill.service.util.Util;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-
-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.logd;
-
-/**
- * This is a class containing helper methods for building Autofill Datasets and Responses.
- */
-public final class AutofillHelper {
-
- 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;
-
- private AutofillHelper() {
- throw new UnsupportedOperationException("provide static methods only");
- }
-
- /**
- * Wraps autofill data in a LoginCredential Dataset object which can then be sent back to the
- * client View.
- */
- public static Dataset newDataset(Context context,
- AutofillFieldMetadataCollection autofillFields,
- FilledAutofillFieldCollection filledAutofillFieldCollection, boolean datasetAuth) {
- String datasetName = filledAutofillFieldCollection.getDataset().getDatasetName();
- Dataset.Builder datasetBuilder;
- if (datasetAuth) {
- datasetBuilder = new Dataset.Builder
- (newRemoteViews(context.getPackageName(), datasetName,
- R.drawable.ic_lock_black_24dp));
- IntentSender sender =
- AuthActivity.getAuthIntentSenderForDataset(context, datasetName);
- datasetBuilder.setAuthentication(sender);
- } else {
- datasetBuilder = new Dataset.Builder
- (newRemoteViews(context.getPackageName(), datasetName,
- R.drawable.ic_person_black_24dp));
- }
- boolean setValueAtLeastOnce =
- filledAutofillFieldCollection.applyToFields(autofillFields, datasetBuilder);
- if (setValueAtLeastOnce) {
- return datasetBuilder.build();
- }
- return null;
- }
-
- public static RemoteViews newRemoteViews(String packageName, String remoteViewsText,
- @DrawableRes int drawableId) {
- RemoteViews presentation =
- new RemoteViews(packageName, R.layout.multidataset_service_list_item);
- presentation.setTextViewText(R.id.text, remoteViewsText);
- presentation.setImageViewResource(R.id.icon, drawableId);
- return presentation;
- }
-
- /**
- * Wraps autofill data in a Response object (essentially a series of Datasets) which can then
- * be sent back to the client View.
- */
- public static FillResponse newResponse(Context context, Bundle previousClientState,
- boolean datasetAuth, AutofillFieldMetadataCollection autofillFields,
- HashMap<String, FilledAutofillFieldCollection> clientFormDataMap) {
- FillResponse.Builder responseBuilder = new FillResponse.Builder();
- if (clientFormDataMap != null) {
- Set<String> datasetNames = clientFormDataMap.keySet();
- for (String datasetName : datasetNames) {
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- clientFormDataMap.get(datasetName);
- if (filledAutofillFieldCollection != null) {
- Dataset dataset = newDataset(context, autofillFields,
- filledAutofillFieldCollection, datasetAuth);
- if (dataset != null) {
- responseBuilder.addDataset(dataset);
- }
- }
- }
- }
- int saveType = autofillFields.getSaveType();
- if (saveType != 0) {
- if (SUPPORT_MULTIPLE_STEPS) {
- setPartialSaveInfo(responseBuilder, saveType, autofillFields, previousClientState);
- } else {
- setFullSaveInfo(responseBuilder, saveType, autofillFields);
- }
- return responseBuilder.build();
- } else {
- logd("These fields are not meant to be saved by autofill.");
- return null;
- }
- }
-
- private static void setFullSaveInfo(FillResponse.Builder responseBuilder, int saveType,
- AutofillFieldMetadataCollection autofillFields) {
- AutofillId[] autofillIds = autofillFields.getAutofillIds();
- responseBuilder.setSaveInfo(new SaveInfo.Builder(saveType, autofillIds).build());
- }
-
- private static void setPartialSaveInfo(FillResponse.Builder responseBuilder, int saveType,
- AutofillFieldMetadataCollection autofillFields,
- Bundle previousClientState) {
- AutofillId[] autofillIds = autofillFields.getAutofillIds();
- List<String> allHints = autofillFields.getAllHints();
- if (Util.logDebugEnabled()) {
- logd("setPartialSaveInfo() for type %s: allHints=%s, ids=%s, clientState=%s",
- getSaveTypeAsString(saveType), allHints, Arrays.toString(autofillIds),
- bundleToString(previousClientState));
- }
-
- // 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");
- setFullSaveInfo(responseBuilder, saveType, autofillFields);
- return;
- }
-
- 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 = previousClientState == null
- ? null
- : previousClientState.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(previousClientState);
- responseBuilder.setSaveInfo
- (new SaveInfo.Builder(newSaveType, newIds)
- .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
- .build())
- .setClientState(newClientState);
-
- return;
- }
-
- responseBuilder.setClientState(newClientState);
-
- // TODO: on MR1, creates a new SaveType without required ids
- setFullSaveInfo(responseBuilder, saveType, autofillFields);
- }
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java
index d1efcc04..9b593426 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java
@@ -15,6 +15,8 @@
*/
package com.example.android.autofill.service;
+import android.view.View;
+
import com.example.android.autofill.service.model.FilledAutofillField;
import java.util.Arrays;
@@ -77,8 +79,8 @@ public final class AutofillHintProperties {
/**
* Sometimes, data for a hint should only be stored as a certain AutofillValue type. For
* example, it is recommended that data representing a Credit Card Expiration date, annotated
- * with the hint {@link android.view.View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}, should
- * only be stored as {@link android.view.View.AUTOFILL_TYPE_DATE}.
+ * with the hint {@link View#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}, should
+ * only be stored as {@link View#AUTOFILL_TYPE_DATE}.
*/
public boolean isValidType(int type) {
return mValidTypes.contains(type);
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
index 7cceba51..39b189c7 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
@@ -16,20 +16,24 @@
package com.example.android.autofill.service;
import android.service.autofill.SaveInfo;
+import android.support.annotation.NonNull;
import android.view.View;
-import com.example.android.autofill.service.model.AutofillDataset;
import com.example.android.autofill.service.model.FilledAutofillField;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
import java.util.Calendar;
-import java.util.UUID;
+import java.util.List;
+import java.util.Objects;
+import static com.example.android.autofill.service.util.Util.logd;
import static com.example.android.autofill.service.util.Util.logw;
-
+import static java.util.stream.Collectors.toList;
public final class AutofillHints {
+ public static final int PARTITION_ALL = -1;
public static final int PARTITION_OTHER = 0;
public static final int PARTITION_ADDRESS = 1;
public static final int PARTITION_EMAIL = 2;
@@ -45,45 +49,44 @@ public final class AutofillHints {
PARTITION_EMAIL,
(seed, datasetId) -> {
String textValue = "email" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- datasetId, View.AUTOFILL_HINT_EMAIL_ADDRESS, textValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId,
+ View.AUTOFILL_HINT_EMAIL_ADDRESS, textValue);
+
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_NAME, new AutofillHintProperties(
View.AUTOFILL_HINT_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "name" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- datasetId, View.AUTOFILL_HINT_NAME, textValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId, View.AUTOFILL_HINT_NAME,
+ textValue);
+
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_USERNAME, new AutofillHintProperties(
View.AUTOFILL_HINT_USERNAME, SaveInfo.SAVE_DATA_TYPE_USERNAME,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "login" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- datasetId, View.AUTOFILL_HINT_USERNAME, textValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId,
+ View.AUTOFILL_HINT_USERNAME, textValue);
+
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_PASSWORD, new AutofillHintProperties(
View.AUTOFILL_HINT_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "login" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- datasetId, View.AUTOFILL_HINT_PASSWORD, textValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId,
+ View.AUTOFILL_HINT_PASSWORD, textValue);
+
}, View.AUTOFILL_TYPE_TEXT))
.put(View.AUTOFILL_HINT_PHONE, new AutofillHintProperties(
View.AUTOFILL_HINT_PHONE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "" + seed + "2345678910";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_PHONE, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_POSTAL_ADDRESS, new AutofillHintProperties(
View.AUTOFILL_HINT_POSTAL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
@@ -91,18 +94,16 @@ public final class AutofillHints {
(seed, datasetId) -> {
String textValue =
"" + seed + " Fake Ln, Fake, FA, FAA 10001";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_POSTAL_ADDRESS, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_POSTAL_CODE, new AutofillHintProperties(
View.AUTOFILL_HINT_POSTAL_CODE, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "1000" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_POSTAL_CODE, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_NUMBER,
@@ -110,10 +111,9 @@ public final class AutofillHints {
PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "" + seed + "234567";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId,
View.AUTOFILL_HINT_CREDIT_CARD_NUMBER, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
@@ -121,9 +121,9 @@ public final class AutofillHints {
PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "" + seed + seed + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(datasetId,
- View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, textValue);
- return filledAutofillField;
+ return new FilledAutofillField(
+ datasetId, View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
+ textValue);
}, View.AUTOFILL_TYPE_TEXT))
.put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
@@ -132,10 +132,9 @@ public final class AutofillHints {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed);
Long dateValue = calendar.getTimeInMillis();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
dateValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_DATE))
.put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
@@ -147,10 +146,9 @@ public final class AutofillHints {
calendar.set(Calendar.MONTH, month);
String textValue = Integer.toString(month);
Long dateValue = calendar.getTimeInMillis();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
textValue, dateValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
View.AUTOFILL_TYPE_DATE))
.put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR, new AutofillHintProperties(
@@ -162,10 +160,9 @@ public final class AutofillHints {
calendar.set(Calendar.YEAR, expYear);
Long dateValue = calendar.getTimeInMillis();
String textValue = Integer.toString(expYear);
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
textValue, dateValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
View.AUTOFILL_TYPE_DATE))
.put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY, new AutofillHintProperties(
@@ -178,10 +175,9 @@ public final class AutofillHints {
calendar.set(Calendar.DATE, day);
String textValue = Integer.toString(day);
Long dateValue = calendar.getTimeInMillis();
- FilledAutofillField filledAutofillField = new FilledAutofillField(datasetId,
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
- textValue, dateValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId,
+ View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
+ textValue, dateValue);
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
View.AUTOFILL_TYPE_DATE))
.put(W3cHints.HONORIFIC_PREFIX, new AutofillHintProperties(
@@ -192,36 +188,32 @@ public final class AutofillHints {
"Sr.", "Dr.", "Lady", "Lord"};
String textValueFromList =
examplePrefixes[seed % examplePrefixes.length].toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(datasetId,
- W3cHints.HONORIFIC_PREFIX, textValueFromList);
- return filledAutofillField;
+ return new FilledAutofillField(
+ datasetId, W3cHints.HONORIFIC_PREFIX, textValueFromList);
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.GIVEN_NAME, new AutofillHintProperties(W3cHints.GIVEN_NAME,
SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "name" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.GIVEN_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDITIONAL_NAME, new AutofillHintProperties(
W3cHints.ADDITIONAL_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "addtlname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDITIONAL_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.FAMILY_NAME, new AutofillHintProperties(
W3cHints.FAMILY_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "famname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.FAMILY_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.HONORIFIC_SUFFIX, new AutofillHintProperties(
W3cHints.HONORIFIC_SUFFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC,
@@ -230,45 +222,40 @@ public final class AutofillHints {
CharSequence[] exampleSuffixes = {"san", "kun", "chan", "sama"};
String textValueFromListValue =
exampleSuffixes[seed % exampleSuffixes.length].toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.HONORIFIC_SUFFIX,
textValueFromListValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.NEW_PASSWORD, new AutofillHintProperties(
W3cHints.NEW_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "login" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.NEW_PASSWORD, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CURRENT_PASSWORD, new AutofillHintProperties(
View.AUTOFILL_HINT_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "login" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_PASSWORD, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ORGANIZATION_TITLE, new AutofillHintProperties(
W3cHints.ORGANIZATION_TITLE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "org" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ORGANIZATION_TITLE, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.ORGANIZATION, new AutofillHintProperties(W3cHints.ORGANIZATION,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "org" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ORGANIZATION, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.STREET_ADDRESS, new AutofillHintProperties(
W3cHints.STREET_ADDRESS, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
@@ -276,78 +263,69 @@ public final class AutofillHints {
(seed, datasetId) -> {
String textValue =
"" + seed + " Fake Ln, Fake, FA, FAA 10001";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.STREET_ADDRESS, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LINE1, new AutofillHintProperties(W3cHints.ADDRESS_LINE1,
SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "" + seed + " Fake Ln";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LINE1, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LINE2, new AutofillHintProperties(W3cHints.ADDRESS_LINE2,
SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "Bldg. " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LINE2, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LINE3, new AutofillHintProperties(W3cHints.ADDRESS_LINE3,
SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "Suite " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LINE3, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LEVEL4, new AutofillHintProperties(
W3cHints.ADDRESS_LEVEL4, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "city " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LEVEL4, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LEVEL3, new AutofillHintProperties(
W3cHints.ADDRESS_LEVEL3, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "county " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LEVEL3, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LEVEL2, new AutofillHintProperties(
W3cHints.ADDRESS_LEVEL2, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "state " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LEVEL2, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.ADDRESS_LEVEL1, new AutofillHintProperties(
W3cHints.ADDRESS_LEVEL1, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "country " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.ADDRESS_LEVEL1, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.COUNTRY, new AutofillHintProperties(W3cHints.COUNTRY,
SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "country " + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.COUNTRY, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.COUNTRY_NAME, new AutofillHintProperties(W3cHints.COUNTRY_NAME,
SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
@@ -355,63 +333,56 @@ public final class AutofillHints {
CharSequence[] exampleCountries = {"USA", "Mexico", "Canada"};
String textValue = exampleCountries[seed % exampleCountries.length]
.toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.COUNTRY_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.POSTAL_CODE, new AutofillHintProperties(
View.AUTOFILL_HINT_POSTAL_CODE, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
PARTITION_ADDRESS,
(seed, datasetId) -> {
String textValue = "" + seed + seed + seed + seed + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_POSTAL_CODE, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_NAME, new AutofillHintProperties(W3cHints.CC_NAME,
SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD,
PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "firstname" + seed + "lastname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.CC_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_GIVEN_NAME, new AutofillHintProperties(W3cHints.CC_GIVEN_NAME,
SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "givenname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.CC_GIVEN_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_ADDITIONAL_NAME, new AutofillHintProperties(
W3cHints.CC_ADDITIONAL_NAME, SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD,
PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "addtlname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.CC_ADDITIONAL_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_FAMILY_NAME, new AutofillHintProperties(
W3cHints.CC_FAMILY_NAME, SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD,
PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "familyname" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.CC_FAMILY_NAME, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_NUMBER, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_NUMBER,
SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "" + seed + "234567";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_NUMBER,
textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_EXPIRATION, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
@@ -420,10 +391,9 @@ public final class AutofillHints {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed);
Long dateValue = calendar.getTimeInMillis();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
dateValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_DATE))
.put(W3cHints.CC_EXPIRATION_MONTH, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
@@ -432,10 +402,9 @@ public final class AutofillHints {
CharSequence[] months = monthRange();
String textValueFromListValue = months[seed % months.length]
.toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
textValueFromListValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.CC_EXPIRATION_YEAR, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
@@ -446,29 +415,26 @@ public final class AutofillHints {
calendar.set(Calendar.YEAR, expYear);
Long dateValue = calendar.getTimeInMillis();
String textValue = "" + expYear;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
textValue, dateValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.CC_CSC, new AutofillHintProperties(
View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "" + seed + seed + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
textValue);
- return filledAutofillField;
+
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.CC_TYPE, new AutofillHintProperties(W3cHints.CC_TYPE,
SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
(seed, datasetId) -> {
String textValue = "type" + seed;
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(datasetId, W3cHints.CC_TYPE,
- textValue);
- return filledAutofillField;
+ return new FilledAutofillField(
+ datasetId, W3cHints.CC_TYPE, textValue);
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TRANSACTION_CURRENCY, new AutofillHintProperties(
W3cHints.TRANSACTION_CURRENCY, SaveInfo.SAVE_DATA_TYPE_GENERIC,
@@ -478,19 +444,17 @@ public final class AutofillHints {
String textValueFromListValue =
exampleCurrencies[seed % exampleCurrencies.length]
.toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TRANSACTION_CURRENCY,
textValueFromListValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TRANSACTION_AMOUNT, new AutofillHintProperties(
W3cHints.TRANSACTION_AMOUNT, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "" + seed * 100;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TRANSACTION_AMOUNT, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.LANGUAGE, new AutofillHintProperties(W3cHints.LANGUAGE,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
@@ -499,9 +463,8 @@ public final class AutofillHints {
"Danish", "Dutch", "English", "Estonian"};
String textValueFromListValue =
exampleLanguages[seed % exampleLanguages.length].toString();
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.LANGUAGE, textValueFromListValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.BDAY, new AutofillHintProperties(W3cHints.BDAY,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
@@ -511,193 +474,169 @@ public final class AutofillHints {
calendar.set(Calendar.MONTH, seed % 12);
calendar.set(Calendar.DATE, seed % 27);
Long dateValue = calendar.getTimeInMillis();
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(datasetId, W3cHints.BDAY, dateValue);
- return filledAutofillField;
+ return new FilledAutofillField(datasetId, W3cHints.BDAY, dateValue);
}, View.AUTOFILL_TYPE_DATE))
.put(W3cHints.BDAY_DAY, new AutofillHintProperties(W3cHints.BDAY_DAY,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "" + seed % 27;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.BDAY_DAY, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.BDAY_MONTH, new AutofillHintProperties(W3cHints.BDAY_MONTH,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "" + seed % 12;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.BDAY_MONTH, textValue);
- return filledAutofillField;
+
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.BDAY_YEAR, new AutofillHintProperties(W3cHints.BDAY_YEAR,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
int year = Calendar.getInstance().get(Calendar.YEAR) - seed * 10;
String textValue = "" + year;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.BDAY_YEAR, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.SEX, new AutofillHintProperties(W3cHints.SEX,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "Other";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.SEX, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.URL, new AutofillHintProperties(W3cHints.URL,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "http://google.com";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.URL, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.PHOTO, new AutofillHintProperties(W3cHints.PHOTO,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
String textValue = "photo" + seed + ".jpg";
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PHOTO, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.PREFIX_SECTION, new AutofillHintProperties(
W3cHints.PREFIX_SECTION, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PREFIX_SECTION);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.SHIPPING, new AutofillHintProperties(W3cHints.SHIPPING,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_ADDRESS,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.SHIPPING);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.BILLING, new AutofillHintProperties(W3cHints.BILLING,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_ADDRESS,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.BILLING);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.PREFIX_HOME, new AutofillHintProperties(W3cHints.PREFIX_HOME,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PREFIX_HOME);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.PREFIX_WORK, new AutofillHintProperties(W3cHints.PREFIX_WORK,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PREFIX_WORK);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.PREFIX_FAX, new AutofillHintProperties(W3cHints.PREFIX_FAX,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PREFIX_FAX);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.PREFIX_PAGER, new AutofillHintProperties(W3cHints.PREFIX_PAGER,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.PREFIX_PAGER);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL, new AutofillHintProperties(W3cHints.TEL,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.TEL_COUNTRY_CODE, new AutofillHintProperties(
W3cHints.TEL_COUNTRY_CODE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_COUNTRY_CODE);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_NATIONAL, new AutofillHintProperties(W3cHints.TEL_NATIONAL,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_NATIONAL);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_AREA_CODE, new AutofillHintProperties(
W3cHints.TEL_AREA_CODE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_AREA_CODE);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_LOCAL, new AutofillHintProperties(
W3cHints.TEL_LOCAL, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_LOCAL);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_LOCAL_PREFIX, new AutofillHintProperties(
W3cHints.TEL_LOCAL_PREFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_LOCAL_PREFIX);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_LOCAL_SUFFIX, new AutofillHintProperties(
W3cHints.TEL_LOCAL_SUFFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_LOCAL_SUFFIX);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.TEL_EXTENSION, new AutofillHintProperties(W3cHints.TEL_EXTENSION,
SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.TEL_EXTENSION);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.put(W3cHints.EMAIL, new AutofillHintProperties(
View.AUTOFILL_HINT_EMAIL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_GENERIC,
PARTITION_EMAIL,
(seed, datasetId) -> {
String textValue = "email" + seed;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, View.AUTOFILL_HINT_EMAIL_ADDRESS, textValue);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT))
.put(W3cHints.IMPP, new AutofillHintProperties(W3cHints.IMPP,
SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS, PARTITION_EMAIL,
(seed, datasetId) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
+ return new FilledAutofillField(
datasetId, W3cHints.IMPP);
- return filledAutofillField;
}, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
.build();
private AutofillHints() {
}
- public static boolean isValidTypeForHints(String hint, int type) {
- if (hint != null && sValidHints.containsKey(hint)) {
+ public static boolean isValidTypeForHints(@NonNull String hint, int type) {
+ if (sValidHints.containsKey(hint)) {
boolean valid = sValidHints.get(hint).isValidType(type);
if (valid) {
return true;
@@ -706,49 +645,85 @@ public final class AutofillHints {
return false;
}
- public static boolean isValidHint(String hint) {
+ public static boolean isValidHint(@NonNull String hint) {
return sValidHints.containsKey(hint);
}
- public static int getSaveTypeForHints(String[] hints) {
- int saveType = 0;
- if (hints != null) {
- for (String hint : hints) {
- if (hint != null && sValidHints.containsKey(hint)) {
- saveType |= sValidHints.get(hint).getSaveType();
- }
- }
+ public static int getSaveTypeForHint(@NonNull String hint) {
+ if (sValidHints.containsKey(hint)) {
+ return sValidHints.get(hint).getSaveType();
+ } else {
+ return 0;
}
- return saveType;
}
- public static FilledAutofillField getFakeField(String hint, int seed, String datasetId) {
- return sValidHints.get(hint).generateFakeField(seed, datasetId);
+ public static FilledAutofillField generateFakeField(@NonNull String hint, int seed,
+ String datasetId) {
+ if (isValidHint(hint)) {
+ return sValidHints.get(hint).generateFakeField(seed, datasetId);
+ } else {
+ return null;
+ }
}
- public static FilledAutofillFieldCollection getFakeFieldCollection(int partition, int seed) {
- String datasetName = "dataset-" + seed;
- String datasetId = UUID.randomUUID().toString();
- AutofillDataset autofillDataset = new AutofillDataset(datasetId, datasetName);
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- new FilledAutofillFieldCollection(autofillDataset);
- for (String hint : sValidHints.keySet()) {
- if (hint != null && sValidHints.get(hint).getPartition() == partition) {
- FilledAutofillField fakeField = getFakeField(hint, seed, datasetId);
- filledAutofillFieldCollection.add(fakeField);
- }
- }
- return filledAutofillFieldCollection;
+ public static ImmutableSet<String> getHints() {
+ return sValidHints.keySet();
+ }
+
+ public static List<String> convertToStoredHintNames(@NonNull List<String> hints) {
+ return convertToStoredHintNames(hints, PARTITION_ALL);
+ }
+
+ public static List<String> convertToStoredHintNames(@NonNull List<String> hints, int partition) {
+ return removePrefixes(hints)
+ .stream()
+ .filter(sValidHints::containsKey)
+ .map(sValidHints::get)
+ .filter(Objects::nonNull)
+ .filter((properties) -> matchesPartition(properties, partition))
+ .map(AutofillHintProperties::getAutofillHint)
+ .collect(toList());
}
- private static String getStoredHintName(String hint) {
- return sValidHints.get(hint).getAutofillHint();
+ public static boolean matchesPartition(@NonNull String hint, int partition) {
+ return isValidHint(hint) && matchesPartition(sValidHints.get(hint), partition);
}
- public static void convertToStoredHintNames(String[] hints) {
- for (int i = 0; i < hints.length; i++) {
- hints[i] = getStoredHintName(hints[i]);
+ private static boolean matchesPartition(@NonNull AutofillHintProperties properties,
+ int partition) {
+ return partition == PARTITION_ALL || properties.getPartition() == partition;
+ }
+
+ private static List<String> removePrefixes(@NonNull List<String> hints) {
+ List<String> hintsWithoutPrefixes = new ArrayList<>();
+ String nextHint = null;
+ for (int i = 0; i < hints.size(); i++) {
+ String hint = hints.get(i);
+ if (i < hints.size() - 1) {
+ nextHint = hints.get(i + 1);
+ }
+ // First convert the compound W3C autofill hints
+ if (isW3cSectionPrefix(hint) && i < hints.size() - 1) {
+ i++;
+ hint = hints.get(i);
+ logd("Hint is a W3C section prefix; using %s instead", hint);
+ if (i < hints.size() - 1) {
+ nextHint = hints.get(i + 1);
+ }
+ }
+ if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint)) {
+ hint = nextHint;
+ i++;
+ logd("Hint is a W3C type prefix; using %s instead", hint);
+ }
+ if (isW3cAddressType(hint) && nextHint != null) {
+ hint = nextHint;
+ i++;
+ logd("Hint is a W3C address prefix; using %s instead", hint);
+ }
+ hintsWithoutPrefixes.add(hint);
}
+ return hintsWithoutPrefixes;
}
private static CharSequence[] dayRange() {
@@ -767,29 +742,11 @@ public final class AutofillHints {
return months;
}
- public static String[] filterForSupportedHints(String[] hints) {
- String[] filteredHints = new String[hints.length];
- int i = 0;
- for (String hint : hints) {
- if (AutofillHints.isValidHint(hint)) {
- filteredHints[i++] = hint;
- } else {
- logw("Invalid autofill hint: %s", hint);
- }
- }
- if (i == 0) {
- return null;
- }
- String[] finalFilteredHints = new String[i];
- System.arraycopy(filteredHints, 0, finalFilteredHints, 0, i);
- return finalFilteredHints;
- }
-
- public static boolean isW3cSectionPrefix(String hint) {
+ private static boolean isW3cSectionPrefix(@NonNull String hint) {
return hint.startsWith(W3cHints.PREFIX_SECTION);
}
- public static boolean isW3cAddressType(String hint) {
+ private static boolean isW3cAddressType(@NonNull String hint) {
switch (hint) {
case W3cHints.SHIPPING:
case W3cHints.BILLING:
@@ -798,7 +755,7 @@ public final class AutofillHints {
return false;
}
- public static boolean isW3cTypePrefix(String hint) {
+ private static boolean isW3cTypePrefix(@NonNull String hint) {
switch (hint) {
case W3cHints.PREFIX_WORK:
case W3cHints.PREFIX_FAX:
@@ -809,7 +766,7 @@ public final class AutofillHints {
return false;
}
- public static boolean isW3cTypeHint(String hint) {
+ private static boolean isW3cTypeHint(@NonNull String hint) {
switch (hint) {
case W3cHints.TEL:
case W3cHints.TEL_COUNTRY_CODE:
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 0bef584e..ba2065d8 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
@@ -16,7 +16,9 @@
package com.example.android.autofill.service;
import android.app.assist.AssistStructure;
+import android.content.Context;
import android.content.IntentSender;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.service.autofill.AutofillService;
@@ -31,21 +33,28 @@ import android.view.View;
import android.view.autofill.AutofillId;
import android.widget.RemoteViews;
-import com.example.android.autofill.service.datasource.DataCallback;
-import com.example.android.autofill.service.datasource.PackageVerificationDataSource;
-import com.example.android.autofill.service.datasource.local.LocalAutofillDataSource;
-import com.example.android.autofill.service.datasource.local.DigitalAssetLinksRepository;
-import com.example.android.autofill.service.datasource.local.SharedPrefsPackageVerificationRepository;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+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;
+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.source.PackageVerificationDataSource;
+import com.example.android.autofill.service.data.source.local.DigitalAssetLinksRepository;
+import com.example.android.autofill.service.data.source.local.LocalAutofillDataSource;
+import com.example.android.autofill.service.data.source.local.SharedPrefsPackageVerificationRepository;
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
+import com.example.android.autofill.service.data.source.local.db.AutofillDatabase;
+import com.example.android.autofill.service.model.DalCheck;
+import com.example.android.autofill.service.model.DalInfo;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
import com.example.android.autofill.service.settings.MyPreferences;
import com.example.android.autofill.service.util.AppExecutors;
import com.example.android.autofill.service.util.Util;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import static com.example.android.autofill.service.AutofillHelper.CLIENT_STATE_PARTIAL_ID_TEMPLATE;
+import static com.example.android.autofill.service.data.adapter.ResponseAdapter.CLIENT_STATE_PARTIAL_ID_TEMPLATE;
import static com.example.android.autofill.service.util.Util.AUTOFILL_ID_FILTER;
import static com.example.android.autofill.service.util.Util.bundleToString;
import static com.example.android.autofill.service.util.Util.dumpStructure;
@@ -60,82 +69,74 @@ public class MyAutofillService extends AutofillService {
private LocalAutofillDataSource mLocalAutofillDataSource;
private DigitalAssetLinksRepository mDalRepository;
private PackageVerificationDataSource mPackageVerificationRepository;
+ private AutofillDataBuilder mAutofillDataBuilder;
+ private DatasetAdapter mDatasetAdapter;
+ private ResponseAdapter mResponseAdapter;
+ private ClientViewMetadata mClientViewMetadata;
@Override
public void onCreate() {
super.onCreate();
Util.setLoggingLevel(MyPreferences.getInstance(this).getLoggingLevel());
- mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(this, new AppExecutors());
- mDalRepository = DigitalAssetLinksRepository.getInstance(this);
+ SharedPreferences localAfDataSourceSharedPrefs =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ AutofillDao autofillDao = AutofillDatabase.getInstance(this).autofillDao();
+ mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(localAfDataSourceSharedPrefs,
+ autofillDao, new AppExecutors());
+ mDalRepository = DigitalAssetLinksRepository.getInstance(getPackageManager());
mPackageVerificationRepository = SharedPrefsPackageVerificationRepository.getInstance(this);
}
@Override
public void onFillRequest(@NonNull FillRequest request,
- @NonNull CancellationSignal cancellationSignal,
- @NonNull FillCallback callback) {
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
AssistStructure structure = request.getFillContexts()
.get(request.getFillContexts().size() - 1).getStructure();
+ StructureParser parser = new StructureParser(structure);
+ mDatasetAdapter = new DatasetAdapter(parser);
+ mClientViewMetadata = new ClientViewMetadata(parser);
+ mResponseAdapter = new ResponseAdapter(this, mClientViewMetadata,
+ getPackageName(), mDatasetAdapter, request.getClientState());
String packageName = structure.getActivityComponent().getPackageName();
if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
- callback.onFailure(
- getApplicationContext().getString(R.string.invalid_package_signature));
+ callback.onFailure(getString(R.string.invalid_package_signature));
return;
}
final Bundle clientState = request.getClientState();
if (logVerboseEnabled()) {
logv("onFillRequest(): clientState=%s", bundleToString(clientState));
+ dumpStructure(structure);
}
- dumpStructure(structure);
-
cancellationSignal.setOnCancelListener(() ->
logw("Cancel autofill not implemented in this sample.")
);
- // Parse AutoFill data in Activity
- StructureParser parser = new StructureParser(getApplicationContext(), structure,
- mLocalAutofillDataSource, mDalRepository);
- // TODO: try / catch on other places (onSave, auth activity, etc...)
- try {
- parser.parseForFill();
- } catch (SecurityException e) {
- // TODO: handle cases where DAL didn't pass by showing a custom UI asking the user
- // to confirm the mapping. Might require subclassing SecurityException.
- logw(e, "Security exception handling %s", request);
- callback.onFailure(e.getMessage());
- return;
- }
- AutofillFieldMetadataCollection autofillFields = parser.getAutofillFields();
- FillResponse.Builder responseBuilder = new FillResponse.Builder();
// Check user's settings for authenticating Responses and Datasets.
boolean responseAuth = MyPreferences.getInstance(this).isResponseAuth();
- AutofillId[] autofillIds = autofillFields.getAutofillIds();
- if (responseAuth && !Arrays.asList(autofillIds).isEmpty()) {
+ if (responseAuth) {
// If the entire Autofill Response is authenticated, AuthActivity is used
// to generate Response.
IntentSender sender = AuthActivity.getAuthIntentSenderForResponse(this);
- RemoteViews presentation = AutofillHelper
- .newRemoteViews(getPackageName(), getString(R.string.autofill_sign_in_prompt),
- R.drawable.ic_lock_black_24dp);
- responseBuilder
- .setAuthentication(autofillIds, sender, presentation);
- callback.onSuccess(responseBuilder.build());
+ RemoteViews remoteViews = RemoteViewsHelper.viewsWithAuth(getPackageName(),
+ getString(R.string.autofill_sign_in_prompt));
+ FillResponse response = mResponseAdapter.buildResponse(sender, remoteViews);
+ if (response != null) {
+ callback.onSuccess(response);
+ }
} else {
boolean datasetAuth = MyPreferences.getInstance(this).isDatasetAuth();
- mLocalAutofillDataSource.getFilledAutofillFieldCollection(
- autofillFields.getFocusedHints(), autofillFields.getAllHints(),
- new DataCallback<HashMap<String, FilledAutofillFieldCollection>>() {
+ mLocalAutofillDataSource.getAutofillDatasets(mClientViewMetadata.getAllHints(),
+ new DataCallback<List<DatasetWithFilledAutofillFields>>() {
@Override
- public void onLoaded(HashMap<String, FilledAutofillFieldCollection>
- clientFormDataMap) {
- FillResponse response = AutofillHelper.newResponse
- (MyAutofillService.this, clientState, datasetAuth,
- autofillFields, clientFormDataMap);
+ public void onLoaded(List<DatasetWithFilledAutofillFields> datasets) {
+ FillResponse response = mResponseAdapter.buildResponse(datasets,
+ datasetAuth);
callback.onSuccess(response);
}
@Override
public void onDataNotAvailable(String msg, Object... params) {
logw(msg, params);
+ callback.onFailure(String.format(msg, params));
}
});
}
@@ -146,6 +147,9 @@ public class MyAutofillService extends AutofillService {
List<FillContext> fillContexts = request.getFillContexts();
int size = fillContexts.size();
AssistStructure structure = fillContexts.get(size - 1).getStructure();
+ StructureParser parser = new StructureParser(structure);
+ mAutofillDataBuilder = new ClientAutofillDataBuilder(parser);
+ mClientViewMetadata = new ClientViewMetadata(parser);
String packageName = structure.getActivityComponent().getPackageName();
if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
callback.onFailure(getApplicationContext().getString(R.string.invalid_package_signature));
@@ -159,13 +163,13 @@ public class MyAutofillService extends AutofillService {
// TODO: hardcode check for partial username
if (clientState != null) {
- String usernameKey =
- String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, View.AUTOFILL_HINT_USERNAME);
+ String usernameKey = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE,
+ View.AUTOFILL_HINT_USERNAME);
AutofillId usernameId = clientState.getParcelable(usernameKey);
logd("client state for %s: %s", usernameKey, usernameId);
if (usernameId != null) {
- String passwordKey =
- String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE, View.AUTOFILL_HINT_PASSWORD);
+ String passwordKey = String.format(CLIENT_STATE_PARTIAL_ID_TEMPLATE,
+ View.AUTOFILL_HINT_PASSWORD);
AutofillId passwordId = clientState.getParcelable(passwordKey);
logd("Scanning %d contexts for username ID %s and password ID %s.", size,
@@ -192,12 +196,50 @@ public class MyAutofillService extends AutofillService {
}
}
}
+ checkWebDomainAndBuildAutofillData(packageName, callback);
+ }
+
+ private void checkWebDomainAndBuildAutofillData(String packageName, SaveCallback callback) {
+ String webDomain;
+ try {
+ webDomain = mClientViewMetadata.buildWebDomain();
+ } catch(SecurityException e) {
+ logw(e.getMessage());
+ callback.onFailure(e.getMessage());
+ return;
+ }
+ if (webDomain != null && webDomain.length() > 0) {
+ mDalRepository.checkValid(new DalInfo(webDomain, packageName),
+ new DataCallback<DalCheck>() {
+ @Override
+ public void onLoaded(DalCheck dalCheck) {
+ if (dalCheck.linked) {
+ logd("Domain %s is valid for %s", webDomain, packageName);
+ buildAndSaveAutofillData();
+ } else {
+ callback.onFailure(String.format(
+ "Could not associate web domain %s with app %s", webDomain,
+ packageName));
+ }
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ callback.onFailure(String.format(msg, params));
+ }
+ });
+ } else {
+ logd("no web domain");
+ buildAndSaveAutofillData();
+ }
+ }
- StructureParser parser = new StructureParser(getApplicationContext(), structure,
- mLocalAutofillDataSource, mDalRepository);
- parser.parseForSave();
- FilledAutofillFieldCollection filledAutofillFieldCollection = parser.getClientFormData();
- mLocalAutofillDataSource.saveFilledAutofillFieldCollection(filledAutofillFieldCollection);
+ private void buildAndSaveAutofillData() {
+ int datasetNumber = mLocalAutofillDataSource.getDatasetNumber();
+ List<DatasetWithFilledAutofillFields> datasetsWithFilledAutofillFields =
+ mAutofillDataBuilder.buildDatasetsByPartition(datasetNumber);
+ mLocalAutofillDataSource.saveAutofillDatasets(datasetsWithFilledAutofillFields);
}
@Override
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/RemoteViewsHelper.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/RemoteViewsHelper.java
new file mode 100644
index 00000000..b925b95a
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/RemoteViewsHelper.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import android.support.annotation.DrawableRes;
+import android.widget.RemoteViews;
+
+/**
+ * This is a class containing helper methods for building Autofill Datasets and Responses.
+ */
+public final class RemoteViewsHelper {
+ private RemoteViewsHelper() {
+ }
+
+ public static RemoteViews viewsWithAuth(String packageName, String text) {
+ return simpleRemoteViews(packageName, text, R.drawable.ic_lock_black_24dp);
+ }
+
+ public static RemoteViews viewsWithNoAuth(String packageName, String text) {
+ return simpleRemoteViews(packageName, text, R.drawable.ic_person_black_24dp);
+ }
+
+ private static RemoteViews simpleRemoteViews(String packageName, String remoteViewsText,
+ @DrawableRes int drawableId) {
+ RemoteViews presentation = new RemoteViews(packageName,
+ R.layout.multidataset_service_list_item);
+ presentation.setTextViewText(R.id.text, remoteViewsText);
+ presentation.setImageViewResource(R.id.icon, drawableId);
+ return presentation;
+ }
+}
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 3bfbd96d..54296f36 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
@@ -13,167 +13,52 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.example.android.autofill.service;
import android.app.assist.AssistStructure;
-import android.app.assist.AssistStructure.ViewNode;
-import android.app.assist.AssistStructure.WindowNode;
-import android.content.Context;
-import android.view.autofill.AutofillValue;
-
-import com.example.android.autofill.service.datasource.DataCallback;
-import com.example.android.autofill.service.datasource.local.DigitalAssetLinksRepository;
-import com.example.android.autofill.service.datasource.local.LocalAutofillDataSource;
-import com.example.android.autofill.service.model.AutofillDataset;
-import com.example.android.autofill.service.model.DalCheck;
-import com.example.android.autofill.service.model.DalInfo;
-import com.example.android.autofill.service.model.FilledAutofillField;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+import android.support.annotation.NonNull;
-import java.util.List;
-import java.util.UUID;
+import com.google.common.base.Preconditions;
-import static com.example.android.autofill.service.util.Util.logd;
-import static com.example.android.autofill.service.util.Util.logw;
+import static android.app.assist.AssistStructure.ViewNode;
/**
- * Parser for an AssistStructure object. This is invoked when the Autofill Service receives an
- * AssistStructure from the client Activity, representing its View hierarchy. In this sample, it
- * parses the hierarchy and collects autofill metadata from {@link ViewNode}s along the way.
+ * Wrapper for {@link AssistStructure} to make it easy to parse.
*/
-final class StructureParser {
- private final AutofillFieldMetadataCollection mAutofillFields =
- new AutofillFieldMetadataCollection();
- private final LocalAutofillDataSource mLocalAutofillDataSource;
- private final DigitalAssetLinksRepository mDalRepository;
+public final class StructureParser {
private final AssistStructure mStructure;
- private FilledAutofillFieldCollection mFilledAutofillFieldCollection;
- StructureParser(Context context, AssistStructure structure,
- LocalAutofillDataSource localAutofillDataSource,
- DigitalAssetLinksRepository dalRepository) {
- mLocalAutofillDataSource = localAutofillDataSource;
- mDalRepository = dalRepository;
+ public StructureParser(@NonNull AssistStructure structure) {
+ Preconditions.checkNotNull(structure);
mStructure = structure;
}
- public void parseForFill() {
- parse(true);
- }
-
- public void parseForSave() {
- parse(false);
- }
-
/**
- * Traverse AssistStructure and add ViewNode metadata to a flat list.
+ * Traverses through the {@link AssistStructure} and does something at each {@link ViewNode}.
+ *
+ * @param processor contains action to be performed on each {@link ViewNode}.
*/
- private void parse(boolean forFill) {
- logd("Parsing structure for %s", mStructure.getActivityComponent());
+ public void parse(NodeProcessor processor) {
int nodes = mStructure.getWindowNodeCount();
- String datasetName = "dataset-" + mLocalAutofillDataSource.getDatasetNumber();
- String datasetId = UUID.randomUUID().toString();
- AutofillDataset dataset = new AutofillDataset(datasetId, datasetName);
- mFilledAutofillFieldCollection = new FilledAutofillFieldCollection(dataset);
- StringBuilder webDomain = new StringBuilder();
for (int i = 0; i < nodes; i++) {
- WindowNode node = mStructure.getWindowNodeAt(i);
- ViewNode view = node.getRootViewNode();
- parseLocked(forFill, view, webDomain);
- }
- if (webDomain.length() > 0) {
- String packageName = mStructure.getActivityComponent().getPackageName();
- mDalRepository.checkValid(new DalInfo(webDomain.toString(), packageName),
- new DataCallback<DalCheck>() {
- @Override
- public void onLoaded(DalCheck dalCheck) {
- if (dalCheck.linked) {
- logd("Domain %s is valid for %s", webDomain, packageName);
- } else {
- throw new SecurityException(String.format(
- "Could not associate web domain %s with app %s", webDomain,
- packageName));
- }
- }
-
- @Override
- public void onDataNotAvailable(String msg, Object... params) {
- logw(msg, params);
- throw new SecurityException(String.format(
- "Could not associate web domain %s with app %s", webDomain,
- packageName));
- }
- });
- } else {
- logd("no web domain");
+ AssistStructure.ViewNode viewNode = mStructure.getWindowNodeAt(i).getRootViewNode();
+ traverseRoot(viewNode, processor);
}
}
- private void parseLocked(boolean forFill, 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);
- }
- }
-
- if (viewNode.getAutofillHints() != null) {
- String[] filteredHints = AutofillHints.filterForSupportedHints(
- viewNode.getAutofillHints());
- if (filteredHints != null && filteredHints.length > 0) {
- if (forFill) {
- mAutofillFields.add(new AutofillFieldMetadata(viewNode));
- } else {
- AutofillValue autofillValue = viewNode.getAutofillValue();
- String textValue = null;
- Long dateValue = null;
- Boolean toggleValue = null;
- CharSequence[] autofillOptions = null;
- Integer listIndex = null;
- if (autofillValue != null) {
- if (autofillValue.isText()) {
- // Using toString of AutofillValue.getTextValue in order to save it to
- // SharedPreferences.
- textValue = autofillValue.getTextValue().toString();
- } else if (autofillValue.isDate()) {
- dateValue = autofillValue.getDateValue();
- } else if (autofillValue.isList()) {
- autofillOptions = viewNode.getAutofillOptions();
- listIndex = autofillValue.getListValue();
- } else if (autofillValue.isToggle()) {
- toggleValue = autofillValue.getToggleValue();
- }
- }
- List<FilledAutofillField> filledAutofillFields =
- FilledAutofillField.build(
- mFilledAutofillFieldCollection.getDataset().getId(),
- viewNode.getAutofillHints(),
- textValue, dateValue, toggleValue, autofillOptions, listIndex);
- if (filledAutofillFields != null) {
- mFilledAutofillFieldCollection.add(filledAutofillFields);
- }
- }
- }
- }
+ private void traverseRoot(AssistStructure.ViewNode viewNode, NodeProcessor processor) {
+ processor.processNode(viewNode);
int childrenSize = viewNode.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
- parseLocked(forFill, viewNode.getChildAt(i), validWebDomain);
+ traverseRoot(viewNode.getChildAt(i), processor);
}
}
}
- public AutofillFieldMetadataCollection getAutofillFields() {
- return mAutofillFields;
- }
- public FilledAutofillFieldCollection getClientFormData() {
- return mFilledAutofillFieldCollection;
+ public interface NodeProcessor {
+ void processNode(ViewNode node);
}
}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/AutofillDataBuilder.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/AutofillDataBuilder.java
new file mode 100644
index 00000000..0110bdd2
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/AutofillDataBuilder.java
@@ -0,0 +1,25 @@
+/*
+ * 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 com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+
+import java.util.List;
+
+public interface AutofillDataBuilder {
+ List<DatasetWithFilledAutofillFields> buildDatasetsByPartition(int datasetNumber);
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientAutofillDataBuilder.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientAutofillDataBuilder.java
new file mode 100644
index 00000000..5d18ae0c
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientAutofillDataBuilder.java
@@ -0,0 +1,157 @@
+/*
+ * 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.support.annotation.NonNull;
+import android.view.View;
+import android.view.autofill.AutofillValue;
+
+import com.example.android.autofill.service.AutofillHints;
+import com.example.android.autofill.service.StructureParser;
+import com.example.android.autofill.service.model.AutofillDataset;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+import com.example.android.autofill.service.model.FilledAutofillField;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import static com.example.android.autofill.service.AutofillHints.convertToStoredHintNames;
+import static com.example.android.autofill.service.util.Util.loge;
+
+public class ClientAutofillDataBuilder implements AutofillDataBuilder {
+ private final StructureParser mStructureParser;
+
+ public ClientAutofillDataBuilder(StructureParser structureParser) {
+ mStructureParser = structureParser;
+ }
+
+ @Override
+ public List<DatasetWithFilledAutofillFields> buildDatasetsByPartition(int datasetNumber) {
+ ImmutableList.Builder<DatasetWithFilledAutofillFields> listBuilder =
+ new ImmutableList.Builder<>();
+ for (int partition : AutofillHints.PARTITIONS) {
+ AutofillDataset autofillDataset = new AutofillDataset(UUID.randomUUID().toString(),
+ "dataset-" + datasetNumber + "." + partition);
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields =
+ buildDatasetForPartition(autofillDataset, partition);
+ if (datasetWithFilledAutofillFields != null) {
+ listBuilder.add(datasetWithFilledAutofillFields);
+ }
+ }
+ return listBuilder.build();
+ }
+
+ /**
+ * Parses a client view structure and build a dataset (in the form of a
+ * {@link DatasetWithFilledAutofillFields}) from the view metadata found.
+ */
+ private DatasetWithFilledAutofillFields buildDatasetForPartition(AutofillDataset dataset,
+ int partition) {
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields =
+ new DatasetWithFilledAutofillFields();
+ datasetWithFilledAutofillFields.autofillDataset = dataset;
+ mStructureParser.parse((node) ->
+ parseAutofillFields(node, datasetWithFilledAutofillFields, partition)
+ );
+ if (datasetWithFilledAutofillFields.filledAutofillFields == null) {
+ return null;
+ } else {
+ return datasetWithFilledAutofillFields;
+ }
+ }
+
+ private void parseAutofillFields(AssistStructure.ViewNode viewNode,
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields, int partition) {
+ String[] hints = viewNode.getAutofillHints();
+ if (hints == null) {
+ return;
+ }
+ List<String> filteredHints = convertToStoredHintNames(Arrays.asList(hints), partition);
+ if (filteredHints == null || filteredHints.size() == 0) {
+ return;
+ }
+ AutofillValue autofillValue = viewNode.getAutofillValue();
+ String textValue = null;
+ Long dateValue = null;
+ Boolean toggleValue = null;
+ CharSequence[] autofillOptions = null;
+ Integer listIndex = null;
+ if (autofillValue != null) {
+ if (autofillValue.isText()) {
+ // Using toString of AutofillValue.getTextValue in order to save it to
+ // SharedPreferences.
+ textValue = autofillValue.getTextValue().toString();
+ } else if (autofillValue.isDate()) {
+ dateValue = autofillValue.getDateValue();
+ } else if (autofillValue.isList()) {
+ autofillOptions = viewNode.getAutofillOptions();
+ listIndex = autofillValue.getListValue();
+ } else if (autofillValue.isToggle()) {
+ toggleValue = autofillValue.getToggleValue();
+ }
+ }
+ appendViewMetadata(datasetWithFilledAutofillFields,
+ filteredHints, textValue, dateValue, toggleValue,
+ autofillOptions, listIndex);
+ }
+
+ private void appendViewMetadata(@NonNull DatasetWithFilledAutofillFields
+ datasetWithFilledAutofillFields, @NonNull List<String> hints,
+ @Nullable String textValue, @Nullable Long dateValue, @Nullable Boolean toggleValue,
+ @Nullable CharSequence[] autofillOptions, @Nullable Integer listIndex) {
+ for (int i = 0; i < hints.size(); i++) {
+ String hint = hints.get(i);
+ // Then check if the "actual" hint is supported.
+ if (AutofillHints.isValidHint(hint)) {
+ // Only add the field if the hint is supported by the type.
+ if (textValue != null) {
+ Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
+ View.AUTOFILL_TYPE_TEXT),
+ "Text is invalid type for hint '%s'", hint);
+ }
+ if (autofillOptions != null && listIndex != null &&
+ autofillOptions.length > listIndex) {
+ Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
+ View.AUTOFILL_TYPE_LIST),
+ "List is invalid type for hint '%s'", hint);
+ textValue = autofillOptions[listIndex].toString();
+ }
+ if (dateValue != null) {
+ Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
+ View.AUTOFILL_TYPE_DATE),
+ "Date is invalid type for hint '%s'", hint);
+ }
+ if (toggleValue != null) {
+ Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
+ View.AUTOFILL_TYPE_TOGGLE),
+ "Toggle is invalid type for hint '%s'", hint);
+ }
+ String datasetId = datasetWithFilledAutofillFields.autofillDataset.getId();
+ datasetWithFilledAutofillFields.add(new FilledAutofillField(datasetId,
+ hint, textValue, dateValue, toggleValue));
+ } else {
+ loge("Invalid hint: %s", hint);
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000..91f20ff8
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/ClientViewMetadata.java
@@ -0,0 +1,155 @@
+/*
+ * 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.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.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.
+ */
+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 List<String> getAllHints() {
+ if (mCachedAllHints == null) {
+ parseHints();
+ }
+ 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;
+ }
+ return autofillIds.toArray(new AutofillId[autofillIds.size()]);
+ }
+
+ public SaveInfo getSaveInfo() {
+ if (mCachedSaveInfo == null) {
+ int saveType = getSaveType();
+ AutofillId[] autofillIdsArray = getAutofillIdsArray();
+ // TODO: on MR1, creates a new SaveType without required ids
+ mCachedSaveInfo = new SaveInfo.Builder(saveType, autofillIdsArray).build();
+ }
+ return mCachedSaveInfo;
+ }
+
+ 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 String buildWebDomain() {
+ StringBuilder webDomainBuilder = new StringBuilder();
+ mStructureParser.parse((node) -> parseWebDomain(node, webDomainBuilder));
+ return webDomainBuilder.toString();
+ }
+
+ 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());
+ }
+ }
+ }
+ }
+
+ private void parseHints() {
+ List<String> allHints = new ArrayList<>();
+ mStructureParser.parse((node) -> getHints(node, allHints));
+ mCachedAllHints = allHints;
+ }
+
+ private void getHints(AssistStructure.ViewNode node, List<String> allHints) {
+ if (node.getAutofillHints() != null) {
+ String[] hints = node.getAutofillHints();
+ Collections.addAll(allHints, hints);
+ }
+ }
+
+ public void clearCache() {
+ mCachedAllHints = null;
+ mCachedSaveType = null;
+ mCachedSaveInfo = null;
+ mCachedAutofillIds = null;
+ }
+
+ private class AutofillSaveType {
+ int saveType;
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DataCallback.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/DataCallback.java
index 432d8c64..e7656028 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DataCallback.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/DataCallback.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource;
+package com.example.android.autofill.service.data;
public interface DataCallback<T> {
void onLoaded(T object);
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/FakeAutofillDataBuilder.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/FakeAutofillDataBuilder.java
new file mode 100644
index 00000000..580df901
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/FakeAutofillDataBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.example.android.autofill.service.AutofillHints;
+import com.example.android.autofill.service.model.AutofillDataset;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+import com.example.android.autofill.service.model.FilledAutofillField;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.UUID;
+
+public class FakeAutofillDataBuilder implements AutofillDataBuilder {
+ private final int mSeed;
+
+ public FakeAutofillDataBuilder(int seed) {
+ mSeed = seed;
+ }
+
+ @Override
+ public List<DatasetWithFilledAutofillFields> buildDatasetsByPartition(int datasetNumber) {
+ ImmutableList.Builder<DatasetWithFilledAutofillFields> listBuilder =
+ new ImmutableList.Builder<>();
+ for (int partition : AutofillHints.PARTITIONS) {
+ AutofillDataset autofillDataset = new AutofillDataset(UUID.randomUUID().toString(),
+ "dataset-" + datasetNumber + "." + partition);
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields =
+ buildCollectionForPartition(autofillDataset, partition);
+ listBuilder.add(datasetWithFilledAutofillFields);
+ }
+ return listBuilder.build();
+ }
+
+ private DatasetWithFilledAutofillFields buildCollectionForPartition(
+ AutofillDataset dataset, int partition) {
+ DatasetWithFilledAutofillFields datasetWithFilledAutofillFields =
+ new DatasetWithFilledAutofillFields();
+ datasetWithFilledAutofillFields.autofillDataset = dataset;
+ for (String hint : AutofillHints.getHints()) {
+ if (AutofillHints.matchesPartition(hint, partition)) {
+ FilledAutofillField fakeField = AutofillHints.generateFakeField(hint, mSeed,
+ dataset.getId());
+ datasetWithFilledAutofillFields.add(fakeField);
+ }
+ }
+ return datasetWithFilledAutofillFields;
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/DatasetAdapter.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/DatasetAdapter.java
new file mode 100644
index 00000000..043f4e36
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/DatasetAdapter.java
@@ -0,0 +1,167 @@
+/*
+ * 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.adapter;
+
+import android.app.assist.AssistStructure;
+import android.content.IntentSender;
+import android.service.autofill.Dataset;
+import android.support.annotation.NonNull;
+import android.util.MutableBoolean;
+import android.view.View;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.widget.RemoteViews;
+
+import com.example.android.autofill.service.AutofillHints;
+import com.example.android.autofill.service.StructureParser;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+import com.example.android.autofill.service.model.FilledAutofillField;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static com.example.android.autofill.service.util.Util.logv;
+import static com.example.android.autofill.service.util.Util.logw;
+import static java.util.stream.Collectors.toMap;
+
+public class DatasetAdapter {
+ private final StructureParser mStructureParser;
+
+ public DatasetAdapter(StructureParser structureParser) {
+ mStructureParser = structureParser;
+ }
+
+ /**
+ * Helper method for getting the index of a CharSequence object in an array.
+ */
+ private static int indexOf(@NonNull CharSequence[] array, CharSequence charSequence) {
+ int index = -1;
+ if (charSequence == null) {
+ return index;
+ }
+ for (int i = 0; i < array.length; i++) {
+ if (charSequence.equals(array[i])) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Wraps autofill data in a {@link Dataset} object which can then be sent back to the client.
+ */
+ public Dataset buildDataset(DatasetWithFilledAutofillFields datasetWithFilledAutofillFields,
+ RemoteViews remoteViews) {
+ return buildDataset(datasetWithFilledAutofillFields, remoteViews, null);
+ }
+
+ /**
+ * Wraps autofill data in a {@link Dataset} object with an IntentSender, which can then be
+ * sent back to the client.
+ */
+ public Dataset buildDataset(DatasetWithFilledAutofillFields datasetWithFilledAutofillFields,
+ RemoteViews remoteViews, IntentSender intentSender) {
+ Dataset.Builder datasetBuilder = new Dataset.Builder(remoteViews);
+ if (intentSender != null) {
+ datasetBuilder.setAuthentication(intentSender);
+ }
+ boolean setAtLeastOneValue = bindDataset(datasetWithFilledAutofillFields, datasetBuilder);
+ if (!setAtLeastOneValue) {
+ return null;
+ }
+ return datasetBuilder.build();
+ }
+
+ /**
+ * Build an autofill {@link Dataset} using saved data and the client's AssistStructure.
+ */
+ private boolean bindDataset(DatasetWithFilledAutofillFields datasetWithFilledAutofillFields,
+ Dataset.Builder datasetBuilder) {
+ MutableBoolean setValueAtLeastOnce = new MutableBoolean(false);
+ Map<String, FilledAutofillField> map = datasetWithFilledAutofillFields.filledAutofillFields
+ .stream().collect(toMap(FilledAutofillField::getHint, Function.identity()));
+ mStructureParser.parse((node) ->
+ parseAutofillFields(node, map, datasetBuilder, setValueAtLeastOnce)
+ );
+ return setValueAtLeastOnce.value;
+ }
+
+ private void parseAutofillFields(AssistStructure.ViewNode viewNode,
+ Map<String, FilledAutofillField> map, Dataset.Builder builder,
+ MutableBoolean setValueAtLeastOnce) {
+ String[] rawHints = viewNode.getAutofillHints();
+ if (rawHints == null || rawHints.length == 0) {
+ logv("No af hints at ViewNode - %s", viewNode.getIdEntry());
+ return;
+ }
+ List<String> hints = AutofillHints.convertToStoredHintNames(Arrays.asList(rawHints));
+ // For simplicity, even if the viewNode has multiple autofill hints, only look at the first
+ // one.
+ String autofillHint = hints.get(0);
+ FilledAutofillField field = map.get(autofillHint);
+ if (field == null) {
+ return;
+ }
+ AutofillId autofillId = viewNode.getAutofillId();
+ if (autofillId == null) {
+ logw("Autofill ID null for %s", viewNode.toString());
+ return;
+ }
+ int autofillType = viewNode.getAutofillType();
+ switch (autofillType) {
+ case View.AUTOFILL_TYPE_LIST:
+ CharSequence[] options = viewNode.getAutofillOptions();
+ int listValue = -1;
+ if (options != null) {
+ listValue = indexOf(viewNode.getAutofillOptions(), field.getTextValue());
+ }
+ if (listValue != -1) {
+ builder.setValue(autofillId, AutofillValue.forList(listValue));
+ setValueAtLeastOnce.value = true;
+ }
+ break;
+ case View.AUTOFILL_TYPE_DATE:
+ Long dateValue = field.getDateValue();
+ if (dateValue != null) {
+ builder.setValue(autofillId, AutofillValue.forDate(dateValue));
+ setValueAtLeastOnce.value = true;
+ }
+ break;
+ case View.AUTOFILL_TYPE_TEXT:
+ String textValue = field.getTextValue();
+ if (textValue != null) {
+ builder.setValue(autofillId, AutofillValue.forText(textValue));
+ setValueAtLeastOnce.value = true;
+ }
+ break;
+ case View.AUTOFILL_TYPE_TOGGLE:
+ Boolean toggleValue = field.getToggleValue();
+ if (toggleValue != null) {
+ builder.setValue(autofillId, AutofillValue.forToggle(toggleValue));
+ setValueAtLeastOnce.value = true;
+ }
+ break;
+ case View.AUTOFILL_TYPE_NONE:
+ default:
+ logw("Invalid autofill type - %d", autofillType);
+ break;
+ }
+ }
+}
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
new file mode 100644
index 00000000..f74a1999
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/adapter/ResponseAdapter.java
@@ -0,0 +1,159 @@
+/*
+ * 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.adapter;
+
+import android.content.Context;
+import android.content.IntentSender;
+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;
+
+import com.example.android.autofill.service.AuthActivity;
+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.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;
+
+ private final Context mContext;
+ private final DatasetAdapter mDatasetAdapter;
+ private final String mPackageName;
+ private final ClientViewMetadata mClientViewMetadata;
+ private final Bundle mPreviousClientState;
+
+ public ResponseAdapter(Context context, ClientViewMetadata clientViewMetadata,
+ String packageName, DatasetAdapter datasetAdapter, Bundle clientState) {
+ mContext = context;
+ mClientViewMetadata = clientViewMetadata;
+ mDatasetAdapter = datasetAdapter;
+ mPackageName = packageName;
+ mPreviousClientState = clientState;
+ }
+
+ /**
+ * Wraps autofill data in a Response object (essentially a series of Datasets) which can then
+ * be sent back to the client View.
+ */
+ public FillResponse buildResponse(List<DatasetWithFilledAutofillFields> datasets,
+ boolean datasetAuth) {
+ FillResponse.Builder responseBuilder = new FillResponse.Builder();
+ if (datasets != null) {
+ for (DatasetWithFilledAutofillFields datasetWithFilledAutofillFields : datasets) {
+ if (datasetWithFilledAutofillFields != null) {
+ Dataset dataset;
+ String datasetName = datasetWithFilledAutofillFields.autofillDataset
+ .getDatasetName();
+ if (datasetAuth) {
+ IntentSender intentSender = AuthActivity.getAuthIntentSenderForDataset(
+ mContext, datasetName);
+ RemoteViews remoteViews = RemoteViewsHelper.viewsWithAuth(
+ mPackageName, datasetName);
+ dataset = mDatasetAdapter.buildDataset(datasetWithFilledAutofillFields,
+ remoteViews, intentSender);
+ } else {
+ RemoteViews remoteViews = RemoteViewsHelper.viewsWithNoAuth(
+ mPackageName, datasetName);
+ dataset = mDatasetAdapter.buildDataset(datasetWithFilledAutofillFields,
+ remoteViews);
+ }
+ if (dataset != null) {
+ responseBuilder.addDataset(dataset);
+ }
+ }
+ }
+ }
+
+ 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");
+ 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);
+ responseBuilder.setSaveInfo(saveInfo);
+ return responseBuilder.build();
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/AutofillDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/AutofillDataSource.java
new file mode 100644
index 00000000..31b30b44
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/AutofillDataSource.java
@@ -0,0 +1,50 @@
+/*
+ * 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.source;
+
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+
+import java.util.List;
+
+public interface AutofillDataSource {
+
+ /**
+ * Asynchronously gets saved list of {@link DatasetWithFilledAutofillFields} that contains some
+ * objects that can autofill fields with these {@code autofillHints}.
+ */
+ void getAutofillDatasets(List<String> allAutofillHints,
+ DataCallback<List<DatasetWithFilledAutofillFields>> datasetsCallback);
+
+ /**
+ * Asynchronously gets a saved {@link DatasetWithFilledAutofillFields} for a specific
+ * {@code datasetName} that contains some objects that can autofill fields with these
+ * {@code autofillHints}.
+ */
+ void getAutofillDataset(List<String> allAutofillHints,
+ String datasetName, DataCallback<DatasetWithFilledAutofillFields> datasetsCallback);
+
+ /**
+ * Stores a collection of Autofill fields.
+ */
+ void saveAutofillDatasets(List<DatasetWithFilledAutofillFields>
+ datasetsWithFilledAutofillFields);
+
+ /**
+ * Clears all data.
+ */
+ void clear();
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DalService.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DalService.java
index 05b27e3f..b9cf6956 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DalService.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DalService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource;
+package com.example.android.autofill.service.data.source;
import com.example.android.autofill.service.model.DalCheck;
@@ -22,7 +22,6 @@ import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
-
public interface DalService {
@GET("/v1/assetlinks:check")
Call<DalCheck> check(@Query("source.web.site") String webDomain,
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DigitalAssetLinksDataSource.java
index 2070c53d..c01573b0 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/DigitalAssetLinksDataSource.java
@@ -13,14 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource;
+package com.example.android.autofill.service.data.source;
+import com.example.android.autofill.service.data.DataCallback;
import com.example.android.autofill.service.model.DalCheck;
import com.example.android.autofill.service.model.DalInfo;
/**
- * Helper format
- * <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a> needs.
+ * Data source for
+ * <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a>.
*/
public interface DigitalAssetLinksDataSource {
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/PackageVerificationDataSource.java
index 10930cfe..7e271e02 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/PackageVerificationDataSource.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource;
+package com.example.android.autofill.service.data.source;
public interface PackageVerificationDataSource {
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/DigitalAssetLinksRepository.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/DigitalAssetLinksRepository.java
index ba5f37e3..dfcecab4 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/DigitalAssetLinksRepository.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/DigitalAssetLinksRepository.java
@@ -13,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource.local;
+package com.example.android.autofill.service.data.source.local;
-import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
-import com.example.android.autofill.service.SecurityHelper;
-import com.example.android.autofill.service.datasource.DalService;
-import com.example.android.autofill.service.datasource.DataCallback;
-import com.example.android.autofill.service.datasource.DigitalAssetLinksDataSource;
+import com.example.android.autofill.service.util.SecurityHelper;
+import com.example.android.autofill.service.data.source.DalService;
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.data.source.DigitalAssetLinksDataSource;
import com.example.android.autofill.service.model.DalCheck;
import com.example.android.autofill.service.model.DalInfo;
import com.google.common.net.InternetDomainName;
@@ -47,12 +46,13 @@ public class DigitalAssetLinksRepository implements DigitalAssetLinksDataSource
private static final String PERMISSION_GET_LOGIN_CREDS = "common.get_login_creds";
private static final String PERMISSION_HANDLE_ALL_URLS = "common.handle_all_urls";
private static DigitalAssetLinksRepository sInstance;
- private final Context mContext;
+
+ private final PackageManager mPackageManager;
private final DalService mDalService;
private final HashMap<DalInfo, DalCheck> mCache;
- private DigitalAssetLinksRepository(Context context) {
- mContext = context;
+ private DigitalAssetLinksRepository(PackageManager packageManager) {
+ mPackageManager = packageManager;
mCache = new HashMap<>();
mDalService = new Retrofit.Builder()
.baseUrl(DAL_BASE_URL)
@@ -60,9 +60,9 @@ public class DigitalAssetLinksRepository implements DigitalAssetLinksDataSource
.create(DalService.class);
}
- public static DigitalAssetLinksRepository getInstance(Context context) {
+ public static DigitalAssetLinksRepository getInstance(PackageManager packageManager) {
if (sInstance == null) {
- sInstance = new DigitalAssetLinksRepository(context.getApplicationContext());
+ sInstance = new DigitalAssetLinksRepository(packageManager);
}
return sInstance;
}
@@ -80,8 +80,7 @@ public class DigitalAssetLinksRepository implements DigitalAssetLinksDataSource
mCache.clear();
}
- public void checkValid(DalInfo dalInfo,
- DataCallback<DalCheck> dalCheckDataCallback) {
+ public void checkValid(DalInfo dalInfo, DataCallback<DalCheck> dalCheckDataCallback) {
DalCheck dalCheck = mCache.get(dalInfo);
if (dalCheck != null) {
dalCheckDataCallback.onLoaded(dalCheck);
@@ -92,8 +91,8 @@ public class DigitalAssetLinksRepository implements DigitalAssetLinksDataSource
final String fingerprint;
try {
- PackageManager pm = mContext.getPackageManager();
- PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
+ PackageManager.GET_SIGNATURES);
fingerprint = SecurityHelper.getFingerprint(packageInfo, packageName);
} catch (Exception e) {
dalCheckDataCallback.onDataNotAvailable("Error getting fingerprint for %s",
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/LocalAutofillDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/LocalAutofillDataSource.java
new file mode 100644
index 00000000..3c326103
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/LocalAutofillDataSource.java
@@ -0,0 +1,148 @@
+/*
+ * 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.source.local;
+
+import android.content.SharedPreferences;
+import android.service.autofill.Dataset;
+
+import com.example.android.autofill.service.AutofillHints;
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.data.source.AutofillDataSource;
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
+import com.example.android.autofill.service.model.AutofillDataset;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+import com.example.android.autofill.service.model.FilledAutofillField;
+import com.example.android.autofill.service.util.AppExecutors;
+
+import java.util.List;
+
+import static com.example.android.autofill.service.util.Util.logw;
+
+public class LocalAutofillDataSource implements AutofillDataSource {
+ public static final String SHARED_PREF_KEY = "com.example.android.autofill"
+ + ".service.datasource.LocalAutofillDataSource";
+ private static final String DATASET_NUMBER_KEY = "datasetNumber";
+ private static final Object sLock = new Object();
+
+ private static LocalAutofillDataSource sInstance;
+
+ private final AutofillDao mAutofillDao;
+ private final SharedPreferences mSharedPreferences;
+ private final AppExecutors mAppExecutors;
+
+ private LocalAutofillDataSource(SharedPreferences sharedPreferences, AutofillDao autofillDao,
+ AppExecutors appExecutors) {
+ mSharedPreferences = sharedPreferences;
+ mAutofillDao = autofillDao;
+ mAppExecutors = appExecutors;
+ }
+
+ public static LocalAutofillDataSource getInstance(SharedPreferences sharedPreferences,
+ AutofillDao autofillDao, AppExecutors appExecutors) {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new LocalAutofillDataSource(sharedPreferences, autofillDao,
+ appExecutors);
+ }
+ return sInstance;
+ }
+ }
+
+ public static void clearInstance() {
+ synchronized (sLock) {
+ sInstance = null;
+ }
+ }
+
+ @Override
+ public void getAutofillDatasets(List<String> allAutofillHints,
+ DataCallback<List<DatasetWithFilledAutofillFields>> datasetsCallback) {
+ final List<String> storedAllAutofillHints =
+ AutofillHints.convertToStoredHintNames(allAutofillHints);
+ mAppExecutors.diskIO().execute(() -> {
+ List<DatasetWithFilledAutofillFields> datasetsWithFilledAutofillFields = mAutofillDao
+ .getFilledAutofillFields(storedAllAutofillHints);
+ mAppExecutors.mainThread().execute(() ->
+ datasetsCallback.onLoaded(datasetsWithFilledAutofillFields)
+ );
+ });
+ }
+
+ @Override
+ public void getAutofillDataset(List<String> allAutofillHints, String datasetName,
+ DataCallback<DatasetWithFilledAutofillFields> datasetsCallback) {
+ mAppExecutors.diskIO().execute(() -> {
+ // Room does not support TypeConverters for collections.
+ List<DatasetWithFilledAutofillFields> autofillDatasetFields =
+ mAutofillDao.getFilledAutofillFieldsWithName(allAutofillHints, datasetName);
+ if (autofillDatasetFields != null && !autofillDatasetFields.isEmpty()) {
+ if (autofillDatasetFields.size() > 1) {
+ logw("More than 1 dataset with name %s", datasetName);
+ }
+ DatasetWithFilledAutofillFields dataset = autofillDatasetFields.get(0);
+
+ mAppExecutors.mainThread().execute(() ->
+ datasetsCallback.onLoaded(dataset)
+ );
+ } else {
+ datasetsCallback.onDataNotAvailable("No data found.");
+ }
+ });
+ }
+
+
+ @Override
+ public void saveAutofillDatasets(List<DatasetWithFilledAutofillFields>
+ datasetsWithFilledAutofillFields) {
+ mAppExecutors.diskIO().execute(() -> {
+ for (DatasetWithFilledAutofillFields datasetWithFilledAutofillFields :
+ datasetsWithFilledAutofillFields) {
+ List<FilledAutofillField> filledAutofillFields =
+ datasetWithFilledAutofillFields.filledAutofillFields;
+ AutofillDataset autofillDataset = datasetWithFilledAutofillFields.autofillDataset;
+ mAutofillDao.saveAutofillDataset(autofillDataset);
+ mAutofillDao.saveFilledAutofillFields(filledAutofillFields);
+ }
+ });
+ incrementDatasetNumber();
+ }
+
+ @Override
+ public void clear() {
+ mAppExecutors.diskIO().execute(() -> {
+ mAutofillDao.clearAll();
+ mSharedPreferences.edit().putInt(DATASET_NUMBER_KEY, 0).apply();
+ });
+ }
+
+ /**
+ * For simplicity, {@link Dataset}s will be named in the form {@code dataset-X.P} where
+ * {@code X} means this was the Xth group of datasets saved, and {@code P} refers to the dataset
+ * partition number. This method returns the appropriate {@code X}.
+ */
+ public int getDatasetNumber() {
+ return mSharedPreferences.getInt(DATASET_NUMBER_KEY, 0);
+ }
+
+ /**
+ * Every time a dataset is saved, this should be called to increment the dataset number.
+ * (only important for this service's dataset naming scheme).
+ */
+ private void incrementDatasetNumber() {
+ mSharedPreferences.edit().putInt(DATASET_NUMBER_KEY, getDatasetNumber() + 1).apply();
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/SharedPrefsPackageVerificationRepository.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/SharedPrefsPackageVerificationRepository.java
index fc2993d3..5c462137 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/SharedPrefsPackageVerificationRepository.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/SharedPrefsPackageVerificationRepository.java
@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource.local;
+package com.example.android.autofill.service.data.source.local;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import com.example.android.autofill.service.SecurityHelper;
-import com.example.android.autofill.service.datasource.PackageVerificationDataSource;
+import com.example.android.autofill.service.util.SecurityHelper;
+import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
import static com.example.android.autofill.service.util.Util.logd;
import static com.example.android.autofill.service.util.Util.logw;
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/dao/AutofillDao.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/dao/AutofillDao.java
new file mode 100644
index 00000000..8a8c6a92
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/dao/AutofillDao.java
@@ -0,0 +1,71 @@
+/*
+ * 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.source.local.dao;
+
+import android.arch.persistence.room.Dao;
+import android.arch.persistence.room.Insert;
+import android.arch.persistence.room.OnConflictStrategy;
+import android.arch.persistence.room.Query;
+
+import com.example.android.autofill.service.model.AutofillDataset;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
+import com.example.android.autofill.service.model.FilledAutofillField;
+
+import java.util.Collection;
+import java.util.List;
+
+@Dao
+public interface AutofillDao {
+ /**
+ * Fetches a list of datasets associated to autofill fields on the page.
+ *
+ * @param allAutofillHints Filtering parameter; represents all of the hints associated with
+ * all of the views on the page.
+ */
+ @Query("SELECT DISTINCT id, datasetName FROM FilledAutofillField, AutofillDataset" +
+ " WHERE AutofillDataset.id = FilledAutofillField.datasetId" +
+ " AND FilledAutofillField.hint IN (:allAutofillHints)")
+ List<DatasetWithFilledAutofillFields> getFilledAutofillFields(List<String> allAutofillHints);
+
+ /**
+ * Fetches a list of datasets associated to autofill fields. It should only return a dataset
+ * if that dataset has an autofill field associate with the view the user is focused on, and
+ * if that dataset's name matches the name passed in.
+ *
+ * @param allAutofillHints Filtering parameter; represents all of the hints associated with
+ * all of the views on the page.
+ * @param datasetName Filtering parameter; only return datasets with this name.
+ */
+ @Query("SELECT id, datasetname FROM FilledAutofillField, AutofillDataset" +
+ " WHERE AutofillDataset.id = FilledAutofillField.datasetId" +
+ " AND AutofillDataset.datasetName = (:datasetName)" +
+ " AND FilledAutofillField.hint IN (:allAutofillHints)")
+ List<DatasetWithFilledAutofillFields> getFilledAutofillFieldsWithName(
+ List<String> allAutofillHints, String datasetName);
+
+ /**
+ * @param autofillFields Collection of autofill fields to be saved to the db.
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void saveFilledAutofillFields(Collection<FilledAutofillField> autofillFields);
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void saveAutofillDataset(AutofillDataset datasets);
+
+ @Query("DELETE FROM AutofillDataset")
+ void clearAll();
+} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/db/AutofillDatabase.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/db/AutofillDatabase.java
index a01e542b..83eda9e6 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/db/AutofillDatabase.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/data/source/local/db/AutofillDatabase.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.example.android.autofill.service.datasource.local.db;
+package com.example.android.autofill.service.data.source.local.db;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
-import com.example.android.autofill.service.datasource.local.dao.AutofillDao;
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
import com.example.android.autofill.service.model.AutofillDataset;
import com.example.android.autofill.service.model.FilledAutofillField;
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java
deleted file mode 100644
index 53e24738..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.datasource;
-
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-
-import java.util.HashMap;
-import java.util.List;
-
-public interface AutofillDataSource {
-
- /**
- * Gets saved FilledAutofillFieldCollection that contains some objects that can autofill fields
- * with these {@code autofillHints}.
- */
- void getFilledAutofillFieldCollection(
- List<String> focusedAutofillHints, List<String> allAutofillHints,
- DataCallback<HashMap<String, FilledAutofillFieldCollection>> datasetsCallback);
-
- /**
- * Stores a collection of Autofill fields.
- */
- void saveFilledAutofillFieldCollection(FilledAutofillFieldCollection
- filledAutofillFieldCollection);
-
- /**
- * Clears all data.
- */
- void clear();
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/LocalAutofillDataSource.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/LocalAutofillDataSource.java
deleted file mode 100644
index ce5857ce..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/LocalAutofillDataSource.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.datasource.local;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-import com.example.android.autofill.service.datasource.AutofillDataSource;
-import com.example.android.autofill.service.datasource.DataCallback;
-import com.example.android.autofill.service.datasource.local.dao.AutofillDao;
-import com.example.android.autofill.service.datasource.local.db.AutofillDatabase;
-import com.example.android.autofill.service.model.AutofillDataset;
-import com.example.android.autofill.service.model.FilledAutofillField;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-import com.example.android.autofill.service.util.AppExecutors;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-public class LocalAutofillDataSource implements AutofillDataSource {
- private static final String SHARED_PREF_KEY = "com.example.android.autofill"
- + ".service.datasource.LocalAutofillDataSource";
- private static final String DATASET_NUMBER_KEY = "datasetNumber";
- private static final Object sLock = new Object();
-
- private static LocalAutofillDataSource sInstance;
-
- private final AutofillDao mAutofillDao;
- private final SharedPreferences mSharedPreferences;
- private final AppExecutors mAppExecutors;
-
- private LocalAutofillDataSource(Context context, AppExecutors appExecutors) {
- mSharedPreferences = context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE);
- mAutofillDao = AutofillDatabase.getInstance(context).autofillDao();
- mAppExecutors = appExecutors;
- }
-
- public static LocalAutofillDataSource getInstance(Context context, AppExecutors appExecutors) {
- synchronized (sLock) {
- if (sInstance == null) {
- sInstance = new LocalAutofillDataSource(context, appExecutors);
- }
- return sInstance;
- }
- }
-
- @Override
- public void getFilledAutofillFieldCollection(List<String> focusedAutofillHints,
- List<String> allAutofillHints,
- DataCallback<HashMap<String, FilledAutofillFieldCollection>> datasetsCallback) {
- mAppExecutors.diskIO().execute(() -> {
- List<AutofillDao.AutofillDatasetField> autofillDatasetFields =
- mAutofillDao.getFilledAutofillFields(focusedAutofillHints, allAutofillHints);
- // Convert to hashmap; Room does not support TypeConverters for list.
- HashMap<String, FilledAutofillFieldCollection> map = new HashMap<>();
- for (AutofillDao.AutofillDatasetField autofillDatasetField : autofillDatasetFields) {
- String datasetName = autofillDatasetField.dataset.getDatasetName();
- if (!map.containsKey(datasetName)) {
- map.put(datasetName, new FilledAutofillFieldCollection(autofillDatasetField.dataset));
- }
- map.get(datasetName).add(autofillDatasetField.filledAutofillField);
- }
- mAppExecutors.mainThread().execute(() ->
- datasetsCallback.onLoaded(map)
- );
- });
- }
-
- @Override
- public void saveFilledAutofillFieldCollection(FilledAutofillFieldCollection
- filledAutofillFieldCollection) {
- mAppExecutors.diskIO().execute(() -> {
- Collection<FilledAutofillField> filledAutofillFields =
- filledAutofillFieldCollection.getAllFields();
- AutofillDataset autofillDataset = filledAutofillFieldCollection.getDataset();
- mAutofillDao.saveAutofillDataset(autofillDataset);
- mAutofillDao.saveFilledAutofillFields(filledAutofillFields);
- incrementDatasetNumber();
- });
- }
-
- @Override
- public void clear() {
- mAppExecutors.diskIO().execute(() -> {
- mAutofillDao.clearAll();
- mSharedPreferences.edit().putInt(DATASET_NUMBER_KEY, 0).apply();
- });
- }
-
- /**
- * For simplicity, datasets will be named in the form "dataset-X" where X means
- * this was the Xth dataset saved.
- */
- public int getDatasetNumber() {
- return mSharedPreferences.getInt(DATASET_NUMBER_KEY, 0);
- }
-
- /**
- * Every time a dataset is saved, this should be called to increment the dataset number.
- * (only important for this service's dataset naming scheme).
- */
- private void incrementDatasetNumber() {
- mSharedPreferences.edit().putInt(DATASET_NUMBER_KEY, getDatasetNumber() + 1).apply();
- }
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/dao/AutofillDao.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/dao/AutofillDao.java
deleted file mode 100644
index d68c4cfd..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/local/dao/AutofillDao.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.datasource.local.dao;
-
-import android.arch.persistence.room.Dao;
-import android.arch.persistence.room.Embedded;
-import android.arch.persistence.room.Insert;
-import android.arch.persistence.room.Query;
-import android.support.annotation.NonNull;
-
-import com.example.android.autofill.service.model.AutofillDataset;
-import com.example.android.autofill.service.model.FilledAutofillField;
-
-import java.util.Collection;
-import java.util.List;
-
-@Dao
-public interface AutofillDao {
- /**
- * Fetches a map of dataset names to associated autofill fields. It should only return a dataset
- * if that dataset has an autofill field associate with the view the user is focused on.
- *
- * @param focusedAutofillHints Filtering parameter; represents the hints associated with the
- * view the user is focused on.
- * @param allAutofillHints Filtering parameter; represents all of the hints associated with
- * all of the views on the page.
- * @return Map of dataset names to associated autofill fields.
- */
- @Query("SELECT * FROM FilledAutofillField, AutofillDataset" +
- " WHERE AutofillDataset.id = FilledAutofillField.datasetId" +
- " AND FilledAutofillField.hint IN (:allAutofillHints) AND AutofillDataset.id in " +
- "(SELECT datasetId FROM FilledAutofillField WHERE hint in (:focusedAutofillHints))")
- List<AutofillDatasetField> getFilledAutofillFields(
- List<String> focusedAutofillHints,
- List<String> allAutofillHints);
-
- /**
- * @param autofillFields Collection of autofill fields to be saved to the db.
- */
- @Insert
- void saveFilledAutofillFields(
- Collection<FilledAutofillField> autofillFields);
-
- @Insert
- void saveAutofillDataset(AutofillDataset datasets);
-
- @Query("DELETE FROM AutofillDataset")
- void clearAll();
-
- /**
- * Intermediate POJO class for Room.
- */
- class AutofillDatasetField {
- @Embedded public final AutofillDataset dataset;
- @Embedded public final FilledAutofillField filledAutofillField;
-
- public AutofillDatasetField(AutofillDataset dataset,
- FilledAutofillField filledAutofillField) {
- this.dataset = dataset;
- this.filledAutofillField = filledAutofillField;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- AutofillDatasetField that = (AutofillDatasetField) o;
-
- if (dataset != null ? !dataset.equals(that.dataset) : that.dataset != null)
- return false;
- return filledAutofillField != null ? filledAutofillField.equals(
- that.filledAutofillField) : that.filledAutofillField == null;
- }
-
- @Override
- public int hashCode() {
- int result = dataset != null ? dataset.hashCode() : 0;
- result = 31 * result + (filledAutofillField != null ?
- filledAutofillField.hashCode() : 0);
- return result;
- }
- }
-} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/AutofillDataset.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/AutofillDataset.java
index 2f36ec85..e7bd3058 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/AutofillDataset.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/AutofillDataset.java
@@ -35,11 +35,13 @@ public class AutofillDataset {
mDatasetName = datasetName;
}
- @NonNull public String getId() {
+ @NonNull
+ public String getId() {
return mId;
}
- @NonNull public String getDatasetName() {
+ @NonNull
+ public String getDatasetName() {
return mDatasetName;
}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DalInfo.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DalInfo.java
index 653983fa..44002ca5 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DalInfo.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DalInfo.java
@@ -16,7 +16,7 @@
package com.example.android.autofill.service.model;
-import static com.example.android.autofill.service.datasource.local.DigitalAssetLinksRepository.getCanonicalDomain;
+import static com.example.android.autofill.service.data.source.local.DigitalAssetLinksRepository.getCanonicalDomain;
public class DalInfo {
private final String mWebDomain;
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DatasetWithFilledAutofillFields.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DatasetWithFilledAutofillFields.java
new file mode 100644
index 00000000..06b529fe
--- /dev/null
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/DatasetWithFilledAutofillFields.java
@@ -0,0 +1,60 @@
+/*
+ * 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.model;
+
+import android.arch.persistence.room.Embedded;
+import android.arch.persistence.room.Relation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DatasetWithFilledAutofillFields {
+ @Embedded
+ public AutofillDataset autofillDataset;
+
+ @Relation(parentColumn = "id", entityColumn = "datasetId", entity = FilledAutofillField.class)
+ public List<FilledAutofillField> filledAutofillFields;
+
+ public void add(FilledAutofillField filledAutofillField) {
+ if (filledAutofillFields == null) {
+ this.filledAutofillFields = new ArrayList<>();
+ }
+ this.filledAutofillFields.add(filledAutofillField);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ DatasetWithFilledAutofillFields that = (DatasetWithFilledAutofillFields) o;
+
+ if (autofillDataset != null ? !autofillDataset.equals(that.autofillDataset) :
+ that.autofillDataset != null)
+ return false;
+ return filledAutofillFields != null ?
+ filledAutofillFields.equals(that.filledAutofillFields) :
+ that.filledAutofillFields == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = autofillDataset != null ? autofillDataset.hashCode() : 0;
+ result = 31 * result + (filledAutofillFields != null ? filledAutofillFields.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
index 6cb93602..ba474d2e 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
@@ -20,25 +20,9 @@ import android.arch.persistence.room.Entity;
import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.Ignore;
import android.support.annotation.NonNull;
-import android.view.View;
-
-import com.example.android.autofill.service.AutofillHints;
-import com.google.common.base.Preconditions;
-
-import java.util.ArrayList;
-import java.util.List;
import javax.annotation.Nullable;
-import static com.example.android.autofill.service.AutofillHints.convertToStoredHintNames;
-import static com.example.android.autofill.service.AutofillHints.filterForSupportedHints;
-import static com.example.android.autofill.service.AutofillHints.isW3cAddressType;
-import static com.example.android.autofill.service.AutofillHints.isW3cSectionPrefix;
-import static com.example.android.autofill.service.AutofillHints.isW3cTypeHint;
-import static com.example.android.autofill.service.AutofillHints.isW3cTypePrefix;
-import static com.example.android.autofill.service.util.Util.logd;
-import static com.example.android.autofill.service.util.Util.loge;
-
@Entity(primaryKeys = {"datasetId", "hint"}, foreignKeys = @ForeignKey(
entity = AutofillDataset.class, parentColumns = "id", childColumns = "datasetId",
onDelete = ForeignKey.CASCADE))
@@ -102,75 +86,6 @@ public class FilledAutofillField {
this(datasetId, hint, null, null, null);
}
-
- @Nullable
- public static List<FilledAutofillField> build(String datasetId, String[] hints,
- @Nullable String textValue, @Nullable Long dateValue, @Nullable Boolean toggleValue,
- @Nullable CharSequence[] autofillOptions, @Nullable Integer listIndex) {
- String[] filteredHints = filterForSupportedHints(hints);
- convertToStoredHintNames(filteredHints);
- List<FilledAutofillField> fields = new ArrayList<>();
- if (filteredHints == null) {
- return null;
- }
- String nextHint = null;
- for (int i = 0; i < filteredHints.length; i++) {
- String hint = filteredHints[i];
- if (i < filteredHints.length - 1) {
- nextHint = filteredHints[i + 1];
- }
- // First convert the compound W3C autofill hints
- if (isW3cSectionPrefix(hint) && i < filteredHints.length - 1) {
- hint = filteredHints[++i];
- logd("Hint is a W3C section prefix; using %s instead", hint);
- if (i < filteredHints.length - 1) {
- nextHint = filteredHints[i + 1];
- }
- }
- if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint)) {
- hint = nextHint;
- i++;
- logd("Hint is a W3C type prefix; using %s instead", hint);
- }
- if (isW3cAddressType(hint) && nextHint != null) {
- hint = nextHint;
- i++;
- logd("Hint is a W3C address prefix; using %s instead", hint);
- }
- // Then check if the "actual" hint is supported.
- if (AutofillHints.isValidHint(hint)) {
- // Only add the field if the hint is supported by the type.
- if (textValue != null) {
- Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
- View.AUTOFILL_TYPE_TEXT),
- "Text is invalid type for hint '%s'", hint);
- }
- if (autofillOptions != null && listIndex != null &&
- autofillOptions.length > listIndex) {
- Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
- View.AUTOFILL_TYPE_LIST),
- "List is invalid type for hint '%s'", hint);
- textValue = autofillOptions[listIndex].toString();
- }
- if (dateValue != null) {
- Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
- View.AUTOFILL_TYPE_DATE),
- "Date is invalid type for hint '%s'", hint);
- }
- if (toggleValue != null) {
- Preconditions.checkArgument(AutofillHints.isValidTypeForHints(hint,
- View.AUTOFILL_TYPE_TOGGLE),
- "Toggle is invalid type for hint '%s'", hint);
- }
- fields.add(new FilledAutofillField(datasetId, filteredHints[i], textValue,
- dateValue, toggleValue));
- } else {
- loge("Invalid hint: %s", hint);
- }
- }
- return fields;
- }
-
@NonNull
public String getDatasetId() {
return mDatasetId;
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java
deleted file mode 100644
index 0413653d..00000000
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.model;
-
-import android.service.autofill.Dataset;
-import android.support.annotation.NonNull;
-import android.view.View;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-
-import com.example.android.autofill.service.AutofillFieldMetadata;
-import com.example.android.autofill.service.AutofillFieldMetadataCollection;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-import static com.example.android.autofill.service.util.Util.logw;
-
-/**
- * FilledAutofillFieldCollection is the model that holds all of the data on a client app's page,
- * plus the dataset name associated with it.
- */
-public final class FilledAutofillFieldCollection {
-
- private final HashMap<String, FilledAutofillField> mHintMap;
- private final AutofillDataset mDataset;
-
- public FilledAutofillFieldCollection(AutofillDataset dataset) {
- mDataset = dataset;
- mHintMap = new HashMap<>();
- }
-
- /**
- * Adds a {@code FilledAutofillField} to the collection, indexed by all of its hints.
- */
- public void add(@NonNull FilledAutofillField filledAutofillField) {
- mHintMap.put(filledAutofillField.getHint(), filledAutofillField);
- }
-
- /**
- * Adds a {@code List<FilledAutofillField>} to the collection, indexed by all of its hints.
- */
- public void add(@NonNull List<FilledAutofillField> filledAutofillFields) {
- for (FilledAutofillField field : filledAutofillFields) {
- add(field);
- }
- }
-
- public Collection<FilledAutofillField> getAllFields() {
- return mHintMap.values();
- }
-
- /**
- * Populates a {@link Dataset.Builder} with appropriate values for each {@link AutofillId}
- * in a {@code AutofillFieldMetadataCollection}.
- * <p>
- * In other words, it constructs an autofill
- * {@link Dataset.Builder} by applying saved values (from this {@code FilledAutofillFieldCollection})
- * to Views specified in a {@code AutofillFieldMetadataCollection}, which represents the current
- * page the user is on.
- */
- public boolean applyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection,
- Dataset.Builder datasetBuilder) {
- boolean setValueAtLeastOnce = false;
- List<String> allHints = autofillFieldMetadataCollection.getAllHints();
- for (int hintIndex = 0; hintIndex < allHints.size(); hintIndex++) {
- String hint = allHints.get(hintIndex);
- List<AutofillFieldMetadata> fillableAutofillFields =
- autofillFieldMetadataCollection.getFieldsForHint(hint);
- if (fillableAutofillFields == null) {
- continue;
- }
- for (int autofillFieldIndex = 0; autofillFieldIndex < fillableAutofillFields.size(); autofillFieldIndex++) {
- FilledAutofillField filledAutofillField = mHintMap.get(hint);
- if (filledAutofillField == null) {
- continue;
- }
- AutofillFieldMetadata autofillFieldMetadata = fillableAutofillFields.get(autofillFieldIndex);
- AutofillId autofillId = autofillFieldMetadata.getId();
- int autofillType = autofillFieldMetadata.getAutofillType();
- switch (autofillType) {
- case View.AUTOFILL_TYPE_LIST:
- int listValue = autofillFieldMetadata.getAutofillOptionIndex(
- filledAutofillField.getTextValue());
- if (listValue != -1) {
- datasetBuilder.setValue(autofillId, AutofillValue.forList(listValue));
- setValueAtLeastOnce = true;
- }
- break;
- case View.AUTOFILL_TYPE_DATE:
- Long dateValue = filledAutofillField.getDateValue();
- if (dateValue != null) {
- datasetBuilder.setValue(autofillId, AutofillValue.forDate(dateValue));
- setValueAtLeastOnce = true;
- }
- break;
- case View.AUTOFILL_TYPE_TEXT:
- String textValue = filledAutofillField.getTextValue();
- if (textValue != null) {
- datasetBuilder.setValue(autofillId, AutofillValue.forText(textValue));
- setValueAtLeastOnce = true;
- }
- break;
- case View.AUTOFILL_TYPE_TOGGLE:
- Boolean toggleValue = filledAutofillField.getToggleValue();
- if (toggleValue != null) {
- datasetBuilder.setValue(autofillId, AutofillValue.forToggle(toggleValue));
- setValueAtLeastOnce = true;
- }
- break;
- case View.AUTOFILL_TYPE_NONE:
- default:
- logw("Invalid autofill type - %d", autofillType);
- break;
- }
- }
- }
- return setValueAtLeastOnce;
- }
-
- public AutofillDataset getDataset() {
- return mDataset;
- }
-}
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
index 70b8ae20..5ccc13ae 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
@@ -15,8 +15,10 @@
*/
package com.example.android.autofill.service.settings;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
@@ -35,14 +37,19 @@ import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;
-import com.example.android.autofill.service.AutofillHints;
import com.example.android.autofill.service.R;
-import com.example.android.autofill.service.datasource.PackageVerificationDataSource;
+import com.example.android.autofill.service.data.AutofillDataBuilder;
+import com.example.android.autofill.service.data.FakeAutofillDataBuilder;
+import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
+import com.example.android.autofill.service.data.source.local.LocalAutofillDataSource;
+import com.example.android.autofill.service.data.source.local.SharedPrefsPackageVerificationRepository;
+import com.example.android.autofill.service.data.source.local.dao.AutofillDao;
+import com.example.android.autofill.service.data.source.local.db.AutofillDatabase;
+import com.example.android.autofill.service.model.DatasetWithFilledAutofillFields;
import com.example.android.autofill.service.util.AppExecutors;
import com.example.android.autofill.service.util.Util;
-import com.example.android.autofill.service.datasource.local.SharedPrefsPackageVerificationRepository;
-import com.example.android.autofill.service.datasource.local.LocalAutofillDataSource;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+
+import java.util.List;
import static com.example.android.autofill.service.util.Util.logd;
import static com.example.android.autofill.service.util.Util.logw;
@@ -58,8 +65,11 @@ public class SettingsActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multidataset_service_settings_activity);
- mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(this,
- new AppExecutors());
+ SharedPreferences localAfDataSourceSharedPrefs =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ AutofillDao autofillDao = AutofillDatabase.getInstance(this).autofillDao();
+ mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(localAfDataSourceSharedPrefs,
+ autofillDao, new AppExecutors());
mAutofillManager = getSystemService(AutofillManager.class);
mPackageVerificationDataSource = SharedPrefsPackageVerificationRepository.getInstance(this);
@@ -155,7 +165,7 @@ public class SettingsActivity extends AppCompatActivity {
.setView(numberOfDatasetsPicker)
.setPositiveButton(R.string.settings_ok, (dialog, which) -> {
int numOfDatasets = numberOfDatasetsPicker.getValue();
- boolean success = buildAndSaveMockedAutofillFieldCollection(numOfDatasets);
+ boolean success = buildAndSaveMockedAutofillFieldCollections(numOfDatasets);
dialog.dismiss();
if (success) {
Snackbar.make(SettingsActivity.this.findViewById(R.id.settings_layout),
@@ -168,21 +178,18 @@ public class SettingsActivity extends AppCompatActivity {
.create();
}
- /**
- * Builds mock autofill data and saves it to repository.
- */
- private boolean buildAndSaveMockedAutofillFieldCollection(int numOfDatasets) {
+ public boolean buildAndSaveMockedAutofillFieldCollections(int numOfDatasets) {
if (numOfDatasets < 0 || numOfDatasets > 10) {
logw("Number of Datasets (%d) out of range.", numOfDatasets);
return false;
}
for (int i = 0; i < numOfDatasets; i++) {
- for (int partition : AutofillHints.PARTITIONS) {
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- AutofillHints.getFakeFieldCollection(partition, i * 2);
- mLocalAutofillDataSource.saveFilledAutofillFieldCollection(
- filledAutofillFieldCollection);
- }
+ int datasetNumber = mLocalAutofillDataSource.getDatasetNumber();
+ AutofillDataBuilder autofillDataBuilder = new FakeAutofillDataBuilder(datasetNumber);
+ List<DatasetWithFilledAutofillFields> datasetsWithFilledAutofillFields =
+ autofillDataBuilder.buildDatasetsByPartition(datasetNumber);
+ // Save datasets to database.
+ mLocalAutofillDataSource.saveAutofillDatasets(datasetsWithFilledAutofillFields);
}
return true;
}
@@ -286,12 +293,12 @@ public class SettingsActivity extends AppCompatActivity {
logd(TAG, "onActivityResult(): req=%s", requestCode);
switch (requestCode) {
case REQUEST_CODE_SET_DEFAULT:
- defaultServiceSet(resultCode);
+ onDefaultServiceSet(resultCode);
break;
}
}
- private void defaultServiceSet(int resultCode) {
+ private void onDefaultServiceSet(int resultCode) {
logd(TAG, "resultCode=%d", resultCode);
switch (resultCode) {
case RESULT_OK:
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/SecurityHelper.java
index fb3cf48a..5311a5f9 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/SecurityHelper.java
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofill.service;
+package com.example.android.autofill.service.util;
-import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
@@ -35,7 +34,7 @@ import java.security.cert.X509Certificate;
public final class SecurityHelper {
private SecurityHelper() {
- throw new UnsupportedOperationException("provides static methods only");
+ throw new UnsupportedOperationException("Provides static methods only.");
}
/**
diff --git a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/Util.java b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/Util.java
index f63bfb51..d7b5b45b 100644
--- a/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/Util.java
+++ b/input/autofill/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/util/Util.java
@@ -37,14 +37,11 @@ import java.util.Set;
public final class Util {
- private static final String TAG = "AutofillSample";
public static final String EXTRA_DATASET_NAME = "dataset_name";
public static final String EXTRA_FOR_RESPONSE = "for_response";
public static final NodeFilter AUTOFILL_ID_FILTER = (node, id) ->
id.equals(node.getAutofillId());
-
- public enum LogLevel { OFF, DEBUG, VERBOSE }
-
+ private static final String TAG = "AutofillSample";
public static LogLevel sLoggingLevel = LogLevel.OFF;
private static void bundleToString(StringBuilder builder, Bundle data) {
@@ -282,6 +279,8 @@ public final class Util {
sLoggingLevel = level;
}
+ public enum LogLevel {OFF, DEBUG, VERBOSE}
+
/**
* Helper interface used to filter Assist nodes.
*/