Update AutoFill sample
Test: Built locally
Bug: 114236837
Change-Id: I6e5202614d5987f4983887cf704e53e312474292
diff --git a/prebuilts/gradle/AutofillFramework/Application/build.gradle b/prebuilts/gradle/AutofillFramework/Application/build.gradle
index 0477823..fc7d19e 100644
--- a/prebuilts/gradle/AutofillFramework/Application/build.gradle
+++ b/prebuilts/gradle/AutofillFramework/Application/build.gradle
@@ -4,15 +4,14 @@
// keep boilerplate and common code separate from
// the main sample code.
List<String> dirs = [
- 'main'] // main sample code; look here for the interesting stuff.
+ 'main'] // main sample code; look here for the interesting stuff.
android {
- compileSdkVersion 26
- buildToolsVersion '26.0.2'
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 26
- targetSdkVersion 26
+ targetSdkVersion 28
}
compileOptions {
@@ -38,11 +37,11 @@
}
dependencies {
- implementation "com.android.support:support-v4:26.1.0"
- implementation "com.android.support:support-v13:26.1.0"
- implementation "com.android.support:cardview-v7:26.1.0"
- implementation "com.android.support:appcompat-v7:26.1.0"
- implementation 'com.android.support:design:26.1.0'
+ implementation "com.android.support:support-v4:28.0.0-alpha1"
+ implementation "com.android.support:support-v13:28.0.0-alpha1"
+ implementation "com.android.support:cardview-v7:28.0.0-alpha1"
+ implementation "com.android.support:appcompat-v7:28.0.0-alpha1"
+ implementation 'com.android.support:design:28.0.0-alpha1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation group: 'com.google.guava', name: 'guava', version: '22.0-android'
}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/AndroidManifest.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/AndroidManifest.xml
index 4f4a356..59368c6 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/AndroidManifest.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/AndroidManifest.xml
@@ -18,58 +18,47 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
- android:theme="@style/Theme.AppCompat.Light">
+ android:theme="@style/AppTheme">
<activity
android:name="com.example.android.autofill.app.MainActivity"
android:taskAffinity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity
- android:name="com.example.android.autofill.app.StandardSignInActivity"
- android:taskAffinity=".StandardSignInActivity" />
- <activity
- android:name="com.example.android.autofill.app.StandardAutoCompleteSignInActivity"
- android:taskAffinity=".StandardAutoCompleteSignInActivity" />
- <activity
- android:name="com.example.android.autofill.app.VirtualSignInActivity"
- android:taskAffinity=".VirtualSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.StandardSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.StandardAutoCompleteSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.VirtualSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.VirtualCompatModeSignInActivity" />
<activity android:name="com.example.android.autofill.app.WelcomeActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.CreditCardActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.CreditCardSpinnersActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.EmailComposeActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.CreditCardCompoundViewActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.CreditCardDatePickerActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.CreditCardAntiPatternActivity" />
<activity
- android:name="com.example.android.autofill.app.CreditCardActivity"
- android:taskAffinity=".CreditCardActivity" />
- <activity
- android:name="com.example.android.autofill.app.CreditCardSpinnersActivity"
- android:taskAffinity=".CreditCardSpinnersActivity" />
- <activity
- android:name="com.example.android.autofill.app.EmailComposeActivity"
- android:taskAffinity=".EmailComposeActivity" />
- <activity
- android:name="com.example.android.autofill.app.CreditCardCompoundViewActivity"
- android:taskAffinity=".CreditCardCompoundViewActivity" />
- <activity
- android:name="com.example.android.autofill.app.CreditCardDatePickerActivity"
- android:taskAffinity=".CreditCardDatePickerActivity" />
- <activity
- android:name="com.example.android.autofill.app.CreditCardAntiPatternActivity"
- android:taskAffinity=".CreditCardAntiPatternActivity" />
- <activity
- android:name="com.example.android.autofill.app.MultiplePartitionsActivity"
- android:taskAffinity=".MultiplePartitionsActivity"
+ android:name="com.example.android.autofill.app.edgecases.MultiplePartitionsActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
- <activity
- android:name="com.example.android.autofill.app.WebViewSignInActivity"
- android:taskAffinity=".WebViewSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.WebViewSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.MultipleStepsSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.MultipleStepsCreditCardActivity" />
+ <activity android:name="com.example.android.autofill.app.commoncases.RecyclerViewActivity" />
+ <activity android:name="com.example.android.autofill.app.antipatterns.BadViewStructureCreationSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.antipatterns.UsernameOnlyActivity" />
+ <activity android:name="com.example.android.autofill.app.antipatterns.PasswordOnlyActivity" />
+ <activity android:name="com.example.android.autofill.app.antipatterns.HintlessSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.antipatterns.CallbackLessAutoCompleteSignInActivity" />
+ <activity android:name="com.example.android.autofill.app.edgecases.CustomThemeSignInActivity"
+ android:theme="@style/CustomAutofilledHighlightTheme" />
</application>
</manifest>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CommonUtil.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CommonUtil.java
deleted file mode 100644
index d68a371..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CommonUtil.java
+++ /dev/null
@@ -1,154 +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.app;
-
-import android.app.assist.AssistStructure;
-import android.app.assist.AssistStructure.ViewNode;
-import android.app.assist.AssistStructure.WindowNode;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewStructure.HtmlInfo;
-import android.view.autofill.AutofillValue;
-
-import java.util.Arrays;
-import java.util.Set;
-
-public final class CommonUtil {
-
- public static final String TAG = "AutofillSample";
- public static final boolean DEBUG = true;
- public static final boolean VERBOSE = false;
- public static final String EXTRA_DATASET_NAME = "dataset_name";
- public static final String EXTRA_FOR_RESPONSE = "for_response";
-
- private static void bundleToString(StringBuilder builder, Bundle data) {
- final Set<String> keySet = data.keySet();
- builder.append("[Bundle with ").append(keySet.size()).append(" keys:");
- for (String key : keySet) {
- builder.append(' ').append(key).append('=');
- Object value = data.get(key);
- if ((value instanceof Bundle)) {
- bundleToString(builder, (Bundle) value);
- } else {
- builder.append((value instanceof Object[])
- ? Arrays.toString((Object[]) value) : value);
- }
- }
- builder.append(']');
- }
-
- public static String bundleToString(Bundle data) {
- if (data == null) {
- return "N/A";
- }
- final StringBuilder builder = new StringBuilder();
- bundleToString(builder, data);
- return builder.toString();
- }
-
- public static String getTypeAsString(int type) {
- switch (type) {
- case View.AUTOFILL_TYPE_TEXT:
- return "TYPE_TEXT";
- case View.AUTOFILL_TYPE_LIST:
- return "TYPE_LIST";
- case View.AUTOFILL_TYPE_NONE:
- return "TYPE_NONE";
- case View.AUTOFILL_TYPE_TOGGLE:
- return "TYPE_TOGGLE";
- case View.AUTOFILL_TYPE_DATE:
- return "TYPE_DATE";
- }
- return "UNKNOWN_TYPE";
- }
-
- private static String getAutofillValueAndTypeAsString(AutofillValue value) {
- if (value == null) return "null";
-
- StringBuilder builder = new StringBuilder(value.toString()).append('(');
- if (value.isText()) {
- builder.append("isText");
- } else if (value.isDate()) {
- builder.append("isDate");
- } else if (value.isToggle()) {
- builder.append("isToggle");
- } else if (value.isList()) {
- builder.append("isList");
- }
- return builder.append(')').toString();
- }
-
- public static void dumpStructure(AssistStructure structure) {
- int nodeCount = structure.getWindowNodeCount();
- Log.v(TAG, "dumpStructure(): component=" + structure.getActivityComponent()
- + " numberNodes=" + nodeCount);
- for (int i = 0; i < nodeCount; i++) {
- Log.v(TAG, "node #" + i);
- WindowNode node = structure.getWindowNodeAt(i);
- dumpNode(" ", node.getRootViewNode());
- }
- }
-
- private static void dumpNode(String prefix, ViewNode node) {
- StringBuilder builder = new StringBuilder();
- builder.append(prefix)
- .append("autoFillId: ").append(node.getAutofillId())
- .append("\tidEntry: ").append(node.getIdEntry())
- .append("\tid: ").append(node.getId())
- .append("\tclassName: ").append(node.getClassName())
- .append('\n');
-
- builder.append(prefix)
- .append("focused: ").append(node.isFocused())
- .append("\tvisibility").append(node.getVisibility())
- .append("\tchecked: ").append(node.isChecked())
- .append("\twebDomain: ").append(node.getWebDomain())
- .append("\thint: ").append(node.getHint())
- .append('\n');
-
- HtmlInfo htmlInfo = node.getHtmlInfo();
-
- if (htmlInfo != null) {
- builder.append(prefix)
- .append("HTML TAG: ").append(htmlInfo.getTag())
- .append(" attrs: ").append(htmlInfo.getAttributes())
- .append('\n');
- }
-
- String[] afHints = node.getAutofillHints();
- CharSequence[] options = node.getAutofillOptions();
- builder.append(prefix).append("afType: ").append(getTypeAsString(node.getAutofillType()))
- .append("\tafValue:")
- .append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
- .append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
- .append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
- .append("\tinputType:").append(node.getInputType())
- .append('\n');
-
- int numberChildren = node.getChildCount();
- builder.append(prefix).append("# children: ").append(numberChildren)
- .append("\ttext: ").append(node.getText())
- .append('\n');
-
- Log.v(TAG, builder.toString());
- final String prefix2 = prefix + " ";
- for (int i = 0; i < numberChildren; i++) {
- Log.v(TAG, prefix + "child #" + i);
- dumpNode(prefix2, node.getChildAt(i));
- }
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardActivity.java
deleted file mode 100644
index 8322eb5..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardActivity.java
+++ /dev/null
@@ -1,82 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.EditText;
-
-
-public class CreditCardActivity extends AppCompatActivity {
-
- private EditText mCcExpDayView;
- private EditText mCcExpMonthView;
- private EditText mCcExpYearView;
- private EditText mCcNumber;
- private EditText mCcSecurityCode;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, CreditCardActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.credit_card_activity);
- mCcExpDayView = findViewById(R.id.expirationDay);
- mCcExpMonthView = findViewById(R.id.expirationMonth);
- mCcExpYearView = findViewById(R.id.expirationYear);
- mCcNumber = findViewById(R.id.creditCardNumberField);
- mCcSecurityCode = findViewById(R.id.creditCardSecurityCode);
- findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- submit();
- }
- });
- findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getSystemService(AutofillManager.class).cancel();
- resetFields();
- }
- });
- }
-
- private void resetFields() {
- mCcExpDayView.setText("");
- mCcExpMonthView.setText("");
- mCcExpYearView.setText("");
- mCcNumber.setText("");
- mCcSecurityCode.setText("");
- }
-
- /**
- * Launches new Activity and finishes, triggering an autofill save request if the user entered
- * any new data.
- */
- private void submit() {
- Intent intent = WelcomeActivity.getStartActivityIntent(this);
- startActivity(intent);
- finish();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardAntiPatternActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardAntiPatternActivity.java
deleted file mode 100644
index a1cb599..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardAntiPatternActivity.java
+++ /dev/null
@@ -1,75 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.EditText;
-
-public class CreditCardAntiPatternActivity extends AppCompatActivity {
-
- private EditText mCcExpDateView;
- private EditText mCcExpNumber;
- private EditText mCcSecurityCode;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, CreditCardAntiPatternActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.credit_card_anti_pattern_activity);
- mCcExpDateView = findViewById(R.id.creditCardExpirationView);
- mCcExpNumber = findViewById(R.id.creditCardNumberField);
- mCcSecurityCode = findViewById(R.id.creditCardSecurityCode);
- findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- submit();
- }
- });
- findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getSystemService(AutofillManager.class).cancel();
- resetFields();
- }
- });
- }
-
- private void resetFields() {
- mCcExpDateView.setText("");
- mCcExpNumber.setText("");
- mCcSecurityCode.setText("");
- }
-
- /**
- * Launches new Activity and finishes, triggering an autofill save request if the user entered
- * any new data.
- */
- private void submit() {
- Intent intent = WelcomeActivity.getStartActivityIntent(this);
- startActivity(intent);
- finish();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardCompoundViewActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardCompoundViewActivity.java
deleted file mode 100644
index 7a936b9..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardCompoundViewActivity.java
+++ /dev/null
@@ -1,75 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.EditText;
-
-public class CreditCardCompoundViewActivity extends AppCompatActivity {
-
- private CreditCardExpirationDateCompoundView mCcExpDateView;
- private EditText mCcExpNumber;
- private EditText mCcSecurityCode;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, CreditCardCompoundViewActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.credit_card_compound_view_activity);
- mCcExpDateView = findViewById(R.id.creditCardExpirationView);
- mCcExpNumber = findViewById(R.id.creditCardNumberField);
- mCcSecurityCode = findViewById(R.id.creditCardSecurityCode);
- findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- submit();
- }
- });
- findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getSystemService(AutofillManager.class).cancel();
- resetFields();
- }
- });
- }
-
- private void resetFields() {
- mCcExpDateView.reset();
- mCcExpNumber.setText("");
- mCcSecurityCode.setText("");
- }
-
- /**
- * Launches new Activity and finishes, triggering an autofill save request if the user entered
- * any new data.
- */
- private void submit() {
- Intent intent = WelcomeActivity.getStartActivityIntent(this);
- startActivity(intent);
- finish();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardDatePickerActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardDatePickerActivity.java
deleted file mode 100644
index 6b575f8..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardDatePickerActivity.java
+++ /dev/null
@@ -1,89 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.EditText;
-
-import static com.example.android.autofill.app.CommonUtil.TAG;
-
-public class CreditCardDatePickerActivity extends AppCompatActivity {
-
- private CreditCardExpirationDatePickerView mCcExpDateView;
- private EditText mCcExpNumber;
- private EditText mCcSecurityCode;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, CreditCardDatePickerActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.credit_card_date_picker_activity);
- mCcExpDateView = findViewById(R.id.creditCardExpirationView);
- mCcExpNumber = findViewById(R.id.creditCardNumberField);
- mCcSecurityCode = findViewById(R.id.creditCardSecurityCode);
- findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- submit();
- }
- });
- findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getSystemService(AutofillManager.class).cancel();
- resetFields();
- }
- });
-
- mCcExpDateView.reset();
- }
-
- private void resetFields() {
- mCcExpDateView.reset();
- mCcExpNumber.setText("");
- mCcSecurityCode.setText("");
- }
-
- public void showDatePickerDialog(View v) {
- if (v != mCcExpDateView) {
- Log.w(TAG, "showDatePickerDialog() called on invalid view: " + v);
- return;
- }
- mCcExpDateView.showDatePickerDialog(getSupportFragmentManager());
- }
-
-
- /**
- * Launches new Activity and finishes, triggering an autofill save request if the user entered
- * any new data.
- */
- private void submit() {
- Intent intent = WelcomeActivity.getStartActivityIntent(this);
- startActivity(intent);
- finish();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDateCompoundView.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDateCompoundView.java
deleted file mode 100644
index 151815c..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDateCompoundView.java
+++ /dev/null
@@ -1,133 +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.app;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.FrameLayout;
-import android.widget.Spinner;
-
-import java.util.Calendar;
-
-import static com.example.android.autofill.app.CommonUtil.TAG;
-
-/**
- * A custom view that represents a {@link View#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} using
- * 2 {@link Spinner spinners} to represent the credit card expiration month and year.
- */
-public class CreditCardExpirationDateCompoundView extends FrameLayout {
-
- private static final int CC_EXP_YEARS_COUNT = 5;
-
- private final String[] mYears = new String[CC_EXP_YEARS_COUNT];
-
- private Spinner mCcExpMonthSpinner;
- private Spinner mCcExpYearSpinner;
-
- public CreditCardExpirationDateCompoundView(@NonNull Context context) {
- this(context, null);
- }
-
- public CreditCardExpirationDateCompoundView(@NonNull Context context,
- @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CreditCardExpirationDateCompoundView(@NonNull Context context,
- @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public CreditCardExpirationDateCompoundView(@NonNull final Context context,
- @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- View rootView = LayoutInflater.from(context).inflate(R.layout.cc_exp_date, this);
- mCcExpMonthSpinner = rootView.findViewById(R.id.ccExpMonth);
- mCcExpYearSpinner = rootView.findViewById(R.id.ccExpYear);
- setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS);
- ArrayAdapter<CharSequence> monthAdapter = ArrayAdapter.createFromResource
- (context, R.array.month_array, android.R.layout.simple_spinner_item);
- monthAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mCcExpMonthSpinner.setAdapter(monthAdapter);
- int year = Calendar.getInstance().get(Calendar.YEAR);
- for (int i = 0; i < mYears.length; i++) {
- mYears[i] = Integer.toString(year + i);
- }
- mCcExpYearSpinner.setAdapter(new ArrayAdapter<>(context,
- android.R.layout.simple_spinner_item, mYears));
- AdapterView.OnItemSelectedListener onItemSelectedListener =
- new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- context.getSystemService(AutofillManager.class)
- .notifyValueChanged(CreditCardExpirationDateCompoundView.this);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- }
- };
- mCcExpMonthSpinner.setOnItemSelectedListener(onItemSelectedListener);
- mCcExpYearSpinner.setOnItemSelectedListener(onItemSelectedListener);
- }
-
- @Override
- public AutofillValue getAutofillValue() {
- Calendar calendar = Calendar.getInstance();
- // Set hours, minutes, seconds, and millis to 0 to ensure getAutofillValue() == the value
- // set by autofill(). Without this line, the view will not turn yellow when updated.
- calendar.clear();
- int year = Integer.parseInt(mCcExpYearSpinner.getSelectedItem().toString());
- int month = mCcExpMonthSpinner.getSelectedItemPosition();
- calendar.set(Calendar.YEAR, year);
- calendar.set(Calendar.MONTH, month);
- long unixTime = calendar.getTimeInMillis();
- return AutofillValue.forDate(unixTime);
- }
-
- @Override
- public void autofill(AutofillValue value) {
- if (!value.isDate()) {
- Log.w(TAG, "Ignoring autofill() because service sent a non-date value:" + value);
- return;
- }
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(value.getDateValue());
- int month = calendar.get(Calendar.MONTH);
- int year = calendar.get(Calendar.YEAR);
- mCcExpMonthSpinner.setSelection(month);
- mCcExpYearSpinner.setSelection(year - Integer.parseInt(mYears[0]));
- }
-
- @Override
- public int getAutofillType() {
- return AUTOFILL_TYPE_DATE;
- }
-
- public void reset() {
- mCcExpMonthSpinner.setSelection(0);
- mCcExpYearSpinner.setSelection(0);
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDatePickerView.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDatePickerView.java
deleted file mode 100644
index f9df96f..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardExpirationDatePickerView.java
+++ /dev/null
@@ -1,161 +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.app;
-
-import android.app.DatePickerDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v7.widget.AppCompatEditText;
-import android.text.format.DateFormat;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.autofill.AutofillValue;
-import android.widget.DatePicker;
-
-import java.util.Calendar;
-import java.util.Date;
-
-import static com.example.android.autofill.app.CommonUtil.DEBUG;
-import static com.example.android.autofill.app.CommonUtil.TAG;
-
-/**
- * A custom view that represents a {@link View#AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} using
- * a non-editable {@link EditText} that triggers a {@link DatePickerDialog} to represent the
- * credit card expiration month and year.
- */
-public class CreditCardExpirationDatePickerView extends AppCompatEditText {
-
- private static final int CC_EXP_YEARS_COUNT = 5;
-
- /**
- * Calendar instance used for month / year calculations. Should be reset before each use.
- */
- private final Calendar mTempCalendar;
-
- private int mMonth;
- private int mYear;
-
- public CreditCardExpirationDatePickerView(@NonNull Context context) {
- this(context, null);
- }
-
- public CreditCardExpirationDatePickerView(@NonNull Context context,
- @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CreditCardExpirationDatePickerView(@NonNull Context context,
- @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- // Use the current date as the initial date in the picker.
- mTempCalendar = Calendar.getInstance();
- mYear = mTempCalendar.get(Calendar.YEAR);
- mMonth = mTempCalendar.get(Calendar.MONTH);
- }
-
- /**
- * Gets a temporary calendar set with the View's year and month.
- */
- private Calendar getCalendar() {
- mTempCalendar.clear();
- mTempCalendar.set(Calendar.YEAR, mYear);
- mTempCalendar.set(Calendar.MONTH, mMonth);
- mTempCalendar.set(Calendar.DATE, 1);
- return mTempCalendar;
- }
-
- @Override
- public AutofillValue getAutofillValue() {
- Calendar c = getCalendar();
- AutofillValue value = AutofillValue.forDate(c.getTimeInMillis());
- if (DEBUG) Log.d(TAG, "getAutofillValue(): " + value);
- return value;
- }
-
- @Override
- public void autofill(AutofillValue value) {
- if (value == null || !value.isDate()) {
- Log.w(TAG, "autofill(): invalid value " + value);
- return;
- }
- long time = value.getDateValue();
- mTempCalendar.setTimeInMillis(time);
- int year = mTempCalendar.get(Calendar.YEAR);
- int month = mTempCalendar.get(Calendar.MONTH);
- if (DEBUG) Log.d(TAG, "autofill(" + value + "): " + month + "/" + year);
- setDate(year, month);
- }
-
- private void setDate(int year, int month) {
- mYear = year;
- mMonth = month;
- Date selectedDate = new Date(getCalendar().getTimeInMillis());
- String dateString = DateFormat.getDateFormat(getContext()).format(selectedDate);
- setText(dateString);
- }
-
- @Override
- public int getAutofillType() {
- return AUTOFILL_TYPE_DATE;
- }
-
- public void reset() {
- mTempCalendar.setTimeInMillis(System.currentTimeMillis());
- setDate(mTempCalendar.get(Calendar.YEAR), mTempCalendar.get(Calendar.MONTH));
- }
-
- public void showDatePickerDialog(FragmentManager fragmentManager) {
- DatePickerFragment newFragment = new DatePickerFragment();
- newFragment.mParent = this;
- newFragment.show(fragmentManager, "datePicker");
- }
-
- public static class DatePickerFragment extends DialogFragment
- implements DatePickerDialog.OnDateSetListener {
-
- private CreditCardExpirationDatePickerView mParent;
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- DatePickerDialog dialog = new DatePickerDialog(getActivity(),
- R.style.CustomDatePickerDialogTheme, this, mParent.mYear, mParent.mMonth, 1);
-
- DatePicker datePicker = dialog.getDatePicker();
-
- // Limit range.
- Calendar c = mParent.getCalendar();
- datePicker.setMinDate(c.getTimeInMillis());
- c.set(Calendar.YEAR, mParent.mYear + CC_EXP_YEARS_COUNT - 1);
- datePicker.setMaxDate(c.getTimeInMillis());
-
- // Remove day.
- datePicker.findViewById(getResources().getIdentifier("day", "id", "android"))
- .setVisibility(View.GONE);
- return dialog;
- }
-
- @Override
- public void onDateSet(DatePicker view, int year, int month, int day) {
- mParent.setDate(year, month);
- }
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardSpinnersActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardSpinnersActivity.java
deleted file mode 100644
index 1fff8b1..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CreditCardSpinnersActivity.java
+++ /dev/null
@@ -1,122 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.Spinner;
-
-import java.util.Calendar;
-
-public class CreditCardSpinnersActivity extends AppCompatActivity {
-
- private static final int CC_EXP_YEARS_COUNT = 5;
-
- private final String[] years = new String[CC_EXP_YEARS_COUNT];
-
- private Spinner mCcExpirationDaySpinner;
- private Spinner mCcExpirationMonthSpinner;
- private Spinner mCcExpirationYearSpinner;
- private EditText mCcCardNumber;
- private EditText mCcSecurityCode;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, CreditCardSpinnersActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.credit_card_spinners_activity);
- mCcExpirationDaySpinner = findViewById(R.id.expirationDay);
- mCcExpirationMonthSpinner = findViewById(R.id.expirationMonth);
- mCcExpirationYearSpinner = findViewById(R.id.expirationYear);
- mCcCardNumber = findViewById(R.id.creditCardNumberField);
- mCcSecurityCode = findViewById(R.id.creditCardSecurityCode);
-
- // Create an ArrayAdapter using the string array and a default spinner layout
- ArrayAdapter<CharSequence> dayAdapter = ArrayAdapter.createFromResource
- (this, R.array.day_array, android.R.layout.simple_spinner_item);
- // Specify the layout to use when the list of choices appears
- dayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- // Apply the adapter to the spinner
- mCcExpirationDaySpinner.setAdapter(dayAdapter);
-
- /*
- R.array.month_array could be an array of Strings like "Jan", "Feb", "March", etc., and
- the AutofillService would know how to autofill it. However, for the sake of keeping the
- AutofillService simple, we will stick to a list of numbers (1, 2, ... 12) to represent
- months; it makes it much easier to generate fake autofill data in the service that can still
- autofill this spinner.
- */
- ArrayAdapter<CharSequence> monthAdapter = ArrayAdapter.createFromResource(
- this, R.array.month_array, android.R.layout.simple_spinner_item);
- // Adapter created from resource has getAutofillOptions() implemented by default.
- monthAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mCcExpirationMonthSpinner.setAdapter(monthAdapter);
-
- int year = Calendar.getInstance().get(Calendar.YEAR);
- for (int i = 0; i < years.length; i++) {
- years[i] = Integer.toString(year + i);
- }
- // Since the years Spinner uses a custom adapter, it needs to implement getAutofillOptions.
- mCcExpirationYearSpinner.setAdapter(
- new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, years) {
- @Override
- public CharSequence[] getAutofillOptions() {
- return years;
- }
- });
- findViewById(R.id.submit).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- submit();
- }
- });
- findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getSystemService(AutofillManager.class).cancel();
- resetFields();
- }
- });
- }
-
- private void resetFields() {
- mCcExpirationDaySpinner.setSelection(0);
- mCcExpirationMonthSpinner.setSelection(0);
- mCcExpirationYearSpinner.setSelection(0);
- mCcCardNumber.setText("");
- mCcSecurityCode.setText("");
- }
-
- /**
- * Launches new Activity and finishes, triggering an autofill save request if the user entered
- * any new data.
- */
- private void submit() {
- Intent intent = WelcomeActivity.getStartActivityIntent(CreditCardSpinnersActivity.this);
- startActivity(intent);
- finish();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CustomVirtualView.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CustomVirtualView.java
deleted file mode 100644
index 24cbd7e..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/CustomVirtualView.java
+++ /dev/null
@@ -1,506 +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.app;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Rect;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewStructure;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.google.common.base.Preconditions;
-
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-
-import static com.example.android.autofill.app.CommonUtil.bundleToString;
-
-/**
- * A custom View with a virtual structure for fields supporting {@link View#getAutofillHints()}
- */
-public class CustomVirtualView extends View {
-
- protected static final boolean DEBUG = true;
- protected static final boolean VERBOSE = false;
-
- /**
- * When set, it notifies AutofillManager of focus change as the view scrolls, so the
- * autofill UI is continually drawn.
- *
- * <p>This is janky and incompatible with the way the autofill UI works on native views, but
- * it's a cool experiment!
- */
- private static final boolean DRAW_AUTOFILL_UI_AFTER_SCROLL = false;
-
- private static final String TAG = "CustomView";
- private static final int DEFAULT_TEXT_HEIGHT_DP = 34;
- private static final int VERTICAL_GAP = 10;
- private static final int UNFOCUSED_COLOR = Color.BLACK;
- private static final int FOCUSED_COLOR = Color.RED;
- private static int sNextId;
- protected final AutofillManager mAutofillManager;
- private final ArrayList<Line> mVirtualViewGroups = new ArrayList<>();
- private final SparseArray<Item> mVirtualViews = new SparseArray<>();
- private final SparseArray<Partition> mPartitionsByAutofillId = new SparseArray<>();
- private final ArrayMap<String, Partition> mPartitionsByName = new ArrayMap<>();
- protected Line mFocusedLine;
- protected int mTopMargin;
- protected int mLeftMargin;
- private Paint mTextPaint;
- private int mTextHeight;
- private int mLineLength;
-
- public CustomVirtualView(Context context) {
- this(context, null);
- }
-
- public CustomVirtualView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CustomVirtualView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public CustomVirtualView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mAutofillManager = context.getSystemService(AutofillManager.class);
- mTextPaint = new Paint();
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomVirtualView,
- defStyleAttr, defStyleRes);
- int defaultHeight =
- (int) (DEFAULT_TEXT_HEIGHT_DP * getResources().getDisplayMetrics().density);
- mTextHeight = typedArray.getDimensionPixelSize(
- R.styleable.CustomVirtualView_internalTextSize, defaultHeight);
- typedArray.recycle();
- resetCoordinates();
- }
-
- protected void resetCoordinates() {
- mTextPaint.setStyle(Style.FILL);
- mTextPaint.setTextSize(mTextHeight);
- mTopMargin = getPaddingTop();
- mLeftMargin = getPaddingStart();
- mLineLength = mTextHeight + VERTICAL_GAP;
- }
-
- @Override
- public void autofill(SparseArray<AutofillValue> values) {
- Context context = getContext();
-
- // User has just selected a Dataset from the list of autofill suggestions.
- // The Dataset is comprised of a list of AutofillValues, with each AutofillValue meant
- // to fill a specific autofillable view. Now we have to update the UI based on the
- // AutofillValues in the list, but first we make sure all autofilled values belong to the
- // same partition
- if (DEBUG) Log.d(TAG, "autofill(): " + values);
-
- // First get the name of all partitions in the values
- ArraySet<String> partitions = new ArraySet<>();
- for (int i = 0; i < values.size(); i++) {
- int id = values.keyAt(i);
- Partition partition = mPartitionsByAutofillId.get(id);
- if (partition == null) {
- showError(context.getString(R.string.message_autofill_no_partitions, id,
- mPartitionsByAutofillId));
- return;
- }
- partitions.add(partition.mName);
- }
-
- // Then make sure they follow the Highlander rule (There can be only one)
- if (partitions.size() != 1) {
- showError(context.getString(R.string.message_autofill_blocked, partitions));
- return;
- }
-
- // Finally, autofill it.
- DateFormat df = android.text.format.DateFormat.getDateFormat(context);
- for (int i = 0; i < values.size(); i++) {
- int id = values.keyAt(i);
- AutofillValue value = values.valueAt(i);
- Item item = mVirtualViews.get(id);
-
- if (item == null) {
- Log.w(TAG, "No item for id " + id);
- continue;
- }
-
- if (!item.editable) {
- showError(context.getString(R.string.message_autofill_readonly, item.text));
- continue;
- }
-
- // Check if the type was properly set by the autofill service
- if (DEBUG) {
- Log.d(TAG, "Validating " + i
- + ": expectedType=" + CommonUtil.getTypeAsString(item.type)
- + "(" + item.type + "), value=" + value);
- }
- boolean valid = false;
- if (value.isText() && item.type == AUTOFILL_TYPE_TEXT) {
- item.text = value.getTextValue();
- valid = true;
- } else if (value.isDate() && item.type == AUTOFILL_TYPE_DATE) {
- item.text = df.format(new Date(value.getDateValue()));
- valid = true;
- } else {
- Log.w(TAG, "Unsupported type: " + value);
- }
- if (!valid) {
- item.text = context.getString(R.string.message_autofill_invalid);
- }
- }
- postInvalidate();
- showMessage(context.getString(R.string.message_autofill_ok, partitions.valueAt(0)));
- }
-
- @Override
- public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
- // Build a ViewStructure that will get passed to the AutofillService by the framework
- // when it is time to find autofill suggestions.
- structure.setClassName(getClass().getName());
- int childrenSize = mVirtualViews.size();
- if (DEBUG) {
- Log.d(TAG, "onProvideAutofillVirtualStructure(): flags = " + flags + ", items = "
- + childrenSize + ", extras: " + bundleToString(structure.getExtras()));
- }
- int index = structure.addChildCount(childrenSize);
- // Traverse through the view hierarchy, including virtual child views. For each view, we
- // need to set the relevant autofill metadata and add it to the ViewStructure.
- for (int i = 0; i < childrenSize; i++) {
- Item item = mVirtualViews.valueAt(i);
- if (DEBUG) Log.d(TAG, "Adding new child at index " + index + ": " + item);
- ViewStructure child = structure.newChild(index);
- child.setAutofillId(structure.getAutofillId(), item.id);
- child.setAutofillHints(item.hints);
- child.setAutofillType(item.type);
- child.setAutofillValue(item.getAutofillValue());
- child.setDataIsSensitive(!item.sanitized);
- child.setFocused(item.focused);
- child.setVisibility(View.VISIBLE);
- child.setDimens(item.line.mBounds.left, item.line.mBounds.top, 0, 0,
- item.line.mBounds.width(), item.line.mBounds.height());
- child.setId(item.id, getContext().getPackageName(), null, item.idEntry);
- child.setClassName(item.getClassName());
- child.setDimens(item.line.mBounds.left, item.line.mBounds.top, 0, 0,
- item.line.mBounds.width(), item.line.mBounds.height());
- index++;
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (VERBOSE) {
- Log.v(TAG, "onDraw(): " + mVirtualViewGroups.size() + " lines; canvas:" + canvas);
- }
- float x;
- float y = mTopMargin + mLineLength;
- for (int i = 0; i < mVirtualViewGroups.size(); i++) {
- Line line = mVirtualViewGroups.get(i);
- x = mLeftMargin;
- if (VERBOSE) Log.v(TAG, "Drawing '" + line + "' at " + x + "x" + y);
- mTextPaint.setColor(line.mFieldTextItem.focused ? FOCUSED_COLOR : UNFOCUSED_COLOR);
- String readOnlyText = line.mLabelItem.text + ": [";
- String writeText = line.mFieldTextItem.text + "]";
- // Paints the label first...
- canvas.drawText(readOnlyText, x, y, mTextPaint);
- // ...then paints the edit text and sets the proper boundary
- float deltaX = mTextPaint.measureText(readOnlyText);
- x += deltaX;
- line.mBounds.set((int) x, (int) (y - mLineLength),
- (int) (x + mTextPaint.measureText(writeText)), (int) y);
- if (VERBOSE) Log.v(TAG, "setBounds(" + x + ", " + y + "): " + line.mBounds);
- canvas.drawText(writeText, x, y, mTextPaint);
- y += mLineLength;
-
- if (DRAW_AUTOFILL_UI_AFTER_SCROLL) {
- line.notifyFocusChanged();
- }
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int y = (int) event.getY();
- onMotion(y);
- return super.onTouchEvent(event);
- }
-
- /**
- * Handles a motion event.
- *
- * @param y y coordinate.
- */
- protected void onMotion(int y) {
- if (DEBUG) {
- Log.d(TAG, "onMotion(): y=" + y + ", range=" + mLineLength + ", top=" + mTopMargin);
- }
- int lowerY = mTopMargin;
- int upperY = -1;
- for (int i = 0; i < mVirtualViewGroups.size(); i++) {
- Line line = mVirtualViewGroups.get(i);
- upperY = lowerY + mLineLength;
- if (DEBUG) Log.d(TAG, "Line " + i + " ranges from " + lowerY + " to " + upperY);
- if (lowerY <= y && y <= upperY) {
- if (mFocusedLine != null) {
- Log.d(TAG, "Removing focus from " + mFocusedLine);
- mFocusedLine.changeFocus(false);
- }
- Log.d(TAG, "Changing focus to " + line);
- mFocusedLine = line;
- mFocusedLine.changeFocus(true);
- invalidate();
- break;
- }
- lowerY += mLineLength;
- }
- }
-
- /**
- * Creates a new partition with the given name.
- *
- * @throws IllegalArgumentException if such partition already exists.
- */
- public Partition addPartition(String name) {
- Preconditions.checkNotNull(name, "Name cannot be null.");
- Preconditions.checkArgument(!mPartitionsByName.containsKey(name),
- "Partition with such name already exists.");
- Partition partition = new Partition(name);
- mPartitionsByName.put(name, partition);
- return partition;
- }
-
- private void showError(String message) {
- showMessage(true, message);
- }
-
- private void showMessage(String message) {
- showMessage(false, message);
- }
-
- private void showMessage(boolean warning, String message) {
- if (warning) {
- Log.w(TAG, message);
- } else {
- Log.i(TAG, message);
- }
- Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
- }
-
-
- protected static final class Item {
- protected final int id;
- private final String idEntry;
- private final Line line;
- private final boolean editable;
- private final boolean sanitized;
- private final String[] hints;
- private final int type;
- private CharSequence text;
- private boolean focused = false;
- private long date;
-
- Item(Line line, int id, String idEntry, String[] hints, int type, CharSequence text,
- boolean editable, boolean sanitized) {
- this.line = line;
- this.id = id;
- this.idEntry = idEntry;
- this.text = text;
- this.editable = editable;
- this.sanitized = sanitized;
- this.hints = hints;
- this.type = type;
- }
-
- @Override
- public String toString() {
- return id + "/" + idEntry + ": "
- + (type == AUTOFILL_TYPE_DATE ? date : text) // TODO: use DateFormat for date
- + " (" + CommonUtil.getTypeAsString(type) + ")"
- + (editable ? " (editable)" : " (read-only)"
- + (sanitized ? " (sanitized)" : " (sensitive"))
- + (hints == null ? " (no hints)" : " ( " + Arrays.toString(hints) + ")");
- }
-
- public String getClassName() {
- return editable ? EditText.class.getName() : TextView.class.getName();
- }
-
- public AutofillValue getAutofillValue() {
- switch (type) {
- case AUTOFILL_TYPE_TEXT:
- return (TextUtils.getTrimmedLength(text) > 0)
- ? AutofillValue.forText(text)
- : null;
- case AUTOFILL_TYPE_DATE:
- return AutofillValue.forDate(date);
- default:
- return null;
- }
- }
- }
-
- /**
- * A partition represents a logical group of items, such as credit card info.
- */
- public final class Partition {
- private final String mName;
- private final SparseArray<Line> mLines = new SparseArray<>();
-
- private Partition(String name) {
- mName = name;
- }
-
- /**
- * Adds a new line (containining a label and an input field) to the view.
- *
- * @param idEntryPrefix id prefix used to identify the line - label node will be suffixed
- * with {@code Label} and editable node with {@code Field}.
- * @param autofillType {@link View#getAutofillType() autofill type} of the field.
- * @param label text used in the label.
- * @param text initial text used in the input field.
- * @param sensitive whether the input is considered sensitive.
- * @param autofillHints list of autofill hints.
- * @return the new line.
- */
- public Line addLine(String idEntryPrefix, int autofillType, String label, String text,
- boolean sensitive, String... autofillHints) {
- Preconditions.checkArgument(autofillType == AUTOFILL_TYPE_TEXT ||
- autofillType == AUTOFILL_TYPE_DATE, "Unsupported type: " + autofillType);
- Line line = new Line(idEntryPrefix, autofillType, label, autofillHints, text,
- !sensitive);
- mVirtualViewGroups.add(line);
- int id = line.mFieldTextItem.id;
- mLines.put(id, line);
- mVirtualViews.put(line.mLabelItem.id, line.mLabelItem);
- mVirtualViews.put(id, line.mFieldTextItem);
- mPartitionsByAutofillId.put(id, this);
-
- return line;
- }
-
- /**
- * Resets the value of all items in the partition.
- */
- public void reset() {
- for (int i = 0; i < mLines.size(); i++) {
- mLines.valueAt(i).reset();
- }
- }
-
- @Override
- public String toString() {
- return mName;
- }
- }
-
- /**
- * A line in the virtual view contains a label and an input field.
- */
- public final class Line {
-
- protected final Item mFieldTextItem;
- // Boundaries of the text field, relative to the CustomView
- private final Rect mBounds = new Rect();
- private final Item mLabelItem;
- private final int mAutofillType;
-
- private Line(String idEntryPrefix, int autofillType, String label, String[] hints,
- String text, boolean sanitized) {
- this.mAutofillType = autofillType;
- this.mLabelItem = new Item(this, ++sNextId, idEntryPrefix + "Label", null,
- AUTOFILL_TYPE_NONE, label, false, true);
- this.mFieldTextItem = new Item(this, ++sNextId, idEntryPrefix + "Field", hints,
- autofillType, text, true, sanitized);
- }
-
- private void changeFocus(boolean focused) {
- mFieldTextItem.focused = focused;
- notifyFocusChanged();
- }
-
- void notifyFocusChanged() {
- if (mFieldTextItem.focused) {
- Rect absBounds = getAbsCoordinates();
- if (DEBUG) {
- Log.d(TAG, "focus gained on " + mFieldTextItem.id + "; absBounds=" + absBounds);
- }
- mAutofillManager.notifyViewEntered(CustomVirtualView.this, mFieldTextItem.id,
- absBounds);
- } else {
- if (DEBUG) Log.d(TAG, "focus lost on " + mFieldTextItem.id);
- mAutofillManager.notifyViewExited(CustomVirtualView.this, mFieldTextItem.id);
- }
- }
-
- private Rect getAbsCoordinates() {
- // Must offset the boundaries so they're relative to the CustomView.
- int offset[] = new int[2];
- getLocationOnScreen(offset);
- Rect absBounds = new Rect(mBounds.left + offset[0],
- mBounds.top + offset[1],
- mBounds.right + offset[0], mBounds.bottom + offset[1]);
- if (VERBOSE) {
- Log.v(TAG, "getAbsCoordinates() for " + mFieldTextItem.id + ": bounds=" + mBounds
- + " offset: " + Arrays.toString(offset) + " absBounds: " + absBounds);
- }
- return absBounds;
- }
-
- /**
- * Gets the value of the input field text.
- */
- public CharSequence getText() {
- return mFieldTextItem.text;
- }
-
- /**
- * Resets the value of the input field text.
- */
- public void reset() {
- mFieldTextItem.text = " ";
- }
-
- @Override
- public String toString() {
- return "Label: " + mLabelItem + " Text: " + mFieldTextItem + " Focused: " +
- mFieldTextItem.focused + " Type: " + mAutofillType;
- }
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/EmailComposeActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/EmailComposeActivity.java
deleted file mode 100644
index bf4995f..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/EmailComposeActivity.java
+++ /dev/null
@@ -1,44 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-
-public class EmailComposeActivity extends AppCompatActivity {
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, EmailComposeActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.email_compose_activity);
- findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(WelcomeActivity.getStartActivityIntent(EmailComposeActivity.this));
- finish();
- }
- });
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/InfoButton.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/InfoButton.java
deleted file mode 100644
index cf88d6f..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/InfoButton.java
+++ /dev/null
@@ -1,52 +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.app;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.AppCompatImageButton;
-import android.util.AttributeSet;
-import android.view.View;
-
-public class InfoButton extends AppCompatImageButton {
- public InfoButton(Context context) {
- this(context, null);
- }
-
- public InfoButton(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public InfoButton(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.InfoButton,
- defStyleAttr, 0);
- String infoText = typedArray.getString(R.styleable.InfoButton_dialogText);
- typedArray.recycle();
- setInfoText(infoText);
- }
-
- public void setInfoText(final String infoText) {
- setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- new AlertDialog.Builder(InfoButton.this.getContext())
- .setMessage(infoText).create().show();
- }
- });
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MainActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MainActivity.java
index 94d339d..2c8915b 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MainActivity.java
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MainActivity.java
@@ -13,129 +13,66 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.example.android.autofill.app;
-import android.content.Intent;
+import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
+import android.support.design.widget.TabLayout;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
+
+import com.example.android.autofill.app.commoncases.CommonCasesFragment;
+import com.example.android.autofill.app.edgecases.EdgeCasesFragment;
/**
* This is used to launch sample activities that showcase autofill.
*/
public class MainActivity extends AppCompatActivity {
- private static final String TAG = "MainActivity";
-
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- if (launchTrampolineActivity()) {
- return;
- }
-
setContentView(R.layout.activity_main);
- NavigationItem loginEditTexts = findViewById(R.id.standardViewSignInButton);
- NavigationItem loginCustomVirtual = findViewById(R.id.virtualViewSignInButton);
- NavigationItem creditCard = findViewById(R.id.creditCardButton);
- NavigationItem creditCardSpinners = findViewById(R.id.creditCardSpinnersButton);
- NavigationItem loginAutoComplete = findViewById(R.id.standardLoginWithAutoCompleteButton);
- NavigationItem emailCompose = findViewById(R.id.emailComposeButton);
- NavigationItem creditCardCompoundView = findViewById(R.id.creditCardCompoundViewButton);
- NavigationItem creditCardDatePicker = findViewById(R.id.creditCardDatePickerButton);
- NavigationItem creditCardAntiPatternPicker = findViewById(R.id.creditCardAntiPatternButton);
- NavigationItem multiplePartitions = findViewById(R.id.multiplePartitionsButton);
- NavigationItem loginWebView = findViewById(R.id.webviewSignInButton);
- loginEditTexts.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(StandardSignInActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- loginCustomVirtual.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(VirtualSignInActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- creditCard.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(CreditCardActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- creditCardSpinners.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(CreditCardSpinnersActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- loginAutoComplete.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(StandardAutoCompleteSignInActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- emailCompose.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(EmailComposeActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- creditCardCompoundView.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(CreditCardCompoundViewActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- creditCardDatePicker.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(CreditCardDatePickerActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- creditCardAntiPatternPicker.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(CreditCardAntiPatternActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- multiplePartitions.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(MultiplePartitionsActivity.getStartActivityIntent(MainActivity.this));
- }
- });
- loginWebView.setNavigationButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(WebViewSignInActivity.getStartActivityIntent(MainActivity.this));
- }
- });
+ ViewPager viewPager = findViewById(R.id.pager);
+ PagerAdapter pagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(), this);
+ viewPager.setAdapter(pagerAdapter);
+ TabLayout tabLayout = findViewById(R.id.sliding_tabs);
+ tabLayout.setupWithViewPager(viewPager);
}
- private boolean launchTrampolineActivity() {
- Intent intent = getIntent();
- if (intent != null) {
- String target = intent.getStringExtra("target");
- if (target != null) {
- Log.i(TAG, "trampolining into " + target + " instead");
- try {
- Intent newIntent = new Intent(this,
- Class.forName("com.example.android.autofill.app." + target));
- newIntent.putExtras(intent);
- newIntent.removeExtra("target");
- getApplicationContext().startActivity(newIntent);
- finish();
- return true;
- } catch (Exception e) {
- Log.e(TAG, "Error launching " + target, e);
- }
- }
+ /**
+ * A simple pager adapter that holds 2 Fragments.
+ */
+ private static class ScreenSlidePagerAdapter extends FragmentPagerAdapter {
+ private BaseMainFragment[] fragments = new BaseMainFragment[]{new CommonCasesFragment(),
+ new EdgeCasesFragment()};
+
+ private Context mContext;
+
+ public ScreenSlidePagerAdapter(FragmentManager fm, Context context) {
+ super(fm);
+ mContext = context;
}
- return false;
+
+ @Override
+ public Fragment getItem(int position) {
+ return fragments[position];
+ }
+
+ @Override
+ public int getCount() {
+ return fragments.length;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return mContext.getString(fragments[position].getPageTitleResId());
+ }
}
}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MultiplePartitionsActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MultiplePartitionsActivity.java
deleted file mode 100644
index 83dd320..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/MultiplePartitionsActivity.java
+++ /dev/null
@@ -1,123 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.Toast;
-
-/**
- * Activity used to demonstrated safe partitioning of data.
- * <p>
- * <p>It has multiple partitions, but only accepts autofill on each partition at time.
- */
-/*
- * TODO list
- *
- * - Fix top margin.
- * - Use a combo box to select if credit card expiration date is expressed as date or text.
- * - Use a dedicated TextView (instead of Toast) for error messages.
- * - Use wrap_context to CustomView container.
- * - Use different background color (or borders) for each partition.
- * - Add more partitions (like address) - should match same partitions from service.
- * - Add more hints (like w3c ones) - should match same hints from service.
- */
-public class MultiplePartitionsActivity extends AppCompatActivity {
-
- private ScrollableCustomVirtualView mCustomVirtualView;
- private AutofillManager mAutofillManager;
-
- private CustomVirtualView.Partition mCredentialsPartition;
- private CustomVirtualView.Partition mCcPartition;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, MultiplePartitionsActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.multiple_partitions_activity);
-
- mCustomVirtualView = findViewById(R.id.custom_view);
-
-
- mCredentialsPartition =
- mCustomVirtualView.addPartition(getString(R.string.partition_credentials));
- mCredentialsPartition.addLine("username", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.username_label),
- " ", false, View.AUTOFILL_HINT_USERNAME);
- mCredentialsPartition.addLine("password", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.password_label),
- " ", true, View.AUTOFILL_HINT_PASSWORD);
-
- int ccExpirationType = View.AUTOFILL_TYPE_DATE;
- // TODO: add a checkbox to switch between text / date instead
- Intent intent = getIntent();
- if (intent != null) {
- int newType = intent.getIntExtra("dateType", -1);
- if (newType != -1) {
- ccExpirationType = newType;
- String typeMessage = getString(R.string.message_credit_card_expiration_type,
- CommonUtil.getTypeAsString(ccExpirationType));
- // TODO: display type in a header or proper status widget
- Toast.makeText(getApplicationContext(), typeMessage, Toast.LENGTH_LONG).show();
- }
- }
-
- mCcPartition = mCustomVirtualView.addPartition(getString(R.string.partition_credit_card));
- mCcPartition.addLine("ccNumber", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.credit_card_number_label),
- " ", true, View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
- mCcPartition.addLine("ccDay", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.credit_card_expiration_day_label),
- " ", true, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
- mCcPartition.addLine("ccMonth", ccExpirationType,
- getString(R.string.credit_card_expiration_month_label),
- " ", true, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
- mCcPartition.addLine("ccYear", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.credit_card_expiration_year_label),
- " ", true, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
- mCcPartition.addLine("ccDate", ccExpirationType,
- getString(R.string.credit_card_expiration_date_label),
- " ", true, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
- mCcPartition.addLine("ccSecurityCode", View.AUTOFILL_TYPE_TEXT,
- 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();
- }
- });
- mAutofillManager = getSystemService(AutofillManager.class);
- }
-
- private void resetFields() {
- mCredentialsPartition.reset();
- mCcPartition.reset();
- mCustomVirtualView.postInvalidate();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/NavigationItem.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/NavigationItem.java
deleted file mode 100644
index b619644..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/NavigationItem.java
+++ /dev/null
@@ -1,76 +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.app;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.CardView;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-public class NavigationItem extends FrameLayout {
- CardView mCardView;
-
- public NavigationItem(Context context) {
- this(context, null);
- }
-
- public NavigationItem(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public NavigationItem(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public NavigationItem(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NavigationItem,
- defStyleAttr, defStyleRes);
- String labelText = typedArray.getString(R.styleable.NavigationItem_labelText);
- String infoText = typedArray.getString(R.styleable.NavigationItem_infoText);
- Drawable logoDrawable = typedArray.getDrawable(R.styleable.NavigationItem_itemLogo);
- @ColorRes int colorRes = typedArray.getResourceId(R.styleable.NavigationItem_imageColor, 0);
- int imageColor = ContextCompat.getColor(getContext(), colorRes);
- typedArray.recycle();
- View rootView = LayoutInflater.from(context).inflate(R.layout.navigation_item, this);
- if (logoDrawable != null) {
- logoDrawable.setColorFilter(imageColor, PorterDuff.Mode.SRC_IN);
- }
- TextView buttonLabel = rootView.findViewById(R.id.buttonLabel);
- buttonLabel.setText(labelText);
- buttonLabel.setCompoundDrawablesRelativeWithIntrinsicBounds(logoDrawable, null,
- null, null);
- InfoButton infoButton = rootView.findViewById(R.id.infoButton);
- infoButton.setInfoText(infoText);
- infoButton.setColorFilter(imageColor);
- mCardView = rootView.findViewById(R.id.cardView);
- }
-
- public void setNavigationButtonClickListener(@Nullable OnClickListener l) {
- mCardView.setOnClickListener(l);
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/ScrollableCustomVirtualView.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/ScrollableCustomVirtualView.java
deleted file mode 100644
index a2b081a..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/ScrollableCustomVirtualView.java
+++ /dev/null
@@ -1,105 +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.app;
-
-import android.content.Context;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-
-/**
- * A version of {@link CustomVirtualView} that uses gesture to provide scrolling.
- */
-public class ScrollableCustomVirtualView extends CustomVirtualView
- implements GestureDetector.OnGestureListener {
-
- private static final String TAG = "ScrollableCustomView";
-
- private GestureDetector mGestureDetector;
-
- public ScrollableCustomVirtualView(Context context) {
- this(context, null);
- }
-
- public ScrollableCustomVirtualView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
-
- }
-
- public ScrollableCustomVirtualView(Context context, @Nullable AttributeSet attrs,
- int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public ScrollableCustomVirtualView(Context context, @Nullable AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mGestureDetector = new GestureDetector(context, this);
- }
-
- /**
- * Resets the UI to the intial state.
- */
- public void resetPositions() {
- super.resetCoordinates();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return mGestureDetector.onTouchEvent(event);
- }
-
- /*
- * Methods below implement GestureDetector.OnGestureListener
- */
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (VERBOSE) Log.v(TAG, "onScroll(): " + distanceX + " - " + distanceY);
- if (mFocusedLine != null) {
- mAutofillManager.notifyViewExited(this, mFocusedLine.mFieldTextItem.id);
- }
- mTopMargin -= distanceY;
- mLeftMargin -= distanceX;
- invalidate();
- return true;
- }
-
- @Override
- public boolean onDown(MotionEvent event) {
- onMotion((int) event.getY());
- return true;
- }
-
- @Override
- public void onShowPress(MotionEvent e) {
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- return true;
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
- }
-
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- return true;
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardAutoCompleteSignInActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardAutoCompleteSignInActivity.java
deleted file mode 100644
index 49acd37..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardAutoCompleteSignInActivity.java
+++ /dev/null
@@ -1,140 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import static com.example.android.autofill.app.CommonUtil.TAG;
-
-public class StandardAutoCompleteSignInActivity extends AppCompatActivity {
- private AutoCompleteTextView mUsernameAutoCompleteField;
- private TextView mPasswordField;
- private TextView mLoginButton;
- private TextView mClearButton;
- private boolean mAutofillReceived = false;
- private AutofillManager.AutofillCallback mAutofillCallback;
- private AutofillManager mAutofillManager;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, StandardAutoCompleteSignInActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.login_with_autocomplete_activity);
-
- mLoginButton = findViewById(R.id.login);
- mClearButton = findViewById(R.id.clear);
- mUsernameAutoCompleteField = findViewById(R.id.usernameField);
- mPasswordField = findViewById(R.id.passwordField);
- mLoginButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- login();
- }
- });
- mClearButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- resetFields();
- }
- });
- mAutofillCallback = new MyAutofillCallback();
- mAutofillManager = getSystemService(AutofillManager.class);
- ArrayAdapter<CharSequence> mockAutocompleteAdapter = ArrayAdapter.createFromResource
- (this, R.array.mock_autocomplete_sign_in_suggestions,
- android.R.layout.simple_dropdown_item_1line);
- mUsernameAutoCompleteField.setAdapter(mockAutocompleteAdapter);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mAutofillManager.registerCallback(mAutofillCallback);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mAutofillManager.unregisterCallback(mAutofillCallback);
- }
-
- private void resetFields() {
- mUsernameAutoCompleteField.setText("");
- mPasswordField.setText("");
- }
-
- /**
- * Emulates a login action.
- */
- private void login() {
- String username = mUsernameAutoCompleteField.getText().toString();
- String password = mPasswordField.getText().toString();
- boolean valid = isValidCredentials(username, password);
- if (valid) {
- Intent intent = WelcomeActivity.getStartActivityIntent(StandardAutoCompleteSignInActivity.this);
- startActivity(intent);
- finish();
- } else {
- Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show();
- }
- }
-
- /**
- * Dummy implementation for demo purposes. A real service should use secure mechanisms to
- * authenticate users.
- */
- public boolean isValidCredentials(String username, String password) {
- return username != null && password != null && username.equals(password);
- }
-
- private class MyAutofillCallback extends AutofillManager.AutofillCallback {
- @Override
- public void onAutofillEvent(@NonNull View view, int event) {
- if (view instanceof AutoCompleteTextView) {
- switch (event) {
- case AutofillManager.AutofillCallback.EVENT_INPUT_UNAVAILABLE:
- // no break on purpose
- case AutofillManager.AutofillCallback.EVENT_INPUT_HIDDEN:
- if (!mAutofillReceived) {
- ((AutoCompleteTextView) view).showDropDown();
- }
- break;
- case AutofillManager.AutofillCallback.EVENT_INPUT_SHOWN:
- mAutofillReceived = true;
- ((AutoCompleteTextView) view).setAdapter(null);
- break;
- default:
- Log.d(TAG, "Unexpected callback: " + event);
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardSignInActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardSignInActivity.java
deleted file mode 100644
index 6664a18..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/StandardSignInActivity.java
+++ /dev/null
@@ -1,85 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.Toast;
-
-public class StandardSignInActivity extends AppCompatActivity {
-
- private EditText mUsernameEditText;
- private EditText mPasswordEditText;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, StandardSignInActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.login_activity);
- mUsernameEditText = findViewById(R.id.usernameField);
- mPasswordEditText = findViewById(R.id.passwordField);
- findViewById(R.id.login).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- login();
- }
- });
- findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- resetFields();
- }
- });
- }
-
- private void resetFields() {
- mUsernameEditText.setText("");
- mPasswordEditText.setText("");
- }
-
- /**
- * Emulates a login action.
- */
- private void login() {
- String username = mUsernameEditText.getText().toString();
- String password = mPasswordEditText.getText().toString();
- boolean valid = isValidCredentials(username, password);
- if (valid) {
- Intent intent = WelcomeActivity.getStartActivityIntent(StandardSignInActivity.this);
- startActivity(intent);
- finish();
- } else {
- Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show();
- }
- }
-
- /**
- * Dummy implementation for demo purposes. A real service should use secure mechanisms to
- * authenticate users.
- */
- public boolean isValidCredentials(String username, String password) {
- return username != null && password != null && username.equals(password);
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/VirtualSignInActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/VirtualSignInActivity.java
deleted file mode 100644
index f157faf..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/VirtualSignInActivity.java
+++ /dev/null
@@ -1,103 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.widget.Toast;
-
-/**
- * Activity that uses a virtual views for Username/Password text fields.
- */
-public class VirtualSignInActivity extends AppCompatActivity {
-
- private CustomVirtualView mCustomVirtualView;
- private AutofillManager mAutofillManager;
- private CustomVirtualView.Line mUsernameLine;
- private CustomVirtualView.Line mPasswordLine;
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, VirtualSignInActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.virtual_login_activity);
-
- mCustomVirtualView = (CustomVirtualView) findViewById(R.id.custom_view);
-
- CustomVirtualView.Partition credentialsPartition =
- mCustomVirtualView.addPartition(getString(R.string.partition_credentials));
- mUsernameLine = credentialsPartition.addLine("username", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.username_label),
- " ", false, View.AUTOFILL_HINT_USERNAME);
- mPasswordLine = credentialsPartition.addLine("password", View.AUTOFILL_TYPE_TEXT,
- getString(R.string.password_label),
- " ", true, View.AUTOFILL_HINT_PASSWORD);
-
- findViewById(R.id.login).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- login();
- }
- });
- findViewById(R.id.clear).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- resetFields();
- mAutofillManager.cancel();
- }
- });
- mAutofillManager = getSystemService(AutofillManager.class);
- }
-
- private void resetFields() {
- mUsernameLine.reset();
- mPasswordLine.reset();
- mCustomVirtualView.postInvalidate();
- }
-
- /**
- * Emulates a login action.
- */
- private void login() {
- String username = mUsernameLine.getText().toString();
- String password = mPasswordLine.getText().toString();
- boolean valid = isValidCredentials(username, password);
- if (valid) {
- Intent intent = WelcomeActivity.getStartActivityIntent(VirtualSignInActivity.this);
- startActivity(intent);
- finish();
- } else {
- Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show();
- }
- }
-
- /**
- * Dummy implementation for demo purposes. A real service should use secure mechanisms to
- * authenticate users.
- */
- public boolean isValidCredentials(String username, String password) {
- return username != null && password != null && username.equals(password);
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/WebViewSignInActivity.java b/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/WebViewSignInActivity.java
deleted file mode 100644
index d7c0124..0000000
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/java/com/example/android/autofill/app/WebViewSignInActivity.java
+++ /dev/null
@@ -1,59 +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.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import static com.example.android.autofill.app.CommonUtil.DEBUG;
-import static com.example.android.autofill.app.CommonUtil.TAG;
-
-public class WebViewSignInActivity extends AppCompatActivity {
-
- public static Intent getStartActivityIntent(Context context) {
- Intent intent = new Intent(context, WebViewSignInActivity.class);
- return intent;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.login_webview_activity);
-
- WebView webView = findViewById(R.id.webview);
- WebSettings webSettings = webView.getSettings();
- webView.setWebViewClient(new WebViewClient());
- webSettings.setJavaScriptEnabled(true);
-
- String url = getIntent().getStringExtra("url");
- if (url == null) {
- url = "file:///android_res/raw/sample_form.html";
- }
- if (DEBUG) Log.d(TAG, "Clearing WebView data");
- webView.clearHistory();
- webView.clearFormData();
- webView.clearCache(true);
- Log.i(TAG, "Loading URL " + url);
- webView.loadUrl(url);
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_autocomplete_logo_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_autocomplete_logo_24dp.xml
index 80f30a2..18dc280 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_autocomplete_logo_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_autocomplete_logo_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h14l4,4L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
+ android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h14l4,4L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_custom_virtual_logo_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_custom_virtual_logo_24dp.xml
index 3a8ee3b..f230e26 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_custom_virtual_logo_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_custom_virtual_logo_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M13,7h-2v2h2L13,7zM13,11h-2v2h2v-2zM17,11h-2v2h2v-2zM3,3v18h18L21,3L3,3zM19,19L5,19L5,5h14v14zM13,15h-2v2h2v-2zM9,11L7,11v2h2v-2z"/>
+ android:pathData="M13,7h-2v2h2L13,7zM13,11h-2v2h2v-2zM17,11h-2v2h2v-2zM3,3v18h18L21,3L3,3zM19,19L5,19L5,5h14v14zM13,15h-2v2h2v-2zM9,11L7,11v2h2v-2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_edittexts_logo_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_edittexts_logo_24dp.xml
index 17e403d..b260df2 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_edittexts_logo_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_edittexts_logo_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M4,9h16v2L4,11zM4,13h10v2L4,15z"/>
+ android:pathData="M4,9h16v2L4,11zM4,13h10v2L4,15z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_email_black_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_email_black_24dp.xml
index 174c127..2c31d68 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_email_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_email_black_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
+ android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_info_black_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_info_black_24dp.xml
index c297121..a3dba1d 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_info_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_info_black_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml
index 6534d9f..032db12 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml
@@ -13,8 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<vector android:alpha="0.50" android:height="24dp"
- android:viewportHeight="24.0" android:viewportWidth="24.0"
- android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:alpha="0.50"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_send_white_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_send_white_24dp.xml
index f614267..5e92b26 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_send_white_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_send_white_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
+ android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_spinners_logo_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_spinners_logo_24dp.xml
index 5fb27a2..ea91d03 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_spinners_logo_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_spinners_logo_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M9,11L7,11v2h2v-2zM13,11h-2v2h2v-2zM17,11h-2v2h2v-2zM19,4h-1L18,2h-2v2L8,4L8,2L6,2v2L5,4c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM19,20L5,20L5,9h14v11z"/>
+ android:pathData="M9,11L7,11v2h2v-2zM13,11h-2v2h2v-2zM17,11h-2v2h2v-2zM19,4h-1L18,2h-2v2L8,4L8,2L6,2v2L5,4c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM19,20L5,20L5,9h14v11z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
index ab36b07..bb739bb 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z"/>
+ android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_web_black_24dp.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_web_black_24dp.xml
index 48e7b7b..d5e35bf 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_web_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/drawable/ic_web_black_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM15,18L4,18v-4h11v4zM15,13L4,13L4,9h11v4zM20,18h-4L16,9h4v9z"/>
+ android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM15,18L4,18v-4h11v4zM15,13L4,13L4,9h11v4zM20,18h-4L16,9h4v9z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/activity_main.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/activity_main.xml
index a1ccd0c..ece13e9 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/activity_main.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/activity_main.xml
@@ -13,118 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <LinearLayout
+ <android.support.design.widget.TabLayout
+ android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingEnd="@dimen/activity_horizontal_margin"
- android:paddingStart="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin">
+ app:tabMode="fixed" />
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/standardViewSignInButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_red_dark"
- app:infoText="@string/edittext_login_info"
- app:itemLogo="@drawable/ic_edittexts_logo_24dp"
- app:labelText="@string/navigation_button_edittext_login_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/standardLoginWithAutoCompleteButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_blue_dark"
- app:infoText="@string/autocomplete_login_info"
- app:itemLogo="@drawable/ic_autocomplete_logo_24dp"
- app:labelText="@string/navigation_button_autocomplete_login_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/virtualViewSignInButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_green_dark"
- app:infoText="@string/custom_virtual_login_info"
- app:itemLogo="@drawable/ic_custom_virtual_logo_24dp"
- app:labelText="@string/navigation_button_custom_virtual_view_login_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/webviewSignInButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_green_dark"
- app:infoText="@string/webview_login_info"
- app:itemLogo="@drawable/ic_web_black_24dp"
- app:labelText="@string/navigation_button_web_view_login_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/creditCardSpinnersButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_orange_dark"
- app:infoText="@string/spinners_credit_card_info"
- app:itemLogo="@drawable/ic_spinners_logo_24dp"
- app:labelText="@string/navigation_button_spinners_credit_card_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/creditCardCompoundViewButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_blue_light"
- app:infoText="@string/compound_view_credit_card_info"
- app:itemLogo="@drawable/ic_view_module_black_24dp"
- app:labelText="@string/navigation_button_compound_view_credit_card_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/creditCardDatePickerButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_blue_light"
- app:infoText="@string/date_picker_credit_card_info"
- app:itemLogo="@drawable/ic_view_module_black_24dp"
- app:labelText="@string/navigation_button_date_picker_credit_card_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/emailComposeButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_purple"
- app:infoText="@string/email_compose_info"
- app:itemLogo="@drawable/ic_email_black_24dp"
- app:labelText="@string/navigation_button_email_compose_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/multiplePartitionsButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_green_dark"
- app:infoText="@string/multiple_partitions"
- app:itemLogo="@drawable/ic_custom_virtual_logo_24dp"
- app:labelText="@string/navigation_button_multiple_partitions_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/creditCardButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_orange_dark"
- app:infoText="@string/credit_card_info"
- app:itemLogo="@drawable/ic_spinners_logo_24dp"
- app:labelText="@string/navigation_button_credit_card_label" />
-
- <com.example.android.autofill.app.NavigationItem
- android:id="@+id/creditCardAntiPatternButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:imageColor="@android:color/holo_orange_dark"
- app:infoText="@string/anti_pattern_credit_card_info"
- app:itemLogo="@drawable/ic_spinners_logo_24dp"
- app:labelText="@string/navigation_button_anti_pattern_credit_card_label" />
- </LinearLayout>
-</ScrollView>
\ No newline at end of file
+ <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</LinearLayout>
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml
index a4dd537..aebe9f8 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml
@@ -14,7 +14,7 @@
* limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.constraint.ConstraintLayout
android:id="@+id/navigation_item_layout"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_activity.xml
index a55fd4b..414803a 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/authLayout"
android:layout_width="match_parent"
@@ -40,7 +39,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_anti_pattern_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_anti_pattern_activity.xml
index 7a126e8..9a3d4ae 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_anti_pattern_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_anti_pattern_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -37,7 +36,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/infoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml
index e2fbc83..1e00f26 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -38,7 +37,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -86,7 +85,7 @@
app:layout_constraintStart_toStartOf="@id/creditCardNumberLabel"
app:layout_constraintTop_toBottomOf="@+id/creditCardNumberLabel" />
- <com.example.android.autofill.app.CreditCardExpirationDateCompoundView
+ <com.example.android.autofill.app.view.autofillable.CreditCardExpirationDateCompoundView
android:id="@+id/creditCardExpirationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_date_picker_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_date_picker_activity.xml
index 22679de..ace95d4 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_date_picker_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_date_picker_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/authLayout"
android:layout_width="match_parent"
@@ -40,7 +39,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -89,7 +88,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/creditCardNumberLabel" />
- <com.example.android.autofill.app.CreditCardExpirationDatePickerView
+ <com.example.android.autofill.app.view.autofillable.CreditCardExpirationDatePickerView
android:id="@+id/creditCardExpirationView"
android:layout_width="250dp"
android:layout_height="wrap_content"
@@ -110,9 +109,9 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_large"
android:importantForAutofill="no"
- android:text="@string/credit_card_security_code_label"
android:labelFor="@+id/creditCardSecurityCode"
android:paddingEnd="@dimen/padding_normal"
+ android:text="@string/credit_card_security_code_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/creditCardExpirationView" />
@@ -124,8 +123,8 @@
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:autofillHints="creditCardSecurityCode"
- android:inputType="number"
android:ems="6"
+ android:inputType="number"
app:layout_constraintBottom_toBottomOf="@+id/creditCardSecurityCodeLabel"
app:layout_constraintStart_toEndOf="@+id/creditCardSecurityCodeLabel"
app:layout_constraintTop_toTopOf="@+id/creditCardSecurityCodeLabel" />
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_spinners_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_spinners_activity.xml
index 5a9b78a..6c1bfef 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_spinners_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/credit_card_spinners_activity.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -38,7 +36,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/infoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/email_compose_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/email_compose_activity.xml
index 9d65f47..bd1bd43 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/email_compose_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/email_compose_activity.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -40,7 +38,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_activity.xml
index f03bc04..1cb4232 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/authLayout"
android:layout_width="match_parent"
@@ -40,7 +39,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_webview_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_webview_activity.xml
index 3985f72..abbd1f4 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_webview_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_webview_activity.xml
@@ -14,6 +14,6 @@
* limitations under the License.
-->
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
\ No newline at end of file
+ android:id="@+id/webview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_with_autocomplete_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_with_autocomplete_activity.xml
index 1c5b92f..d9f89e7 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_with_autocomplete_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/login_with_autocomplete_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/authLayout"
android:layout_width="match_parent"
@@ -39,7 +38,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
index ff7dfcf..e0fae46 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/multiple_partitions_activity.xml
@@ -37,7 +37,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -49,19 +49,19 @@
app:layout_constraintStart_toEndOf="@+id/multiple_partitions_header"
app:layout_constraintTop_toTopOf="@+id/multiple_partitions_header" />
- <com.example.android.autofill.app.ScrollableCustomVirtualView
+ <com.example.android.autofill.app.view.autofillable.ScrollableCustomVirtualView
android:id="@+id/custom_view"
android:layout_width="match_parent"
android:layout_height="@dimen/multiple_partitions_height"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
- android:paddingTop="@dimen/spacing_large"
- android:paddingStart="@dimen/spacing_large"
android:paddingEnd="@dimen/spacing_large"
+ android:paddingStart="@dimen/spacing_large"
+ android:paddingTop="@dimen/spacing_large"
+ app:internalTextSize="34sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/multiple_partitions_header"
- app:internalTextSize="34sp"/>
+ app:layout_constraintTop_toBottomOf="@+id/multiple_partitions_header" />
<TextView
android:id="@+id/clear"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_button.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_button.xml
index e4c91ec..84e27be 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_button.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_button.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,7 @@
* limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools">
+ xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/navigation_button_layout"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_item.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_item.xml
index 2903c36..200ab16 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_item.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/navigation_item.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +14,8 @@
* limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
<android.support.constraint.ConstraintLayout
android:id="@+id/navigation_item_layout"
@@ -51,7 +50,7 @@
tools:text="@string/navigation_button_edittext_login_label" />
</android.support.v7.widget.CardView>
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/infoButton"
android:layout_width="wrap_content"
android:layout_height="0dp"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/virtual_login_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/virtual_login_activity.xml
index c144310..31ca52f 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/virtual_login_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/virtual_login_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -37,7 +36,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
- <com.example.android.autofill.app.InfoButton
+ <com.example.android.autofill.app.view.widget.InfoButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -49,15 +48,15 @@
app:layout_constraintStart_toEndOf="@+id/custom_virtual_login_header"
app:layout_constraintTop_toTopOf="@+id/custom_virtual_login_header" />
- <com.example.android.autofill.app.CustomVirtualView
+ <com.example.android.autofill.app.view.autofillable.CustomVirtualView
android:id="@+id/custom_view"
android:layout_width="match_parent"
android:layout_height="@dimen/custom_view_height"
- android:paddingTop="@dimen/spacing_large"
- android:paddingStart="@dimen/spacing_large"
- android:paddingEnd="@dimen/spacing_large"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
+ android:paddingEnd="@dimen/spacing_large"
+ android:paddingStart="@dimen/spacing_large"
+ android:paddingTop="@dimen/spacing_large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/custom_virtual_login_header" />
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/welcome_activity.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/welcome_activity.xml
index 60d6e1f..a400a84 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/welcome_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/layout/welcome_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/raw/sample_form.html b/prebuilts/gradle/AutofillFramework/Application/src/main/res/raw/sample_form.html
index 2a26223..076eead 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/raw/sample_form.html
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/raw/sample_form.html
@@ -1,5 +1,4 @@
-<!DOCTYPE html>
-<!--
+<!DOCTYPE html><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,18 +14,56 @@
* limitations under the License.
-->
<html>
-<body>
-<form>
- Username: <input type='text' name='username' autocomplete='username'/><br/><br/>
- Password: <input type='password' name='password' autocomplete='current-password'/><br/><br/>
- Work email: <input type='text' name='email' autocomplete='work email'/><br/><br/>
- Shipping address1: <input type='text' name='address'
- autocomplete='section-whatever shipping address-line1'/><br/>
- Shipping address2: <input type='text' name='address'
- autocomplete='shipping address-line2'/><br/>
- Shipping address3: <input type='text' name='address'
- autocomplete='section-whatever address-line3'/><br/><br/>
- <input type='submit' value='Login'/><br/>
-</form>
-</body>
+ <body>
+ <form>
+ Username:
+ <input
+ type='text'
+ name='username'
+ autocomplete='username' />
+ <br />
+ <br />
+ Password:
+ <input
+ type='password'
+ name='password'
+ autocomplete='current-password' />
+ <br />
+ <input
+ type='submit'
+ value='Login' />
+ </form>
+
+ <!-- Other autocomplete examples - they're not included because they would require
+ filling all fields to trigger Save when using the sample services
+
+ Work email:
+ <input
+ type='text'
+ name='email'
+ autocomplete='work email' />
+ <br />
+
+ Shipping address1:
+ <input
+ type='text'
+ name='address'
+ autocomplete='section-whatever shipping address-line1' />
+ <br />
+ Shipping address2:
+ <input
+ type='text'
+ name='address'
+ autocomplete='shipping address-line2' />
+ <br />
+ Shipping address3:
+ <input
+ type='text'
+ name='address'
+ autocomplete='section-whatever address-line3' />
+ <br />
+ <br />
+ </form>
+ -->
+ </body>
</html>
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/attrs.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/attrs.xml
index 23bf5cf..01328b8 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/attrs.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/attrs.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +17,10 @@
<declare-styleable name="NavigationItem">
<attr name="labelText" format="string" />
<attr name="infoText" format="string" />
+ <attr name="destinationActivityName" format="string" />
<attr name="itemLogo" format="integer" />
<attr name="imageColor" format="reference" />
+ <attr name="minSdk" format="integer" />
</declare-styleable>
<declare-styleable name="InfoButton">
<attr name="dialogText" format="string" />
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/dimens.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/dimens.xml
index 43410b8..965af8a 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/dimens.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/dimens.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/strings.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/strings.xml
index 15191d9..8b40483 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/strings.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +16,10 @@
<resources>
<string name="app_name">Autofill Sample</string>
+ <string name="edge_cases_page_title">Edge Cases</string>
+ <string name="common_cases_page_title">Common Cases</string>
<string name="navigation_button_custom_virtual_view_login_label">Sample Login Using a Custom Virtual View</string>
+ <string name="navigation_button_custom_virtual_view_compat_mode_login_label">Sample Login Using a Custom Virtual View and Compatibility Mode</string>
<string name="navigation_button_credit_card_label">Sample Credit Card Check Out Using EditTexts</string>
<string name="navigation_button_spinners_credit_card_label">Sample Credit Card Check Out Using Spinners</string>
<string name="navigation_button_edittext_login_label">Sample Login Using EditTexts</string>
@@ -25,9 +27,17 @@
<string name="navigation_button_email_compose_label">Sample Email Compose Using EditTexts</string>
<string name="navigation_button_compound_view_credit_card_label">Sample Credit Card Check Out Using Compound Views</string>
<string name="navigation_button_date_picker_credit_card_label">Sample Credit Card Check Out Using Date Picker</string>
+ <string name="navigation_button_recycler_view_label">Sample Credit Card Form Using RecyclerView</string>
<string name="navigation_button_multiple_partitions_label">Sample Page with Multiple Data Partitions</string>
<string name="navigation_button_web_view_login_label">Sample Login Using a WebView</string>
<string name="navigation_button_anti_pattern_credit_card_label">Sample Credit Card Anti Pattern</string>
+ <string name="navigation_button_anti_pattern_bad_view_structure_label">Bad View Structure Creation Anti Pattern</string>
+ <string name="navigation_button_multistep_signin_label">Multi-Step Sign In</string>
+ <string name="navigation_button_multistep_cc_label">Multi-Step Credit Card Check Out</string>
+ <string name="navigation_button_anti_pattern_multistep_signin_label">Multi-Step Sign In Anti Pattern</string>
+ <string name="navigation_button_anti_pattern_hintless_signin_label">Hintless Sign In Anti Pattern</string>
+ <string name="navigation_button_anti_pattern_callbackless_autocomplete_login_label">Auto Complete without Autofill Integration Anti Pattern</string>
+ <string name="navigation_button_custom_theme_login_label">Sign In Using Custom Theme</string>
<string name="username_label">Username</string>
<string name="password_label">Password</string>
<string name="welcome_text">Success!</string>
@@ -66,6 +76,11 @@
virtual children out of the box, it is necessary implement certain Autofill-specific methods
and interface directly with AutofillManager.
</string>
+ <string name="custom_virtual_compat_mode_login_info">This is a sample login page that uses a
+ custom View with virtual children. This view does not implement the Autofill APIs, but
+ it generates Accessibility events, which can be used to implement Autofill through a
+ 'compatibility mode' feature introduced on Android Pie.
+ </string>
<string name="credit_card_info">This is a sample credit card checkout page that uses
EditTexts to input data into the form.
</string>
@@ -100,6 +115,11 @@
While the EditText is optimized out of the box for autofill, this example shows how to
use it to autofill a date field.
</string>
+ <string name="recycler_view_info">
+ This is a sample form that has a list of fields in a RecyclerView. It demos the new APIs in
+ API 28 that allow you to dynamically change the AutofillId associated with a View. This is
+ needed when Views are being recycled, as they are in a RecyclerView.
+ </string>
<string name="multiple_partitions">
This is a sample page that contains multiple partitions (login credentials, address,
credit card info) and can be used to make sure that only one partition can be autofilled
@@ -116,6 +136,33 @@
is through a View.AUTOFILL_TYPE_DATE value, which is what the other credit card sample
activities use.
</string>
+ <string name="anti_pattern_bad_view_structure_info">This is a simple login page where the view
+ structure is created onStart() instead of onCreate(), which causes autofill to misbehave
+ when the autofill service requires authentication.
+ </string>
+ <string name="anti_pattern_hintless_signin_info">This is a sample login page that uses standard EditTexts
+ from the UI toolkit, but without annotating them with android:autofillHints.
+ </string>
+
+ <string name="multi_step_signin_info">
+ <!--TODO-->
+ </string>
+
+ <string name="multi_step_cc_info">
+ <!--TODO-->
+ </string>
+
+ <string name="anti_pattern_multistep_signin_info">
+ <!--TODO-->
+ </string>
+
+ <string name="anti_pattern_callbackless_autocomplete_login_info">
+ <!--TODO-->
+ </string>
+
+ <string name="custom_theme_login_info">
+ <!--TODO-->
+ </string>
<string name="partition_credentials">Credentials</string>
<string name="partition_credit_card">Credit Card</string>
@@ -127,14 +174,21 @@
<string name="message_autofill_invalid">INVALID</string>
<string name="message_credit_card_expiration_type">Representing expiration dates as %1$s</string>
+ <string name="message_finished">Finished</string>
+ <string name="message_showing_step">Showing step %1$d</string>
+ <string name="message_step_description">%1$s: %2$s</string>
+
+ <string name="previous_label">Prev</string>
+ <string name="next_label">Next</string>
+ <string name="finish_label">Finish</string>
+
<plurals name="welcome_page_countdown">
<item quantity="one">Automatically return to main page in %d second.</item>
<item quantity="other">Automatically return to main page in %d seconds.</item>
</plurals>
<string-array name="mock_autocomplete_sign_in_suggestions">
- <item>user-1</item>
- <item>user-2</item>
+ <item>app_provided_user</item>
</string-array>
<string-array name="month_array">
@@ -182,4 +236,18 @@
<item>27</item>
</string-array>
+ <string name="recycler_view_label_name">Name</string>
+ <string name="recycler_view_label_birthday_month">Birthday Month</string>
+ <string name="recycler_view_label_birthday_year">Birthday Year</string>
+ <string name="recycler_view_label_email">Email</string>
+ <string name="recycler_view_label_phone">Telephone</string>
+ <string name="recycler_view_label_tel_extension">Tel. Extension</string>
+ <string name="recycler_view_label_cc_number">CC Number</string>
+ <string name="recycler_view_label_cc_sc">CSC</string>
+ <string name="recycler_view_label_cc_exp_month">CC Exp Month</string>
+ <string name="recycler_view_label_cc_exp_year">CC Exp Year</string>
+ <string name="recycler_view_label_address_line_1">Address Line 1</string>
+ <string name="recycler_view_label_address_line_2">Address Line 2</string>
+ <string name="recycler_view_label_address_line_3">Address Line 3</string>
+ <string name="recycler_view_label_postal_code">Postal Code</string>
</resources>
diff --git a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/styles.xml b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/styles.xml
index 39e5ba8..e7549ac 100644
--- a/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/styles.xml
+++ b/prebuilts/gradle/AutofillFramework/Application/src/main/res/values/styles.xml
@@ -15,6 +15,14 @@
-->
<resources>
+ <style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+ <style name="CustomAutofilledHighlightTheme" parent="AppTheme">
+ <item name="android:autofilledHighlight">@drawable/custom_autofilled_highlight</item>
+ </style>
+
<style name="CustomDatePickerDialogTheme" parent="android:Theme.Material.Light.Dialog">
<item name="android:datePickerStyle">@style/MyDatePickerStyle</item>
</style>
diff --git a/prebuilts/gradle/AutofillFramework/README.md b/prebuilts/gradle/AutofillFramework/README.md
index fe05df5..66c9343 100644
--- a/prebuilts/gradle/AutofillFramework/README.md
+++ b/prebuilts/gradle/AutofillFramework/README.md
@@ -131,7 +131,7 @@
--------------
- Android SDK 26
-- Android Build Tools v27.0.2
+- Android Build Tools v27.0.3
- Android Support Repository
Screenshots
diff --git a/prebuilts/gradle/AutofillFramework/afservice/build.gradle b/prebuilts/gradle/AutofillFramework/afservice/build.gradle
index f98116c..0d8bd19 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/build.gradle
+++ b/prebuilts/gradle/AutofillFramework/afservice/build.gradle
@@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 26
- targetSdkVersion 26
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
@@ -15,6 +15,10 @@
buildTypes {
release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
@@ -26,10 +30,22 @@
}
dependencies {
- implementation 'com.android.support:appcompat-v7:26.1.0'
+ implementation 'com.android.support:appcompat-v7:28.0.0-alpha1'
+ implementation "android.arch.persistence.room:runtime:1.0.0"
+ annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'com.android.support:design:26.1.0'
+ implementation 'com.android.support:design:28.0.0-alpha1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
- implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.1'
+ implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.2'
+ implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation group: 'com.google.guava', name: 'guava', version: '22.0-android'
+ implementation "com.android.support.test.espresso:espresso-idling-resource:3.0.1"
+ implementation "com.google.code.findbugs:jsr305:3.0.2"
+
+ androidTestImplementation "junit:junit:4.12"
+ androidTestImplementation ("com.android.support.test.espresso:espresso-core:3.0.1")
+ androidTestImplementation "com.android.support.test.espresso:espresso-contrib:3.0.1"
+ androidTestImplementation "com.android.support.test.espresso:espresso-intents:3.0.1"
+ androidTestImplementation "com.android.support.test.espresso.idling:idling-concurrent:3.0.1"
+
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/proguard-rules.pro b/prebuilts/gradle/AutofillFramework/afservice/proguard-rules.pro
index f1b4245..fc3ef4e 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/proguard-rules.pro
+++ b/prebuilts/gradle/AutofillFramework/afservice/proguard-rules.pro
@@ -4,7 +4,11 @@
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
-
+# Disable warnings from the following packages
+-dontwarn okio.**
+-dontwarn retrofit2.Platform$Java8
+-dontwarn com.google.common.**
+-dontwarn com.google.errorprone.annotations.**
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
@@ -19,3 +23,7 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+-keep class com.google.common.base.Preconditions { *; }
+-keep class android.arch.** { *; }
+-keep class com.example.android.autofill.service.** { *; }
+
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/AndroidManifest.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/AndroidManifest.xml
index f03a454..9bfff73 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/AndroidManifest.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/AndroidManifest.xml
@@ -1,36 +1,88 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.autofill.service">
+ package="com.example.android.autofill.service">
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true"
- android:theme="@style/AppTheme" >
- <!--
-Declare AutofillService implementation; only needed for a small number of apps that will
-be implementing an AutofillService. Framework parses meta-data and sets the service's
-Settings Activity based on what the meta-data resource points to.
--->
- <service
- android:name=".MyAutofillService"
- android:label="Multi-Dataset Autofill Service"
- android:permission="android.permission.BIND_AUTOFILL_SERVICE">
- <meta-data
- android:name="android.autofill"
- android:resource="@xml/multidataset_service" />
+ android:theme="@style/AppTheme">
+ <!--
+ Declare AutofillService implementation; only needed for a small number of apps that will
+ be implementing an AutofillService. Framework parses meta-data and sets the service's
+ Settings Activity based on what the meta-data resource points to.
+ -->
+ <service
+ android:name=".MyAutofillService"
+ android:label="Multi-Dataset Autofill Service"
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE">
+ <meta-data
+ android:name="android.autofill"
+ android:resource="@xml/multidataset_service" />
- <intent-filter>
- <action android:name="android.service.autofill.AutofillService" />
- </intent-filter>
- </service>
+ <intent-filter>
+ <action android:name="android.service.autofill.AutofillService" />
+ </intent-filter>
+ </service>
- <activity android:name=".AuthActivity" />
+ <service
+ android:name=".simple.BasicService"
+ android:label="Basic Autofill Service"
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.autofill.AutofillService" />
+ </intent-filter>
+ </service>
+
+ <service
+ android:name=".simple.DebugService"
+ android:label="Debug Autofill Service"
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE">
+ <meta-data
+ android:name="android.autofill"
+ android:resource="@xml/debug_service"/>
+ <intent-filter>
+ <action android:name="android.service.autofill.AutofillService" />
+ </intent-filter>
+ </service>
+
+ <service
+ android:name=".simple.MultiStepsService"
+ android:label="Multiple-steps Service"
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.autofill.AutofillService" />
+ </intent-filter>
+ </service>
+
+ <activity
+ android:name=".AuthActivity"
+ android:taskAffinity=".AuthActivity"
+ android:label="@string/authentication_name" />
+
+ <activity
+ android:name=".simple.SimpleAuthActivity"
+ android:taskAffinity=".simple.SimpleAuthActivity"
+ android:label="@string/authentication_name" />
+
+ <activity
+ android:name=".ManualActivity"
+ android:taskAffinity=".ManualActivity"
+ android:label="@string/manual_name" />
+
+ <activity
+ android:name=".ManualFieldPickerActivity"
+ android:taskAffinity=".ManualActivity"
+ android:label="@string/manual_field_picker_name" />
+
<!-- Including launcher icon for Autofill Settings to convenience. Not necessary for a
real service. -->
<activity
android:name=".settings.SettingsActivity"
android:exported="true"
android:label="@string/settings_name"
- android:taskAffinity=".SettingsActivity">
+ android:taskAffinity=".settings.SettingsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
index e995160..e1660b7 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AuthActivity.java
@@ -20,29 +20,43 @@
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;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.EditText;
+import android.widget.RemoteViews;
import android.widget.Toast;
-import com.example.android.autofill.service.datasource.SharedPrefsAutofillRepository;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+import com.example.android.autofill.service.data.ClientViewMetadata;
+import com.example.android.autofill.service.data.ClientViewMetadataBuilder;
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.data.adapter.DatasetAdapter;
+import com.example.android.autofill.service.data.adapter.ResponseAdapter;
+import com.example.android.autofill.service.data.source.DefaultFieldTypesSource;
+import com.example.android.autofill.service.data.source.local.DefaultFieldTypesLocalJsonSource;
+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.model.FieldTypeWithHeuristics;
import com.example.android.autofill.service.settings.MyPreferences;
+import com.example.android.autofill.service.util.AppExecutors;
+import com.google.gson.GsonBuilder;
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;
-import static com.example.android.autofill.service.CommonUtil.EXTRA_DATASET_NAME;
-import static com.example.android.autofill.service.CommonUtil.EXTRA_FOR_RESPONSE;
-import static com.example.android.autofill.service.CommonUtil.TAG;
+import static com.example.android.autofill.service.util.Util.EXTRA_DATASET_NAME;
+import static com.example.android.autofill.service.util.Util.EXTRA_FOR_RESPONSE;
+import static com.example.android.autofill.service.util.Util.logw;
+
/**
* This Activity controls the UI for logging in to the Autofill service.
@@ -54,20 +68,28 @@
// Unique id for dataset intents.
private static int sDatasetPendingIntentId = 0;
+ private LocalAutofillDataSource mLocalAutofillDataSource;
+ private DigitalAssetLinksRepository mDalRepository;
private EditText mMasterPassword;
+ private DatasetAdapter mDatasetAdapter;
+ private ResponseAdapter mResponseAdapter;
+ private ClientViewMetadata mClientViewMetadata;
+ private String mPackageName;
private Intent mReplyIntent;
+ private MyPreferences mPreferences;
- 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();
}
@@ -75,33 +97,35 @@
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multidataset_service_auth_activity);
+ SharedPreferences sharedPreferences =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ DefaultFieldTypesSource defaultFieldTypesSource =
+ DefaultFieldTypesLocalJsonSource.getInstance(getResources(),
+ new GsonBuilder().create());
+ AutofillDao autofillDao = AutofillDatabase.getInstance(this,
+ defaultFieldTypesSource, new AppExecutors()).autofillDao();
+ mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(sharedPreferences,
+ autofillDao, new AppExecutors());
+ mDalRepository = DigitalAssetLinksRepository.getInstance(getPackageManager());
mMasterPassword = findViewById(R.id.master_password);
- findViewById(R.id.login).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- login();
- }
-
- });
- findViewById(R.id.cancel).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onFailure();
- AuthActivity.this.finish();
- }
+ mPackageName = getPackageName();
+ mPreferences = MyPreferences.getInstance(this);
+ findViewById(R.id.login).setOnClickListener((view) -> login());
+ findViewById(R.id.cancel).setOnClickListener((view) -> {
+ onFailure();
+ AuthActivity.this.finish();
});
}
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();
onFailure();
}
- finish();
}
@Override
@@ -115,7 +139,7 @@
}
private void onFailure() {
- Log.w(TAG, "Failed auth.");
+ logw("Failed auth.");
mReplyIntent = null;
}
@@ -123,22 +147,74 @@
Intent intent = getIntent();
boolean forResponse = intent.getBooleanExtra(EXTRA_FOR_RESPONSE, true);
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
- StructureParser parser = new StructureParser(getApplicationContext(), structure);
- parser.parseForFill();
- AutofillFieldMetadataCollection autofillFields = parser.getAutofillFields();
- int saveTypes = autofillFields.getSaveType();
+ ClientParser clientParser = new ClientParser(structure);
mReplyIntent = new Intent();
- HashMap<String, FilledAutofillFieldCollection> clientFormDataMap =
- SharedPrefsAutofillRepository.getInstance().getFilledAutofillFieldCollection
- (this, autofillFields.getFocusedHints(), autofillFields.getAllHints());
- if (forResponse) {
- setResponseIntent(AutofillHelper.newResponse
- (this, false, autofillFields, clientFormDataMap));
- } else {
- String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
- setDatasetIntent(AutofillHelper.newDataset
- (this, autofillFields, clientFormDataMap.get(datasetName), false));
- }
+ mLocalAutofillDataSource.getFieldTypeByAutofillHints(
+ new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
+ @Override
+ public void onLoaded(HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
+ ClientViewMetadataBuilder builder = new ClientViewMetadataBuilder(clientParser,
+ fieldTypesByAutofillHint);
+ mClientViewMetadata = builder.buildClientViewMetadata();
+ mDatasetAdapter = new DatasetAdapter(clientParser);
+ mResponseAdapter = new ResponseAdapter(AuthActivity.this,
+ mClientViewMetadata, mPackageName, mDatasetAdapter);
+ if (forResponse) {
+ fetchAllDatasetsAndSetIntent(fieldTypesByAutofillHint);
+ } else {
+ String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
+ fetchDatasetAndSetIntent(fieldTypesByAutofillHint, datasetName);
+ }
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+
+ }
+ });
+ }
+
+ private void fetchDatasetAndSetIntent(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint, 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(fieldTypesByAutofillHint,
+ dataset, remoteViews));
+ finish();
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ finish();
+ }
+ });
+ }
+
+ private void fetchAllDatasetsAndSetIntent(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
+ mLocalAutofillDataSource.getAutofillDatasets(mClientViewMetadata.getAllHints(),
+ new DataCallback<List<DatasetWithFilledAutofillFields>>() {
+ @Override
+ public void onLoaded(List<DatasetWithFilledAutofillFields> datasets) {
+ boolean datasetAuth = mPreferences.isDatasetAuth();
+ FillResponse fillResponse = mResponseAdapter.buildResponse(
+ fieldTypesByAutofillHint, datasets, datasetAuth);
+ setResponseIntent(fillResponse);
+ finish();
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ finish();
+ }
+ });
}
private void setResponseIntent(FillResponse fillResponse) {
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadata.java
deleted file mode 100644
index ab15e3f..0000000
--- a/prebuilts/gradle/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/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillFieldMetadataCollection.java
deleted file mode 100644
index d343ff2..0000000
--- a/prebuilts/gradle/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/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java
deleted file mode 100644
index 4161724..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHelper.java
+++ /dev/null
@@ -1,116 +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.service.autofill.Dataset;
-import android.service.autofill.FillResponse;
-import android.service.autofill.SaveInfo;
-import android.support.annotation.DrawableRes;
-import android.util.Log;
-import android.view.autofill.AutofillId;
-import android.widget.RemoteViews;
-
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-
-import java.util.HashMap;
-import java.util.Set;
-
-import static com.example.android.autofill.service.CommonUtil.TAG;
-
-/**
- * This is a class containing helper methods for building Autofill Datasets and Responses.
- */
-public final class AutofillHelper {
-
- 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.getDatasetName();
- if (datasetName != null) {
- 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,
- 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);
- }
- }
- }
- }
- if (autofillFields.getSaveType() != 0) {
- AutofillId[] autofillIds = autofillFields.getAutofillIds();
- responseBuilder.setSaveInfo
- (new SaveInfo.Builder(autofillFields.getSaveType(), autofillIds).build());
- return responseBuilder.build();
- } else {
- Log.d(TAG, "These fields are not meant to be saved by autofill.");
- return null;
- }
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java
index 1be307c..8314eb3 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHintProperties.java
+++ b/prebuilts/gradle/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;
@@ -44,8 +46,8 @@
/**
* Generates dummy autofill field data that is relevant to the autofill hint.
*/
- public FilledAutofillField generateFakeField(int seed) {
- return mFakeFieldGenerator.generate(seed);
+ public FilledAutofillField generateFakeField(int seed, String datasetId) {
+ return mFakeFieldGenerator.generate(seed, datasetId);
}
/**
@@ -77,10 +79,14 @@
/**
* 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);
}
+
+ public Set<Integer> getTypes() {
+ return mValidTypes;
+ }
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
index 7c00399..d43071f 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/AutofillHints.java
@@ -15,19 +15,25 @@
*/
package com.example.android.autofill.service;
-import android.service.autofill.SaveInfo;
-import android.util.Log;
-import android.view.View;
+import android.support.annotation.NonNull;
+import com.example.android.autofill.service.model.FakeData;
+import com.example.android.autofill.service.model.FieldType;
+import com.example.android.autofill.service.model.FieldTypeWithHeuristics;
import com.example.android.autofill.service.model.FilledAutofillField;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
-import static com.example.android.autofill.service.CommonUtil.TAG;
+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;
@@ -35,740 +41,135 @@
public static final int[] PARTITIONS = {
PARTITION_OTHER, PARTITION_ADDRESS, PARTITION_EMAIL, PARTITION_CREDIT_CARD
};
- /* TODO: finish building fake data for all hints. */
- private static final ImmutableMap<String, AutofillHintProperties> sValidHints =
- new ImmutableMap.Builder<String, AutofillHintProperties>()
- .put(View.AUTOFILL_HINT_EMAIL_ADDRESS, new AutofillHintProperties(
- View.AUTOFILL_HINT_EMAIL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS,
- PARTITION_EMAIL,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_EMAIL_ADDRESS);
- filledAutofillField.setTextValue("email" + seed);
- return filledAutofillField;
- }, 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_NAME);
- filledAutofillField.setTextValue("name" + seed);
- return filledAutofillField;
- }, 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_USERNAME);
- filledAutofillField.setTextValue("login" + seed);
- return filledAutofillField;
- }, 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_PASSWORD);
- filledAutofillField.setTextValue("login" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(View.AUTOFILL_HINT_PHONE, new AutofillHintProperties(
- View.AUTOFILL_HINT_PHONE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_PHONE);
- filledAutofillField.setTextValue("" + seed + "2345678910");
- 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,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_ADDRESS);
- filledAutofillField.setTextValue(
- "" + seed + " Fake Ln, Fake, FA, FAA 10001");
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_CODE);
- filledAutofillField.setTextValue("1000" + seed);
- 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,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD,
- PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
- filledAutofillField.setTextValue("" + seed + "234567");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD,
- PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
- filledAutofillField.setTextValue("" + seed + seed + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
- new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
- Calendar calendar = Calendar.getInstance();
- calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed);
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_DATE))
- .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
- new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- CharSequence[] months = monthRange();
- int month = seed % months.length;
- Calendar calendar = Calendar.getInstance();
- calendar.set(Calendar.MONTH, month);
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
- filledAutofillField.setListValue(months, month);
- filledAutofillField.setTextValue(Integer.toString(month));
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
- View.AUTOFILL_TYPE_DATE))
- .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
- Calendar calendar = Calendar.getInstance();
- int expYear = calendar.get(Calendar.YEAR) + seed;
- calendar.set(Calendar.YEAR, expYear);
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- filledAutofillField.setTextValue(Integer.toString(expYear));
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
- View.AUTOFILL_TYPE_DATE))
- .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- CharSequence[] days = dayRange();
- int day = seed % days.length;
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY);
- Calendar calendar = Calendar.getInstance();
- calendar.set(Calendar.DATE, day);
- filledAutofillField.setListValue(days, day);
- filledAutofillField.setTextValue(Integer.toString(day));
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST,
- View.AUTOFILL_TYPE_DATE))
- .put(W3cHints.HONORIFIC_PREFIX, new AutofillHintProperties(
- W3cHints.HONORIFIC_PREFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- W3cHints.HONORIFIC_PREFIX);
- CharSequence[] examplePrefixes = {"Miss", "Ms.", "Mr.", "Mx.",
- "Sr.", "Dr.", "Lady", "Lord"};
- filledAutofillField.setListValue(examplePrefixes,
- seed % examplePrefixes.length);
- return filledAutofillField;
- }, 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.GIVEN_NAME);
- filledAutofillField.setTextValue("name" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDITIONAL_NAME, new AutofillHintProperties(
- W3cHints.ADDITIONAL_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDITIONAL_NAME);
- filledAutofillField.setTextValue("addtlname" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.FAMILY_NAME, new AutofillHintProperties(
- W3cHints.FAMILY_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.FAMILY_NAME);
- filledAutofillField.setTextValue("famname" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.HONORIFIC_SUFFIX, new AutofillHintProperties(
- W3cHints.HONORIFIC_SUFFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.HONORIFIC_SUFFIX);
- CharSequence[] exampleSuffixes = {"san", "kun", "chan", "sama"};
- filledAutofillField.setListValue(exampleSuffixes,
- seed % exampleSuffixes.length);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.NEW_PASSWORD);
- filledAutofillField.setTextValue("login" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.CURRENT_PASSWORD, new AutofillHintProperties(
- View.AUTOFILL_HINT_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_PASSWORD);
- filledAutofillField.setTextValue("login" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ORGANIZATION_TITLE, new AutofillHintProperties(
- W3cHints.ORGANIZATION_TITLE, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ORGANIZATION_TITLE);
- filledAutofillField.setTextValue("org" + seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ORGANIZATION);
- filledAutofillField.setTextValue("org" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .put(W3cHints.STREET_ADDRESS, new AutofillHintProperties(
- W3cHints.STREET_ADDRESS, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.STREET_ADDRESS);
- filledAutofillField.setTextValue(
- "" + seed + " Fake Ln, Fake, FA, FAA 10001");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LINE1, new AutofillHintProperties(W3cHints.ADDRESS_LINE1,
- SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LINE1);
- filledAutofillField.setTextValue("" + seed + " Fake Ln");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LINE2, new AutofillHintProperties(W3cHints.ADDRESS_LINE2,
- SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LINE2);
- filledAutofillField.setTextValue("Apt. " + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LINE3, new AutofillHintProperties(W3cHints.ADDRESS_LINE3,
- SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LINE3);
- filledAutofillField.setTextValue("FA" + seed + ", FA, FAA");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LEVEL4, new AutofillHintProperties(
- W3cHints.ADDRESS_LEVEL4, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LEVEL4);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LEVEL3, new AutofillHintProperties(
- W3cHints.ADDRESS_LEVEL3, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LEVEL3);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LEVEL2, new AutofillHintProperties(
- W3cHints.ADDRESS_LEVEL2, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LEVEL2);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.ADDRESS_LEVEL1, new AutofillHintProperties(
- W3cHints.ADDRESS_LEVEL1, SaveInfo.SAVE_DATA_TYPE_ADDRESS,
- PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.ADDRESS_LEVEL1);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.COUNTRY, new AutofillHintProperties(W3cHints.COUNTRY,
- SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.COUNTRY);
- 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,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.COUNTRY_NAME);
- CharSequence[] exampleCountries = {"USA", "Mexico", "Canada"};
- filledAutofillField.setListValue(exampleCountries,
- seed % exampleCountries.length);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_CODE);
- filledAutofillField.setTextValue("" + seed + seed + seed + seed +
- seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.CC_NAME);
- filledAutofillField.setTextValue("firstname" + seed + "lastname" +
- seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.CC_GIVEN_NAME);
- filledAutofillField.setTextValue("givenname" + seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.CC_ADDITIONAL_NAME);
- filledAutofillField.setTextValue("addtlname" + seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.CC_FAMILY_NAME);
- filledAutofillField.setTextValue("familyname" + seed);
- 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) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_NUMBER);
- filledAutofillField.setTextValue("" + seed + "234567");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.CC_EXPIRATION, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE);
- Calendar calendar = Calendar.getInstance();
- calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed);
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_DATE))
- .put(W3cHints.CC_EXPIRATION_MONTH, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH);
- CharSequence[] months = monthRange();
- filledAutofillField.setListValue(months,
- seed % months.length);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .put(W3cHints.CC_EXPIRATION_YEAR, new AutofillHintProperties(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
- SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD,
- (seed) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR);
- Calendar calendar = Calendar.getInstance();
- int expYear = calendar.get(Calendar.YEAR) + seed;
- calendar.set(Calendar.YEAR, expYear);
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- filledAutofillField.setTextValue("" + expYear);
- 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) -> {
- FilledAutofillField filledAutofillField = new FilledAutofillField(
- View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE);
- filledAutofillField.setTextValue("" + seed + seed + seed);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.CC_TYPE);
- filledAutofillField.setTextValue("type" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .put(W3cHints.TRANSACTION_CURRENCY, new AutofillHintProperties(
- W3cHints.TRANSACTION_CURRENCY, SaveInfo.SAVE_DATA_TYPE_GENERIC,
- PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.TRANSACTION_CURRENCY);
- CharSequence[] exampleCurrencies = {"USD", "CAD", "KYD", "CRC"};
- filledAutofillField.setListValue(exampleCurrencies,
- seed % exampleCurrencies.length);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.TRANSACTION_AMOUNT);
- filledAutofillField.setTextValue("" + seed * 100);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .put(W3cHints.LANGUAGE, new AutofillHintProperties(W3cHints.LANGUAGE,
- SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.LANGUAGE);
- CharSequence[] exampleLanguages = {"Bulgarian", "Croatian", "Czech",
- "Danish", "Dutch", "English", "Estonian"};
- filledAutofillField.setListValue(exampleLanguages,
- seed % exampleLanguages.length);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .put(W3cHints.BDAY, new AutofillHintProperties(W3cHints.BDAY,
- SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.BDAY);
- Calendar calendar = Calendar.getInstance();
- calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - seed * 10);
- calendar.set(Calendar.MONTH, seed % 12);
- calendar.set(Calendar.DATE, seed % 27);
- filledAutofillField.setDateValue(calendar.getTimeInMillis());
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_DATE))
- .put(W3cHints.BDAY_DAY, new AutofillHintProperties(W3cHints.BDAY_DAY,
- SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.BDAY_DAY);
- filledAutofillField.setTextValue("" + seed % 27);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.BDAY_MONTH);
- filledAutofillField.setTextValue("" + seed % 12);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.BDAY_YEAR);
- int year = Calendar.getInstance().get(Calendar.YEAR) - seed * 10;
- filledAutofillField.setTextValue("" + year);
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.SEX);
- filledAutofillField.setTextValue("Other");
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.URL);
- filledAutofillField.setTextValue("http://google.com");
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.PHOTO, new AutofillHintProperties(W3cHints.PHOTO,
- SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.PHOTO);
- filledAutofillField.setTextValue("photo" + seed + ".jpg");
- 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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(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) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(View.AUTOFILL_HINT_EMAIL_ADDRESS);
- filledAutofillField.setTextValue("email" + seed);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT))
- .put(W3cHints.IMPP, new AutofillHintProperties(W3cHints.IMPP,
- SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS, PARTITION_EMAIL,
- (seed) -> {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(W3cHints.IMPP);
- return filledAutofillField;
- }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST))
- .build();
private AutofillHints() {
}
- public static boolean isValidTypeForHints(String[] hints, int type) {
- if (hints != null) {
- for (String hint : hints) {
- if (hint != null && sValidHints.containsKey(hint)) {
- boolean valid = sValidHints.get(hint).isValidType(type);
- if (valid) {
- return true;
- }
+ public static FilledAutofillField generateFakeField(
+ FieldTypeWithHeuristics fieldTypeWithHeuristics, String packageName, int seed,
+ String datasetId) {
+ FakeData fakeData = fieldTypeWithHeuristics.fieldType.getFakeData();
+ String fieldTypeName = fieldTypeWithHeuristics.fieldType.getTypeName();
+ String text = null;
+ Long date = null;
+ Boolean toggle = null;
+ if (fakeData.strictExampleSet != null && fakeData.strictExampleSet.strings != null &&
+ fakeData.strictExampleSet.strings.size() > 0 &&
+ !fakeData.strictExampleSet.strings.get(0).isEmpty()) {
+ List<String> choices = fakeData.strictExampleSet.strings;
+ text = choices.get(seed % choices.size());
+ } else if (fakeData.textTemplate != null) {
+ text = fakeData.textTemplate.replace("seed", "" + seed)
+ .replace("curr_time", "" + Calendar.getInstance().getTimeInMillis());
+ } else if (fakeData.dateTemplate != null) {
+ if (fakeData.dateTemplate.contains("curr_time")) {
+ date = Calendar.getInstance().getTimeInMillis();
+ }
+ }
+ return new FilledAutofillField(datasetId, fieldTypeName, text, date, toggle);
+ }
+
+ public static String getFieldTypeNameFromAutofillHints(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint,
+ @NonNull List<String> hints) {
+ return getFieldTypeNameFromAutofillHints(fieldTypesByAutofillHint, hints, PARTITION_ALL);
+ }
+
+ public static String getFieldTypeNameFromAutofillHints(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint,
+ @NonNull List<String> hints, int partition) {
+ List<String> fieldTypeNames = removePrefixes(hints)
+ .stream()
+ .filter(fieldTypesByAutofillHint::containsKey)
+ .map(fieldTypesByAutofillHint::get)
+ .filter(Objects::nonNull)
+ .filter((fieldTypeWithHints) ->
+ matchesPartition(fieldTypeWithHints.fieldType.getPartition(), partition))
+ .map(FieldTypeWithHeuristics::getFieldType).map(FieldType::getTypeName)
+ .collect(toList());
+ if (fieldTypeNames != null && fieldTypeNames.size() > 0) {
+ return fieldTypeNames.get(0);
+ } else {
+ return null;
+ }
+ }
+
+ public static boolean matchesPartition(int partition, int otherPartition) {
+ return partition == PARTITION_ALL || otherPartition == PARTITION_ALL ||
+ partition == otherPartition;
+ }
+
+ 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 boolean isW3cSectionPrefix(@NonNull String hint) {
+ return hint.startsWith(W3cHints.PREFIX_SECTION);
+ }
+
+ private static boolean isW3cAddressType(@NonNull String hint) {
+ switch (hint) {
+ case W3cHints.SHIPPING:
+ case W3cHints.BILLING:
+ return true;
}
return false;
}
- public static boolean isValidHint(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();
- }
- }
+ private static boolean isW3cTypePrefix(@NonNull String hint) {
+ switch (hint) {
+ case W3cHints.PREFIX_WORK:
+ case W3cHints.PREFIX_FAX:
+ case W3cHints.PREFIX_HOME:
+ case W3cHints.PREFIX_PAGER:
+ return true;
}
- return saveType;
+ return false;
}
- public static FilledAutofillField getFakeField(String hint, int seed) {
- return sValidHints.get(hint).generateFakeField(seed);
- }
-
- public static FilledAutofillFieldCollection getFakeFieldCollection(int partition, int seed) {
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- new FilledAutofillFieldCollection();
- for (String hint : sValidHints.keySet()) {
- if (hint != null && sValidHints.get(hint).getPartition() == partition) {
- FilledAutofillField fakeField = getFakeField(hint, seed);
- filledAutofillFieldCollection.add(fakeField);
- }
+ private static boolean isW3cTypeHint(@NonNull String hint) {
+ switch (hint) {
+ case W3cHints.TEL:
+ case W3cHints.TEL_COUNTRY_CODE:
+ case W3cHints.TEL_NATIONAL:
+ case W3cHints.TEL_AREA_CODE:
+ case W3cHints.TEL_LOCAL:
+ case W3cHints.TEL_LOCAL_PREFIX:
+ case W3cHints.TEL_LOCAL_SUFFIX:
+ case W3cHints.TEL_EXTENSION:
+ case W3cHints.EMAIL:
+ case W3cHints.IMPP:
+ return true;
}
- return filledAutofillFieldCollection;
- }
-
- private static String getStoredHintName(String hint) {
- return sValidHints.get(hint).getAutofillHint();
- }
-
- public static void convertToStoredHintNames(String[] hints) {
- for (int i = 0; i < hints.length; i++) {
- hints[i] = getStoredHintName(hints[i]);
- }
- }
-
- private static CharSequence[] dayRange() {
- CharSequence[] days = new CharSequence[27];
- for (int i = 0; i < days.length; i++) {
- days[i] = Integer.toString(i);
- }
- return days;
- }
-
- private static CharSequence[] monthRange() {
- CharSequence[] months = new CharSequence[12];
- for (int i = 0; i < months.length; i++) {
- months[i] = Integer.toString(i);
- }
- 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 {
- Log.w(TAG, "Invalid autofill hint: " + hint);
- }
- }
- if (i == 0) {
- return null;
- }
- String[] finalFilteredHints = new String[i];
- System.arraycopy(filteredHints, 0, finalFilteredHints, 0, i);
- return finalFilteredHints;
+ logw("Invalid W3C type hint: %s", hint);
+ return false;
}
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/CommonUtil.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/CommonUtil.java
deleted file mode 100644
index f3f169f..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/CommonUtil.java
+++ /dev/null
@@ -1,154 +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;
-import android.app.assist.AssistStructure.ViewNode;
-import android.app.assist.AssistStructure.WindowNode;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewStructure.HtmlInfo;
-import android.view.autofill.AutofillValue;
-
-import java.util.Arrays;
-import java.util.Set;
-
-public final class CommonUtil {
-
- public static final String TAG = "AutofillSample";
- public static final boolean DEBUG = true;
- public static final boolean VERBOSE = false;
- public static final String EXTRA_DATASET_NAME = "dataset_name";
- public static final String EXTRA_FOR_RESPONSE = "for_response";
-
- private static void bundleToString(StringBuilder builder, Bundle data) {
- final Set<String> keySet = data.keySet();
- builder.append("[Bundle with ").append(keySet.size()).append(" keys:");
- for (String key : keySet) {
- builder.append(' ').append(key).append('=');
- Object value = data.get(key);
- if ((value instanceof Bundle)) {
- bundleToString(builder, (Bundle) value);
- } else {
- builder.append((value instanceof Object[])
- ? Arrays.toString((Object[]) value) : value);
- }
- }
- builder.append(']');
- }
-
- public static String bundleToString(Bundle data) {
- if (data == null) {
- return "N/A";
- }
- final StringBuilder builder = new StringBuilder();
- bundleToString(builder, data);
- return builder.toString();
- }
-
- public static String getTypeAsString(int type) {
- switch (type) {
- case View.AUTOFILL_TYPE_TEXT:
- return "TYPE_TEXT";
- case View.AUTOFILL_TYPE_LIST:
- return "TYPE_LIST";
- case View.AUTOFILL_TYPE_NONE:
- return "TYPE_NONE";
- case View.AUTOFILL_TYPE_TOGGLE:
- return "TYPE_TOGGLE";
- case View.AUTOFILL_TYPE_DATE:
- return "TYPE_DATE";
- }
- return "UNKNOWN_TYPE";
- }
-
- private static String getAutofillValueAndTypeAsString(AutofillValue value) {
- if (value == null) return "null";
-
- StringBuilder builder = new StringBuilder(value.toString()).append('(');
- if (value.isText()) {
- builder.append("isText");
- } else if (value.isDate()) {
- builder.append("isDate");
- } else if (value.isToggle()) {
- builder.append("isToggle");
- } else if (value.isList()) {
- builder.append("isList");
- }
- return builder.append(')').toString();
- }
-
- public static void dumpStructure(AssistStructure structure) {
- int nodeCount = structure.getWindowNodeCount();
- Log.v(TAG, "dumpStructure(): component=" + structure.getActivityComponent()
- + " numberNodes=" + nodeCount);
- for (int i = 0; i < nodeCount; i++) {
- Log.v(TAG, "node #" + i);
- WindowNode node = structure.getWindowNodeAt(i);
- dumpNode(" ", node.getRootViewNode());
- }
- }
-
- private static void dumpNode(String prefix, ViewNode node) {
- StringBuilder builder = new StringBuilder();
- builder.append(prefix)
- .append("autoFillId: ").append(node.getAutofillId())
- .append("\tidEntry: ").append(node.getIdEntry())
- .append("\tid: ").append(node.getId())
- .append("\tclassName: ").append(node.getClassName())
- .append('\n');
-
- builder.append(prefix)
- .append("focused: ").append(node.isFocused())
- .append("\tvisibility").append(node.getVisibility())
- .append("\tchecked: ").append(node.isChecked())
- .append("\twebDomain: ").append(node.getWebDomain())
- .append("\thint: ").append(node.getHint())
- .append('\n');
-
- HtmlInfo htmlInfo = node.getHtmlInfo();
-
- if (htmlInfo != null) {
- builder.append(prefix)
- .append("HTML TAG: ").append(htmlInfo.getTag())
- .append(" attrs: ").append(htmlInfo.getAttributes())
- .append('\n');
- }
-
- String[] afHints = node.getAutofillHints();
- CharSequence[] options = node.getAutofillOptions();
- builder.append(prefix).append("afType: ").append(getTypeAsString(node.getAutofillType()))
- .append("\tafValue:")
- .append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
- .append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
- .append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
- .append("\tinputType:").append(node.getInputType())
- .append('\n');
-
- int numberChildren = node.getChildCount();
- builder.append(prefix).append("# children: ").append(numberChildren)
- .append("\ttext: ").append(node.getText())
- .append('\n');
-
- Log.v(TAG, builder.toString());
- final String prefix2 = prefix + " ";
- for (int i = 0; i < numberChildren; i++) {
- Log.v(TAG, prefix + "child #" + i);
- dumpNode(prefix2, node.getChildAt(i));
- }
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/FakeFieldGenerator.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/FakeFieldGenerator.java
index 475b9d0..8d0754a 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/FakeFieldGenerator.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/FakeFieldGenerator.java
@@ -18,5 +18,5 @@
import com.example.android.autofill.service.model.FilledAutofillField;
interface FakeFieldGenerator {
- FilledAutofillField generate(int seed);
+ FilledAutofillField generate(int seed, String datasetId);
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
index bec5fff..e9cdd6c 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/MyAutofillService.java
@@ -16,8 +16,9 @@
package com.example.android.autofill.service;
import android.app.assist.AssistStructure;
+import android.content.Context;
import android.content.IntentSender;
-import android.os.Bundle;
+import android.content.SharedPreferences;
import android.os.CancellationSignal;
import android.service.autofill.AutofillService;
import android.service.autofill.FillCallback;
@@ -26,118 +27,256 @@
import android.service.autofill.FillResponse;
import android.service.autofill.SaveCallback;
import android.service.autofill.SaveRequest;
-import android.util.Log;
-import android.view.autofill.AutofillId;
+import android.support.annotation.NonNull;
+import android.view.autofill.AutofillManager;
import android.widget.RemoteViews;
-import com.example.android.autofill.service.datasource.SharedPrefsAutofillRepository;
-import com.example.android.autofill.service.datasource.SharedPrefsPackageVerificationRepository;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+import com.example.android.autofill.service.data.AutofillDataBuilder;
+import com.example.android.autofill.service.data.ClientAutofillDataBuilder;
+import com.example.android.autofill.service.data.ClientViewMetadata;
+import com.example.android.autofill.service.data.ClientViewMetadataBuilder;
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.data.adapter.DatasetAdapter;
+import com.example.android.autofill.service.data.adapter.ResponseAdapter;
+import com.example.android.autofill.service.data.source.DefaultFieldTypesSource;
+import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
+import com.example.android.autofill.service.data.source.local.DefaultFieldTypesLocalJsonSource;
+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.model.FieldTypeWithHeuristics;
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 com.google.gson.GsonBuilder;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
-import static com.example.android.autofill.service.CommonUtil.TAG;
-import static com.example.android.autofill.service.CommonUtil.VERBOSE;
-import static com.example.android.autofill.service.CommonUtil.bundleToString;
-import static com.example.android.autofill.service.CommonUtil.dumpStructure;
+import static com.example.android.autofill.service.util.Util.DalCheckRequirement;
+import static com.example.android.autofill.service.util.Util.bundleToString;
+import static com.example.android.autofill.service.util.Util.dumpStructure;
+import static com.example.android.autofill.service.util.Util.logVerboseEnabled;
+import static com.example.android.autofill.service.util.Util.logd;
+import static com.example.android.autofill.service.util.Util.loge;
+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.toList;
public class MyAutofillService extends AutofillService {
- @Override
- public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal,
- FillCallback callback) {
- AssistStructure structure = request.getFillContexts()
- .get(request.getFillContexts().size() - 1).getStructure();
- String packageName = structure.getActivityComponent().getPackageName();
- if (!SharedPrefsPackageVerificationRepository.getInstance()
- .putPackageSignatures(getApplicationContext(), packageName)) {
- callback.onFailure(
- getApplicationContext().getString(R.string.invalid_package_signature));
- return;
- }
- final Bundle data = request.getClientState();
- if (VERBOSE) {
- Log.v(TAG, "onFillRequest(): data=" + bundleToString(data));
- dumpStructure(structure);
- }
+ private LocalAutofillDataSource mLocalAutofillDataSource;
+ private DigitalAssetLinksRepository mDalRepository;
+ private PackageVerificationDataSource mPackageVerificationRepository;
+ private AutofillDataBuilder mAutofillDataBuilder;
+ private ResponseAdapter mResponseAdapter;
+ private ClientViewMetadata mClientViewMetadata;
+ private MyPreferences mPreferences;
- cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
- @Override
- public void onCancel() {
- Log.w(TAG, "Cancel autofill not implemented in this sample.");
- }
- });
- // Parse AutoFill data in Activity
- StructureParser parser = new StructureParser(getApplicationContext(), structure);
- // 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.
- Log.w(TAG, "Security exception handling " + request, e);
- callback.onFailure(e.getMessage());
- return;
- }
- AutofillFieldMetadataCollection autofillFields = parser.getAutofillFields();
- FillResponse.Builder responseBuilder = new FillResponse.Builder();
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mPreferences = MyPreferences.getInstance(this);
+ Util.setLoggingLevel(mPreferences.getLoggingLevel());
+ SharedPreferences localAfDataSourceSharedPrefs =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ DefaultFieldTypesSource defaultFieldTypesSource =
+ DefaultFieldTypesLocalJsonSource.getInstance(getResources(),
+ new GsonBuilder().create());
+ AutofillDao autofillDao = AutofillDatabase.getInstance(this,
+ defaultFieldTypesSource, new AppExecutors()).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) {
+ List<FillContext> fillContexts = request.getFillContexts();
+ List<AssistStructure> structures =
+ fillContexts.stream().map(FillContext::getStructure).collect(toList());
+ AssistStructure latestStructure = fillContexts.get(fillContexts.size() - 1).getStructure();
+ ClientParser parser = new ClientParser(structures);
+
// 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()) {
+ boolean responseAuth = mPreferences.isResponseAuth();
+ boolean datasetAuth = mPreferences.isDatasetAuth();
+ boolean manual = (request.getFlags() & FillRequest.FLAG_MANUAL_REQUEST) != 0;
+ mLocalAutofillDataSource.getFieldTypeByAutofillHints(
+ new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
+ @Override
+ public void onLoaded(HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
+ DatasetAdapter datasetAdapter = new DatasetAdapter(parser);
+ ClientViewMetadataBuilder clientViewMetadataBuilder =
+ new ClientViewMetadataBuilder(parser, fieldTypesByAutofillHint);
+ mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
+ mResponseAdapter = new ResponseAdapter(MyAutofillService.this,
+ mClientViewMetadata, getPackageName(), datasetAdapter);
+ String packageName = latestStructure.getActivityComponent().getPackageName();
+ if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
+ callback.onFailure(getString(R.string.invalid_package_signature));
+ return;
+ }
+ if (logVerboseEnabled()) {
+ logv("onFillRequest(): clientState=%s",
+ bundleToString(request.getClientState()));
+ dumpStructure(latestStructure);
+ }
+ cancellationSignal.setOnCancelListener(() ->
+ logw("Cancel autofill not implemented in this sample.")
+ );
+ fetchDataAndGenerateResponse(fieldTypesByAutofillHint, responseAuth,
+ datasetAuth, manual, callback);
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+
+ }
+ });
+ }
+
+ private void fetchDataAndGenerateResponse(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint, boolean responseAuth,
+ boolean datasetAuth, boolean manual, FillCallback callback) {
+ 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();
- HashMap<String, FilledAutofillFieldCollection> clientFormDataMap =
- SharedPrefsAutofillRepository.getInstance().getFilledAutofillFieldCollection(
- this, autofillFields.getFocusedHints(), autofillFields.getAllHints());
- FillResponse response = AutofillHelper.newResponse
- (this, datasetAuth, autofillFields, clientFormDataMap);
- callback.onSuccess(response);
+ mLocalAutofillDataSource.getAutofillDatasets(mClientViewMetadata.getAllHints(),
+ new DataCallback<List<DatasetWithFilledAutofillFields>>() {
+ @Override
+ public void onLoaded(List<DatasetWithFilledAutofillFields> datasets) {
+ if ((datasets == null || datasets.isEmpty()) && manual) {
+ IntentSender sender = ManualActivity
+ .getManualIntentSenderForResponse(MyAutofillService.this);
+ RemoteViews remoteViews = RemoteViewsHelper.viewsWithNoAuth(
+ getPackageName(),
+ getString(R.string.autofill_manual_prompt));
+ FillResponse response = mResponseAdapter.buildManualResponse(sender,
+ remoteViews);
+ if (response != null) {
+ callback.onSuccess(response);
+ }
+ } else {
+ FillResponse response = mResponseAdapter.buildResponse(
+ fieldTypesByAutofillHint, datasets, datasetAuth);
+ callback.onSuccess(response);
+ }
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ callback.onFailure(String.format(msg, params));
+ }
+ });
}
}
@Override
- public void onSaveRequest(SaveRequest request, SaveCallback callback) {
- List<FillContext> context = request.getFillContexts();
- final AssistStructure structure = context.get(context.size() - 1).getStructure();
- String packageName = structure.getActivityComponent().getPackageName();
- if (!SharedPrefsPackageVerificationRepository.getInstance()
- .putPackageSignatures(getApplicationContext(), packageName)) {
- callback.onFailure(
- getApplicationContext().getString(R.string.invalid_package_signature));
+ public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
+ List<FillContext> fillContexts = request.getFillContexts();
+ List<AssistStructure> structures =
+ fillContexts.stream().map(FillContext::getStructure).collect(toList());
+ AssistStructure latestStructure = fillContexts.get(fillContexts.size() - 1).getStructure();
+ ClientParser parser = new ClientParser(structures);
+ mLocalAutofillDataSource.getFieldTypeByAutofillHints(
+ new DataCallback<HashMap<String, FieldTypeWithHeuristics>>() {
+ @Override
+ public void onLoaded(
+ HashMap<String, FieldTypeWithHeuristics> fieldTypesByAutofillHint) {
+ mAutofillDataBuilder = new ClientAutofillDataBuilder(
+ fieldTypesByAutofillHint, getPackageName(), parser);
+ ClientViewMetadataBuilder clientViewMetadataBuilder =
+ new ClientViewMetadataBuilder(parser, fieldTypesByAutofillHint);
+ mClientViewMetadata = clientViewMetadataBuilder.buildClientViewMetadata();
+ String packageName = latestStructure.getActivityComponent().getPackageName();
+ if (!mPackageVerificationRepository.putPackageSignatures(packageName)) {
+ callback.onFailure(getString(R.string.invalid_package_signature));
+ return;
+ }
+ if (logVerboseEnabled()) {
+ logv("onSaveRequest(): clientState=%s",
+ bundleToString(request.getClientState()));
+ }
+ dumpStructure(latestStructure);
+ checkWebDomainAndBuildAutofillData(packageName, callback);
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ loge("Should not happen - could not find field types.");
+ }
+ });
+ }
+
+ private void checkWebDomainAndBuildAutofillData(String packageName, SaveCallback callback) {
+ String webDomain;
+ try {
+ webDomain = mClientViewMetadata.getWebDomain();
+ } catch (SecurityException e) {
+ logw(e.getMessage());
+ callback.onFailure(getString(R.string.security_exception));
return;
}
- final Bundle data = request.getClientState();
- if (VERBOSE) {
- Log.v(TAG, "onSaveRequest(): data=" + bundleToString(data));
- dumpStructure(structure);
+ if (webDomain != null && webDomain.length() > 0) {
+ DalCheckRequirement req = mPreferences.getDalCheckRequirement();
+ mDalRepository.checkValid(req, 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 {
+ loge("Could not associate web domain %s with app %s",
+ webDomain, packageName);
+ callback.onFailure(getString(R.string.dal_exception));
+ }
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+ logw(msg, params);
+ callback.onFailure(getString(R.string.dal_exception));
+ }
+ });
+ } else {
+ logd("no web domain");
+ buildAndSaveAutofillData();
}
- StructureParser parser = new StructureParser(getApplicationContext(), structure);
- parser.parseForSave();
- FilledAutofillFieldCollection filledAutofillFieldCollection = parser.getClientFormData();
- SharedPrefsAutofillRepository.getInstance()
- .saveFilledAutofillFieldCollection(this, filledAutofillFieldCollection);
+ }
+
+ private void buildAndSaveAutofillData() {
+ int datasetNumber = mLocalAutofillDataSource.getDatasetNumber();
+ List<DatasetWithFilledAutofillFields> datasetsWithFilledAutofillFields =
+ mAutofillDataBuilder.buildDatasetsByPartition(datasetNumber);
+ mLocalAutofillDataSource.saveAutofillDatasets(datasetsWithFilledAutofillFields);
}
@Override
public void onConnected() {
- Log.d(TAG, "onConnected");
+ logd("onConnected");
}
@Override
public void onDisconnected() {
- Log.d(TAG, "onDisconnected");
+ logd("onDisconnected");
}
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java
deleted file mode 100644
index 5ab23ac..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/SecurityHelper.java
+++ /dev/null
@@ -1,199 +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.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.os.AsyncTask;
-import android.util.Log;
-
-import com.google.common.net.InternetDomainName;
-
-import org.json.JSONObject;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.security.MessageDigest;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
-import static com.example.android.autofill.service.CommonUtil.DEBUG;
-import static com.example.android.autofill.service.CommonUtil.TAG;
-import static com.example.android.autofill.service.CommonUtil.VERBOSE;
-
-/**
- * Helper class for security checks.
- */
-public final class SecurityHelper {
-
- private static final String REST_TEMPLATE =
- "https://digitalassetlinks.googleapis.com/v1/assetlinks:check?"
- + "source.web.site=%s&relation=delegate_permission/%s"
- + "&target.android_app.package_name=%s"
- + "&target.android_app.certificate.sha256_fingerprint=%s";
-
- 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 SecurityHelper() {
- throw new UnsupportedOperationException("provides static methods only");
- }
-
- private static boolean isValidSync(String webDomain, String permission, String packageName,
- String fingerprint) {
- if (DEBUG) Log.d(TAG, "validating domain " + webDomain + " for pkg " + packageName
- + " and fingerprint " + fingerprint + " for permission" + permission);
- if (!webDomain.startsWith("http:") && !webDomain.startsWith("https:")) {
- // Unfortunately AssistStructure.ViewNode does not tell what the domain is, so let's
- // assume it's https
- webDomain = "https://" + webDomain;
- }
-
- String restUrl =
- String.format(REST_TEMPLATE, webDomain, permission, packageName, fingerprint);
- if (DEBUG) Log.d(TAG, "DAL REST request: " + restUrl);
-
- HttpURLConnection urlConnection = null;
- StringBuilder output = new StringBuilder();
- try {
- URL url = new URL(restUrl);
- urlConnection = (HttpURLConnection) url.openConnection();
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(urlConnection.getInputStream()))) {
- String line = null;
- while ((line = reader.readLine()) != null) {
- output.append(line);
- }
- }
- String response = output.toString();
- if (VERBOSE) Log.v(TAG, "DAL REST Response: " + response);
-
- JSONObject jsonObject = new JSONObject(response);
- boolean valid = jsonObject.optBoolean("linked", false);
- if (DEBUG) Log.d(TAG, "Valid: " + valid);
-
- return valid;
- } catch (Exception e) {
- throw new RuntimeException("Failed to validate", e);
- } finally {
- if (urlConnection != null) {
- urlConnection.disconnect();
- }
- }
-
- }
-
- private static boolean isValidSync(String webDomain, String packageName, String fingerprint) {
- boolean isValid =
- isValidSync(webDomain, PERMISSION_GET_LOGIN_CREDS, packageName, fingerprint);
- if (!isValid) {
- // Ideally we should only check for the get_login_creds, but not all domains set
- // it yet, so validating for handle_all_urls gives a higher coverage.
- if (DEBUG) {
- Log.d(TAG, PERMISSION_GET_LOGIN_CREDS + " validation failed; trying "
- + PERMISSION_HANDLE_ALL_URLS);
- }
- isValid = isValidSync(webDomain, PERMISSION_HANDLE_ALL_URLS, packageName, fingerprint);
- }
- return isValid;
- }
-
- public static String getCanonicalDomain(String domain) {
- InternetDomainName idn = InternetDomainName.from(domain);
- while (idn != null && !idn.isTopPrivateDomain()) {
- idn = idn.parent();
- }
- return idn == null ? null : idn.toString();
- }
-
- public static boolean isValid(String webDomain, String packageName, String fingerprint) {
- String canonicalDomain = getCanonicalDomain(webDomain);
- if (DEBUG) Log.d(TAG, "validating domain " + canonicalDomain + " (" + webDomain
- + ") for pkg " + packageName + " and fingerprint " + fingerprint);
- final String fullDomain;
- if (!webDomain.startsWith("http:") && !webDomain.startsWith("https:")) {
- // Unfortunately AssistStructure.ViewNode does not tell what the domain is, so let's
- // assume it's https
- fullDomain = "https://" + canonicalDomain;
- } else {
- fullDomain = canonicalDomain;
- }
-
- // TODO: use the DAL Java API or a better REST alternative like Volley
- // and/or document it should not block until it returns (for example, the server could
- // start parsing the structure while it waits for the result.
- AsyncTask<String, Integer, Boolean> task = new AsyncTask<String, Integer, Boolean>() {
- @Override
- protected Boolean doInBackground(String... strings) {
- return isValidSync(fullDomain, packageName, fingerprint);
- }
- };
- try {
- return task.execute((String[]) null).get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- Log.w(TAG, "Thread interrupted");
- } catch (Exception e) {
- Log.w(TAG, "Async task failed", e);
- }
- return false;
- }
-
- /**
- * Gets the fingerprint of the signed certificate of a package.
- */
- public static String getFingerprint(Context context, String packageName) throws Exception {
- PackageManager pm = context.getPackageManager();
- PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
- Signature[] signatures = packageInfo.signatures;
- if (signatures.length != 1) {
- throw new SecurityException(packageName + " has " + signatures.length + " signatures");
- }
- byte[] cert = signatures[0].toByteArray();
- try (InputStream input = new ByteArrayInputStream(cert)) {
- CertificateFactory factory = CertificateFactory.getInstance("X509");
- X509Certificate x509 = (X509Certificate) factory.generateCertificate(input);
- MessageDigest md = MessageDigest.getInstance("SHA256");
- byte[] publicKey = md.digest(x509.getEncoded());
- return toHexFormat(publicKey);
- }
- }
-
- private static String toHexFormat(byte[] bytes) {
- StringBuilder builder = new StringBuilder(bytes.length * 2);
- for (int i = 0; i < bytes.length; i++) {
- String hex = Integer.toHexString(bytes[i]);
- int length = hex.length();
- if (length == 1) {
- hex = "0" + hex;
- }
- if (length > 2) {
- hex = hex.substring(length - 2, length);
- }
- builder.append(hex.toUpperCase());
- if (i < (bytes.length - 1)) {
- builder.append(':');
- }
- }
- return builder.toString();
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java
deleted file mode 100644
index ce020a7..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/StructureParser.java
+++ /dev/null
@@ -1,137 +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;
-import android.app.assist.AssistStructure.ViewNode;
-import android.app.assist.AssistStructure.WindowNode;
-import android.content.Context;
-import android.util.Log;
-import android.view.autofill.AutofillValue;
-
-import com.example.android.autofill.service.datasource.SharedPrefsDigitalAssetLinksRepository;
-import com.example.android.autofill.service.model.FilledAutofillField;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-
-import static com.example.android.autofill.service.CommonUtil.DEBUG;
-import static com.example.android.autofill.service.CommonUtil.TAG;
-
-/**
- * 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.
- */
-final class StructureParser {
- private final AutofillFieldMetadataCollection mAutofillFields =
- new AutofillFieldMetadataCollection();
- private final Context mContext;
- private final AssistStructure mStructure;
- private FilledAutofillFieldCollection mFilledAutofillFieldCollection;
-
- StructureParser(Context context, AssistStructure structure) {
- mContext = context;
- mStructure = structure;
- }
-
- public void parseForFill() {
- parse(true);
- }
-
- public void parseForSave() {
- parse(false);
- }
-
- /**
- * Traverse AssistStructure and add ViewNode metadata to a flat list.
- */
- private void parse(boolean forFill) {
- if (DEBUG) Log.d(TAG, "Parsing structure for " + mStructure.getActivityComponent());
- int nodes = mStructure.getWindowNodeCount();
- mFilledAutofillFieldCollection = new FilledAutofillFieldCollection();
- 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();
- boolean valid = SharedPrefsDigitalAssetLinksRepository.getInstance().isValid(mContext,
- webDomain.toString(), packageName);
- if (!valid) {
- throw new SecurityException(mContext.getString(
- R.string.invalid_link_association, webDomain, packageName));
- }
- if (DEBUG) Log.d(TAG, "Domain " + webDomain + " is valid for " + packageName);
- } else {
- if (DEBUG) Log.d(TAG, "no web domain");
- }
- }
-
- private void parseLocked(boolean forFill, ViewNode viewNode, StringBuilder validWebDomain) {
- String webDomain = viewNode.getWebDomain();
- if (webDomain != null) {
- if (DEBUG) Log.d(TAG, "child web domain: " + 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 {
- FilledAutofillField filledAutofillField =
- new FilledAutofillField(viewNode.getAutofillHints());
- AutofillValue autofillValue = viewNode.getAutofillValue();
- if (autofillValue.isText()) {
- // Using toString of AutofillValue.getTextValue in order to save it to
- // SharedPreferences.
- filledAutofillField.setTextValue(autofillValue.getTextValue().toString());
- } else if (autofillValue.isDate()) {
- filledAutofillField.setDateValue(autofillValue.getDateValue());
- } else if (autofillValue.isList()) {
- filledAutofillField.setListValue(viewNode.getAutofillOptions(),
- autofillValue.getListValue());
- }
- mFilledAutofillFieldCollection.add(filledAutofillField);
- }
- }
- }
- int childrenSize = viewNode.getChildCount();
- if (childrenSize > 0) {
- for (int i = 0; i < childrenSize; i++) {
- parseLocked(forFill, viewNode.getChildAt(i), validWebDomain);
- }
- }
- }
-
- public AutofillFieldMetadataCollection getAutofillFields() {
- return mAutofillFields;
- }
-
- public FilledAutofillFieldCollection getClientFormData() {
- return mFilledAutofillFieldCollection;
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/W3cHints.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/W3cHints.java
index 1721477..fd8e945 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/W3cHints.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/W3cHints.java
@@ -16,50 +16,6 @@
package com.example.android.autofill.service;
public final class W3cHints {
-
- // Supported W3C autofill tokens (https://html.spec.whatwg.org/multipage/forms.html#autofill)
- public static final String HONORIFIC_PREFIX = "honorific-prefix";
- public static final String NAME = "name";
- public static final String GIVEN_NAME = "given-name";
- public static final String ADDITIONAL_NAME = "additional-name";
- public static final String FAMILY_NAME = "family-name";
- public static final String HONORIFIC_SUFFIX = "honorific-suffix";
- public static final String USERNAME = "username";
- public static final String NEW_PASSWORD = "new-password";
- public static final String CURRENT_PASSWORD = "current-password";
- public static final String ORGANIZATION_TITLE = "organization-title";
- public static final String ORGANIZATION = "organization";
- public static final String STREET_ADDRESS = "street-address";
- public static final String ADDRESS_LINE1 = "address-line1";
- public static final String ADDRESS_LINE2 = "address-line2";
- public static final String ADDRESS_LINE3 = "address-line3";
- public static final String ADDRESS_LEVEL4 = "address-level4";
- public static final String ADDRESS_LEVEL3 = "address-level3";
- public static final String ADDRESS_LEVEL2 = "address-level2";
- public static final String ADDRESS_LEVEL1 = "address-level1";
- public static final String COUNTRY = "country";
- public static final String COUNTRY_NAME = "country-name";
- public static final String POSTAL_CODE = "postal-code";
- public static final String CC_NAME = "cc-name";
- public static final String CC_GIVEN_NAME = "cc-given-name";
- public static final String CC_ADDITIONAL_NAME = "cc-additional-name";
- public static final String CC_FAMILY_NAME = "cc-family-name";
- public static final String CC_NUMBER = "cc-number";
- public static final String CC_EXPIRATION = "cc-exp";
- public static final String CC_EXPIRATION_MONTH = "cc-exp-month";
- public static final String CC_EXPIRATION_YEAR = "cc-exp-year";
- public static final String CC_CSC = "cc-csc";
- public static final String CC_TYPE = "cc-type";
- public static final String TRANSACTION_CURRENCY = "transaction-currency";
- public static final String TRANSACTION_AMOUNT = "transaction-amount";
- public static final String LANGUAGE = "language";
- public static final String BDAY = "bday";
- public static final String BDAY_DAY = "bday-day";
- public static final String BDAY_MONTH = "bday-month";
- public static final String BDAY_YEAR = "bday-year";
- public static final String SEX = "sex";
- public static final String URL = "url";
- public static final String PHOTO = "photo";
// Optional W3C prefixes
public static final String PREFIX_SECTION = "section-";
public static final String SHIPPING = "shipping";
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java
deleted file mode 100644
index 38e7007..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/AutofillDataSource.java
+++ /dev/null
@@ -1,44 +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 android.content.Context;
-
-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}.
- */
- HashMap<String, FilledAutofillFieldCollection> getFilledAutofillFieldCollection(Context context,
- List<String> focusedAutofillHints, List<String> allAutofillHints);
-
- /**
- * Stores a collection of Autofill fields.
- */
- void saveFilledAutofillFieldCollection(Context context,
- FilledAutofillFieldCollection filledAutofillFieldCollection);
-
- /**
- * Clears all data.
- */
- void clear(Context context);
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java
deleted file mode 100644
index 040ab50..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/DigitalAssetLinksDataSource.java
+++ /dev/null
@@ -1,35 +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 android.content.Context;
-
-/**
- * Helper format
- * <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a> needs.
- */
-public interface DigitalAssetLinksDataSource {
-
- /**
- * Checks if the association between a web domain and a package is valid.
- */
- boolean isValid(Context context, String webDomain, String packageName);
-
- /**
- * Clears all cached data.
- */
- void clear(Context context);
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java
deleted file mode 100644
index ed1d1ce..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/PackageVerificationDataSource.java
+++ /dev/null
@@ -1,38 +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 android.content.Context;
-
-public interface PackageVerificationDataSource {
-
- /**
- * Verifies that the signatures in the passed {@code Context} match what is currently in
- * storage. If there are no current signatures in storage for this packageName, it will store
- * the signatures from the passed {@code Context}.
- *
- * @return {@code true} if signatures for this packageName are not currently in storage
- * or if the signatures in the passed {@code Context} match what is currently in storage;
- * {@code false} if the signatures in the passed {@code Context} do not match what is
- * currently in storage or if an {@code Exception} was thrown while generating the signatures.
- */
- boolean putPackageSignatures(Context context, String packageName);
-
- /**
- * Clears all signature data currently in storage.
- */
- void clear(Context context);
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsAutofillRepository.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsAutofillRepository.java
deleted file mode 100644
index 0643a3f..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsAutofillRepository.java
+++ /dev/null
@@ -1,141 +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 android.content.Context;
-import android.util.ArraySet;
-
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Singleton autofill data repository that stores autofill fields to SharedPreferences.
- *
- * <p><b>Disclaimer</b>: you should not store sensitive fields like user data unencrypted.
- * This is done here only for simplicity and learning purposes.
- */
-public class SharedPrefsAutofillRepository implements AutofillDataSource {
- private static final String SHARED_PREF_KEY = "com.example.android.autofill"
- + ".service.datasource.AutofillDataSource";
- private static final String CLIENT_FORM_DATA_KEY = "loginCredentialDatasets";
- private static final String DATASET_NUMBER_KEY = "datasetNumber";
- private static SharedPrefsAutofillRepository sInstance;
-
- private SharedPrefsAutofillRepository() {
- }
-
- public static SharedPrefsAutofillRepository getInstance() {
- if (sInstance == null) {
- sInstance = new SharedPrefsAutofillRepository();
- }
- return sInstance;
- }
-
- @Override
- public HashMap<String, FilledAutofillFieldCollection> getFilledAutofillFieldCollection(
- Context context, List<String> focusedAutofillHints, List<String> allAutofillHints) {
- boolean hasDataForFocusedAutofillHints = false;
- HashMap<String, FilledAutofillFieldCollection> clientFormDataMap = new HashMap<>();
- Set<String> clientFormDataStringSet = getAllAutofillDataStringSet(context);
- for (String clientFormDataString : clientFormDataStringSet) {
- Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- gson.fromJson(clientFormDataString, FilledAutofillFieldCollection.class);
- if (filledAutofillFieldCollection != null) {
- if (filledAutofillFieldCollection.helpsWithHints(focusedAutofillHints)) {
- // Saved data has data relevant to at least 1 of the hints associated with the
- // View in focus.
- hasDataForFocusedAutofillHints = true;
- }
- if (filledAutofillFieldCollection.helpsWithHints(allAutofillHints)) {
- // Saved data has data relevant to at least 1 of these hints associated with any
- // of the Views in the hierarchy.
- clientFormDataMap.put(filledAutofillFieldCollection.getDatasetName(),
- filledAutofillFieldCollection);
- }
- }
- }
- if (hasDataForFocusedAutofillHints) {
- return clientFormDataMap;
- } else {
- return null;
- }
- }
-
- @Override
- public void saveFilledAutofillFieldCollection(Context context,
- FilledAutofillFieldCollection filledAutofillFieldCollection) {
- String datasetName = "dataset-" + getDatasetNumber(context);
- filledAutofillFieldCollection.setDatasetName(datasetName);
- Set<String> allAutofillData = getAllAutofillDataStringSet(context);
- Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
- allAutofillData.add(gson.toJson(filledAutofillFieldCollection));
- saveAllAutofillDataStringSet(context, allAutofillData);
- incrementDatasetNumber(context);
- }
-
- @Override
- public void clear(Context context) {
- context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .edit()
- .remove(CLIENT_FORM_DATA_KEY)
- .remove(DATASET_NUMBER_KEY)
- .apply();
- }
-
- private Set<String> getAllAutofillDataStringSet(Context context) {
- return context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .getStringSet(CLIENT_FORM_DATA_KEY, new ArraySet<String>());
- }
-
- private void saveAllAutofillDataStringSet(Context context,
- Set<String> allAutofillDataStringSet) {
- context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .edit()
- .putStringSet(CLIENT_FORM_DATA_KEY, allAutofillDataStringSet)
- .apply();
- }
-
- /**
- * For simplicity, datasets will be named in the form "dataset-X" where X means
- * this was the Xth dataset saved.
- */
- private int getDatasetNumber(Context context) {
- return context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .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(Context context) {
- context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .edit()
- .putInt(DATASET_NUMBER_KEY, getDatasetNumber(context) + 1)
- .apply();
- }
-}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsDigitalAssetLinksRepository.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsDigitalAssetLinksRepository.java
deleted file mode 100644
index 476cf4c..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsDigitalAssetLinksRepository.java
+++ /dev/null
@@ -1,63 +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 android.content.Context;
-import android.util.Log;
-
-import com.example.android.autofill.service.SecurityHelper;
-
-import static com.example.android.autofill.service.CommonUtil.TAG;
-
-/**
- * Singleton repository that caches the result of Digital Asset Links checks.
- */
-public class SharedPrefsDigitalAssetLinksRepository implements DigitalAssetLinksDataSource {
-
- private static SharedPrefsDigitalAssetLinksRepository sInstance;
-
- private SharedPrefsDigitalAssetLinksRepository() {
- }
-
- public static SharedPrefsDigitalAssetLinksRepository getInstance() {
- if (sInstance == null) {
- sInstance = new SharedPrefsDigitalAssetLinksRepository();
- }
- return sInstance;
- }
-
- @Override
- public boolean isValid(Context context, String webDomain, String packageName) {
- // TODO: implement caching. It could cache the whole domain -> (packagename, fingerprint),
- // but then either invalidate when the package change or when the DAL association times out
- // (the maxAge is part of the API response), or document that a real-life service
- // should do that.
-
- String fingerprint = null;
- try {
- fingerprint = SecurityHelper.getFingerprint(context, packageName);
- } catch (Exception e) {
- Log.w(TAG, "error getting fingerprint for " + packageName, e);
- return false;
- }
- return SecurityHelper.isValid(webDomain, packageName, fingerprint);
- }
-
- @Override
- public void clear(Context context) {
- // TODO: implement once if caches results or remove from the interface
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsPackageVerificationRepository.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsPackageVerificationRepository.java
deleted file mode 100644
index a0aaeab..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/datasource/SharedPrefsPackageVerificationRepository.java
+++ /dev/null
@@ -1,85 +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 android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import com.example.android.autofill.service.SecurityHelper;
-
-import static com.example.android.autofill.service.CommonUtil.TAG;
-
-public class SharedPrefsPackageVerificationRepository implements PackageVerificationDataSource {
-
- private static final String SHARED_PREF_KEY = "com.example.android.autofill.service"
- + ".datasource.PackageVerificationDataSource";
- private static PackageVerificationDataSource sInstance;
-
- private SharedPrefsPackageVerificationRepository() {
- }
-
- public static PackageVerificationDataSource getInstance() {
- if (sInstance == null) {
- sInstance = new SharedPrefsPackageVerificationRepository();
- }
- return sInstance;
- }
-
- @Override
- public void clear(Context context) {
- context.getApplicationContext().getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .edit()
- .clear()
- .apply();
- }
-
- @Override
- public boolean putPackageSignatures(Context context, String packageName) {
- String hash;
- try {
- hash = SecurityHelper.getFingerprint(context, packageName);
- Log.d(TAG, "Hash for " + packageName + ": " + hash);
- } catch (Exception e) {
- Log.w(TAG, "Error getting hash for " + packageName + ": " + e);
- return false;
- }
-
- if (!containsSignatureForPackage(context, packageName)) {
- // Storage does not yet contain signature for this package name.
- context.getApplicationContext()
- .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE)
- .edit()
- .putString(packageName, hash)
- .apply();
- return true;
- }
- return containsMatchingSignatureForPackage(context, packageName, hash);
- }
-
- private boolean containsSignatureForPackage(Context context, String packageName) {
- SharedPreferences prefs = context.getApplicationContext().getSharedPreferences(
- SHARED_PREF_KEY, Context.MODE_PRIVATE);
- return prefs.contains(packageName);
- }
-
- private boolean containsMatchingSignatureForPackage(Context context, String packageName,
- String hash) {
- SharedPreferences prefs = context.getApplicationContext().getSharedPreferences(
- SHARED_PREF_KEY, Context.MODE_PRIVATE);
- return hash.equals(prefs.getString(packageName, null));
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
index 0262401..85ad05a 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillField.java
@@ -15,96 +15,104 @@
*/
package com.example.android.autofill.service.model;
-import android.util.Log;
-import android.view.View;
+import android.arch.persistence.room.ColumnInfo;
+import android.arch.persistence.room.Entity;
+import android.arch.persistence.room.ForeignKey;
+import android.arch.persistence.room.Ignore;
+import android.support.annotation.NonNull;
-import com.example.android.autofill.service.AutofillHints;
-import com.google.common.base.Preconditions;
-import com.google.gson.annotations.Expose;
+import javax.annotation.Nullable;
-import java.util.Arrays;
-
-import static com.example.android.autofill.service.CommonUtil.TAG;
-import static com.example.android.autofill.service.AutofillHints.convertToStoredHintNames;
-import static com.example.android.autofill.service.AutofillHints.filterForSupportedHints;
-
-/**
- * JSON serializable data class containing the same data as an {@link AutofillValue}.
- */
+@Entity(primaryKeys = {"datasetId", "fieldTypeName"}, foreignKeys = {
+ @ForeignKey(entity = AutofillDataset.class, parentColumns = "id",
+ childColumns = "datasetId", onDelete = ForeignKey.CASCADE),
+ @ForeignKey(entity = FieldType.class, parentColumns = "typeName",
+ childColumns = "fieldTypeName", onDelete = ForeignKey.CASCADE)
+})
public class FilledAutofillField {
- @Expose
- private String mTextValue = null;
- @Expose
- private Long mDateValue = null;
- @Expose
- private Boolean mToggleValue = null;
- //TODO add explicit mListValue
+ @NonNull
+ @ColumnInfo(name = "datasetId")
+ private final String mDatasetId;
- /**
- * Does not need to be serialized into persistent storage, so it's not exposed.
- */
- private String[] mAutofillHints = null;
+ @Nullable
+ @ColumnInfo(name = "textValue")
+ private final String mTextValue;
- public FilledAutofillField(String... hints) {
- mAutofillHints = filterForSupportedHints(hints);
- convertToStoredHintNames(mAutofillHints);
+ @Nullable
+ @ColumnInfo(name = "dateValue")
+ private final Long mDateValue;
+
+ @Nullable
+ @ColumnInfo(name = "toggleValue")
+ private final Boolean mToggleValue;
+
+ @NonNull
+ @ColumnInfo(name = "fieldTypeName")
+ private final String mFieldTypeName;
+
+ public FilledAutofillField(@NonNull String datasetId, @NonNull String fieldTypeName,
+ @Nullable String textValue, @Nullable Long dateValue,
+ @Nullable Boolean toggleValue) {
+ mDatasetId = datasetId;
+ mFieldTypeName = fieldTypeName;
+ mTextValue = textValue;
+ mDateValue = dateValue;
+ mToggleValue = toggleValue;
}
- public void setListValue(CharSequence[] autofillOptions, int listValue) {
- /* Only set list value when a hint is allowed to store list values. */
- Preconditions.checkArgument(
- AutofillHints.isValidTypeForHints(mAutofillHints, View.AUTOFILL_TYPE_LIST),
- "List is invalid autofill type for hint(s) - %s",
- Arrays.toString(mAutofillHints));
- if (autofillOptions != null && autofillOptions.length > 0) {
- mTextValue = autofillOptions[listValue].toString();
- } else {
- Log.w(TAG, "autofillOptions should have at least one entry.");
- }
+ @Ignore
+ public FilledAutofillField(@NonNull String datasetId,
+ @NonNull String fieldTypeName, @Nullable String textValue, @Nullable Long dateValue) {
+ this(datasetId, fieldTypeName, textValue, dateValue, null);
}
- public String[] getAutofillHints() {
- return mAutofillHints;
+ @Ignore
+ public FilledAutofillField(@NonNull String datasetId, @NonNull String fieldTypeName,
+ @Nullable String textValue) {
+ this(datasetId, fieldTypeName, textValue, null, null);
}
+ @Ignore
+ public FilledAutofillField(@NonNull String datasetId, @NonNull String fieldTypeName,
+ @Nullable Long dateValue) {
+ this(datasetId, fieldTypeName, null, dateValue, null);
+ }
+
+ @Ignore
+ public FilledAutofillField(@NonNull String datasetId, @NonNull String fieldTypeName,
+ @Nullable Boolean toggleValue) {
+ this(datasetId, fieldTypeName, null, null, toggleValue);
+ }
+
+ @Ignore
+ public FilledAutofillField(@NonNull String datasetId, @NonNull String fieldTypeName) {
+ this(datasetId, fieldTypeName, null, null, null);
+ }
+
+ @NonNull
+ public String getDatasetId() {
+ return mDatasetId;
+ }
+
+ @Nullable
public String getTextValue() {
return mTextValue;
}
- public void setTextValue(CharSequence textValue) {
- /* Only set text value when a hint is allowed to store text values. */
- Preconditions.checkArgument(
- AutofillHints.isValidTypeForHints(mAutofillHints, View.AUTOFILL_TYPE_TEXT),
- "Text is invalid autofill type for hint(s) - %s",
- Arrays.toString(mAutofillHints));
- mTextValue = textValue.toString();
- }
-
+ @Nullable
public Long getDateValue() {
return mDateValue;
}
- public void setDateValue(Long dateValue) {
- /* Only set date value when a hint is allowed to store date values. */
- Preconditions.checkArgument(
- AutofillHints.isValidTypeForHints(mAutofillHints, View.AUTOFILL_TYPE_DATE),
- "Date is invalid autofill type for hint(s) - %s"
- , Arrays.toString(mAutofillHints));
- mDateValue = dateValue;
- }
-
+ @Nullable
public Boolean getToggleValue() {
return mToggleValue;
}
- public void setToggleValue(Boolean toggleValue) {
- /* Only set toggle value when a hint is allowed to store toggle values. */
- Preconditions.checkArgument(
- AutofillHints.isValidTypeForHints(mAutofillHints, View.AUTOFILL_TYPE_TOGGLE),
- "Toggle is invalid autofill type for hint(s) - %s",
- Arrays.toString(mAutofillHints));
- mToggleValue = toggleValue;
+ @NonNull
+ public String getFieldTypeName() {
+ return mFieldTypeName;
}
public boolean isNull() {
@@ -122,8 +130,9 @@
return false;
if (mDateValue != null ? !mDateValue.equals(that.mDateValue) : that.mDateValue != null)
return false;
- return mToggleValue != null ? mToggleValue.equals(that.mToggleValue) :
- that.mToggleValue == null;
+ if (mToggleValue != null ? !mToggleValue.equals(that.mToggleValue) : that.mToggleValue != null)
+ return false;
+ return mFieldTypeName.equals(that.mFieldTypeName);
}
@Override
@@ -131,6 +140,7 @@
int result = mTextValue != null ? mTextValue.hashCode() : 0;
result = 31 * result + (mDateValue != null ? mDateValue.hashCode() : 0);
result = 31 * result + (mToggleValue != null ? mToggleValue.hashCode() : 0);
+ result = 31 * result + mFieldTypeName.hashCode();
return result;
}
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java
deleted file mode 100644
index 7165859..0000000
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/model/FilledAutofillFieldCollection.java
+++ /dev/null
@@ -1,234 +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.util.Log;
-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 com.example.android.autofill.service.AutofillHints;
-import com.example.android.autofill.service.W3cHints;
-import com.google.gson.annotations.Expose;
-
-import java.util.HashMap;
-import java.util.List;
-
-import static com.example.android.autofill.service.CommonUtil.DEBUG;
-import static com.example.android.autofill.service.CommonUtil.TAG;
-
-/**
- * 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 {
- @Expose
- private final HashMap<String, FilledAutofillField> mHintMap;
- @Expose
- private String mDatasetName;
-
- public FilledAutofillFieldCollection() {
- this(null, new HashMap<String, FilledAutofillField>());
- }
-
- public FilledAutofillFieldCollection(String datasetName, HashMap<String, FilledAutofillField> hintMap) {
- mHintMap = hintMap;
- mDatasetName = datasetName;
- }
-
- private static boolean isW3cSectionPrefix(String hint) {
- return hint.startsWith(W3cHints.PREFIX_SECTION);
- }
-
- private static boolean isW3cAddressType(String hint) {
- switch (hint) {
- case W3cHints.SHIPPING:
- case W3cHints.BILLING:
- return true;
- }
- return false;
- }
-
- private static boolean isW3cTypePrefix(String hint) {
- switch (hint) {
- case W3cHints.PREFIX_WORK:
- case W3cHints.PREFIX_FAX:
- case W3cHints.PREFIX_HOME:
- case W3cHints.PREFIX_PAGER:
- return true;
- }
- return false;
- }
-
- private static boolean isW3cTypeHint(String hint) {
- switch (hint) {
- case W3cHints.TEL:
- case W3cHints.TEL_COUNTRY_CODE:
- case W3cHints.TEL_NATIONAL:
- case W3cHints.TEL_AREA_CODE:
- case W3cHints.TEL_LOCAL:
- case W3cHints.TEL_LOCAL_PREFIX:
- case W3cHints.TEL_LOCAL_SUFFIX:
- case W3cHints.TEL_EXTENSION:
- case W3cHints.EMAIL:
- case W3cHints.IMPP:
- return true;
- }
- Log.w(TAG, "Invalid W3C type hint: " + hint);
- return false;
- }
-
- /**
- * Returns the name of the {@link Dataset}.
- */
- public String getDatasetName() {
- return mDatasetName;
- }
-
- /**
- * Sets the {@link Dataset} name.
- */
- public void setDatasetName(String datasetName) {
- mDatasetName = datasetName;
- }
-
- /**
- * Adds a {@code FilledAutofillField} to the collection, indexed by all of its hints.
- */
- public void add(@NonNull FilledAutofillField filledAutofillField) {
- String[] autofillHints = filledAutofillField.getAutofillHints();
- String nextHint = null;
- for (int i = 0; i < autofillHints.length; i++) {
- String hint = autofillHints[i];
- if (i < autofillHints.length - 1) {
- nextHint = autofillHints[i + 1];
- }
- // First convert the compound W3C autofill hints
- if (isW3cSectionPrefix(hint) && i < autofillHints.length - 1) {
- hint = autofillHints[++i];
- if (DEBUG) Log.d(TAG, "Hint is a W3C section prefix; using " + hint + " instead");
- if (i < autofillHints.length - 1) {
- nextHint = autofillHints[i + 1];
- }
- }
- if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint)) {
- hint = nextHint;
- i++;
- if (DEBUG) Log.d(TAG, "Hint is a W3C type prefix; using " + hint + " instead");
- }
- if (isW3cAddressType(hint) && nextHint != null) {
- hint = nextHint;
- i++;
- if (DEBUG) Log.d(TAG, "Hint is a W3C address prefix; using " + hint + " instead");
- }
-
- // Then check if the "actual" hint is supported.
-
-
- if (AutofillHints.isValidHint(hint)) {
- mHintMap.put(hint, filledAutofillField);
- } else {
- Log.e(TAG, "Invalid hint: " + autofillHints[i]);
- }
- }
- }
-
- /**
- * Populates a {@link Dataset.Builder} with appropriate values for each {@link AutofillId}
- * in a {@code AutofillFieldMetadataCollection}.
- *
- * 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:
- Log.w(TAG, "Invalid autofill type - " + autofillType);
- break;
- }
- }
- }
- return setValueAtLeastOnce;
- }
-
- /**
- * Takes in a list of autofill hints (autofillHints), usually associated with a View or set of
- * Views. Returns whether any of the filled fields on the page have at least 1 of these
- * autofillHints.
- */
- public boolean helpsWithHints(List<String> autofillHints) {
- for (int i = 0; i < autofillHints.size(); i++) {
- String autofillHint = autofillHints.get(i);
- if (mHintMap.containsKey(autofillHint) && !mHintMap.get(autofillHint).isNull()) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/MyPreferences.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/MyPreferences.java
index 563b4fc..6a723f0 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/MyPreferences.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/MyPreferences.java
@@ -17,12 +17,19 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.service.autofill.Dataset;
+import android.service.autofill.FillResponse;
import android.support.annotation.NonNull;
+import com.example.android.autofill.service.util.Util;
+
public class MyPreferences {
private static final String RESPONSE_AUTH_KEY = "response_auth";
private static final String DATASET_AUTH_KEY = "dataset_auth";
private static final String MASTER_PASSWORD_KEY = "master_password";
+ private static final String LOGGING_LEVEL = "logging_level";
+ private static final String DAL_CHECK_REQUIRED = "dal_check_required";
+ private static final String NUMBER_DATASETS = "number_datasets";
private static MyPreferences sInstance;
private final SharedPreferences mPrefs;
@@ -83,4 +90,30 @@
public void clearCredentials() {
mPrefs.edit().remove(MASTER_PASSWORD_KEY).apply();
}
+
+ public Util.LogLevel getLoggingLevel() {
+ return Util.LogLevel.values()[mPrefs.getInt(LOGGING_LEVEL, Util.LogLevel.Off.ordinal())];
+ }
+
+ public void setLoggingLevel(Util.LogLevel level) {
+ mPrefs.edit().putInt(LOGGING_LEVEL, level.ordinal()).apply();
+ Util.setLoggingLevel(level);
+ }
+
+ public Util.DalCheckRequirement getDalCheckRequirement() {
+ return Util.DalCheckRequirement.values()[mPrefs.getInt(DAL_CHECK_REQUIRED,
+ Util.DalCheckRequirement.AllUrls.ordinal())];
+ }
+
+ public void setDalCheckRequired(Util.DalCheckRequirement level) {
+ mPrefs.edit().putInt(DAL_CHECK_REQUIRED, level.ordinal()).apply();
+ }
+
+ public int getNumberDatasets(int defaultNumber) {
+ return mPrefs.getInt(NUMBER_DATASETS, defaultNumber);
+ }
+
+ public void setNumberDatasets(int number) {
+ mPrefs.edit().putInt(NUMBER_DATASETS, number).apply();
+ }
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
index 3a96faf..500ceec 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/java/com/example/android/autofill/service/settings/SettingsActivity.java
@@ -17,45 +17,88 @@
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;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.autofill.AutofillManager;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.NumberPicker;
+import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;
import com.example.android.autofill.service.R;
-import com.example.android.autofill.service.AutofillHints;
-import com.example.android.autofill.service.datasource.SharedPrefsAutofillRepository;
-import com.example.android.autofill.service.datasource.SharedPrefsPackageVerificationRepository;
-import com.example.android.autofill.service.model.FilledAutofillFieldCollection;
+import com.example.android.autofill.service.data.AutofillDataBuilder;
+import com.example.android.autofill.service.data.DataCallback;
+import com.example.android.autofill.service.data.FakeAutofillDataBuilder;
+import com.example.android.autofill.service.data.source.DefaultFieldTypesSource;
+import com.example.android.autofill.service.data.source.PackageVerificationDataSource;
+import com.example.android.autofill.service.data.source.local.DefaultFieldTypesLocalJsonSource;
+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.model.FieldTypeWithHeuristics;
+import com.example.android.autofill.service.util.AppExecutors;
+import com.example.android.autofill.service.util.Util;
+import com.google.gson.GsonBuilder;
+
+import java.util.List;
+
+import static com.example.android.autofill.service.util.Util.DalCheckRequirement.AllUrls;
+import static com.example.android.autofill.service.util.Util.DalCheckRequirement.Disabled;
+import static com.example.android.autofill.service.util.Util.DalCheckRequirement.LoginOnly;
+import static com.example.android.autofill.service.util.Util.logd;
+import static com.example.android.autofill.service.util.Util.logw;
public class SettingsActivity extends AppCompatActivity {
private static final String TAG = "SettingsActivity";
+ private static final int REQUEST_CODE_SET_DEFAULT = 1;
+ private AutofillManager mAutofillManager;
+ private LocalAutofillDataSource mLocalAutofillDataSource;
+ private PackageVerificationDataSource mPackageVerificationDataSource;
+ private MyPreferences mPreferences;
+ private String mPackageName;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multidataset_service_settings_activity);
- final MyPreferences preferences = MyPreferences.getInstance(this);
+ SharedPreferences localAfDataSourceSharedPrefs =
+ getSharedPreferences(LocalAutofillDataSource.SHARED_PREF_KEY, Context.MODE_PRIVATE);
+ DefaultFieldTypesSource defaultFieldTypesSource =
+ DefaultFieldTypesLocalJsonSource.getInstance(getResources(),
+ new GsonBuilder().create());
+ AutofillDao autofillDao = AutofillDatabase.getInstance(
+ this, defaultFieldTypesSource, new AppExecutors()).autofillDao();
+ mPackageName = getPackageName();
+ mLocalAutofillDataSource = LocalAutofillDataSource.getInstance(localAfDataSourceSharedPrefs,
+ autofillDao, new AppExecutors());
+ mAutofillManager = getSystemService(AutofillManager.class);
+ mPackageVerificationDataSource =
+ SharedPrefsPackageVerificationRepository.getInstance(this);
+ mPreferences = MyPreferences.getInstance(this);
setupSettingsSwitch(R.id.settings_auth_responses_container,
R.id.settings_auth_responses_label,
R.id.settings_auth_responses_switch,
- preferences.isResponseAuth(),
- (compoundButton, isResponseAuth) -> preferences.setResponseAuth(isResponseAuth));
+ mPreferences.isResponseAuth(),
+ (compoundButton, isResponseAuth) -> mPreferences.setResponseAuth(isResponseAuth));
setupSettingsSwitch(R.id.settings_auth_datasets_container,
R.id.settings_auth_datasets_label,
R.id.settings_auth_datasets_switch,
- preferences.isDatasetAuth(),
- (compoundButton, isDatasetAuth) -> preferences.setDatasetAuth(isDatasetAuth));
+ mPreferences.isDatasetAuth(),
+ (compoundButton, isDatasetAuth) -> mPreferences.setDatasetAuth(isDatasetAuth));
setupSettingsButton(R.id.settings_add_data_container,
R.id.settings_add_data_label,
R.id.settings_add_data_icon,
@@ -68,12 +111,70 @@
R.id.settings_auth_credentials_label,
R.id.settings_auth_credentials_icon,
(view) -> {
- if (preferences.getMasterPassword() != null) {
+ if (mPreferences.getMasterPassword() != null) {
buildCurrentCredentialsDialog().show();
} else {
buildNewCredentialsDialog().show();
}
});
+ setupSettingsSwitch(R.id.settingsSetServiceContainer,
+ R.id.settingsSetServiceLabel,
+ R.id.settingsSetServiceSwitch,
+ mAutofillManager.hasEnabledAutofillServices(),
+ (compoundButton, serviceSet) -> setService(serviceSet));
+ RadioGroup loggingLevelContainer = findViewById(R.id.loggingLevelContainer);
+ Util.LogLevel loggingLevel = mPreferences.getLoggingLevel();
+ Util.setLoggingLevel(loggingLevel);
+ switch (loggingLevel) {
+ case Off:
+ loggingLevelContainer.check(R.id.loggingOff);
+ break;
+ case Debug:
+ loggingLevelContainer.check(R.id.loggingDebug);
+ break;
+ case Verbose:
+ loggingLevelContainer.check(R.id.loggingVerbose);
+ break;
+ }
+ loggingLevelContainer.setOnCheckedChangeListener((group, checkedId) -> {
+ switch (checkedId) {
+ case R.id.loggingOff:
+ mPreferences.setLoggingLevel(Util.LogLevel.Off);
+ break;
+ case R.id.loggingDebug:
+ mPreferences.setLoggingLevel(Util.LogLevel.Debug);
+ break;
+ case R.id.loggingVerbose:
+ mPreferences.setLoggingLevel(Util.LogLevel.Verbose);
+ break;
+ }
+ });
+ RadioGroup dalCheckRequirementContainer = findViewById(R.id.dalCheckRequirementContainer);
+ Util.DalCheckRequirement dalCheckRequirement = mPreferences.getDalCheckRequirement();
+ switch (dalCheckRequirement) {
+ case Disabled:
+ dalCheckRequirementContainer.check(R.id.dalDisabled);
+ break;
+ case LoginOnly:
+ dalCheckRequirementContainer.check(R.id.dalLoginOnly);
+ break;
+ case AllUrls:
+ dalCheckRequirementContainer.check(R.id.dalAllUrls);
+ break;
+ }
+ dalCheckRequirementContainer.setOnCheckedChangeListener((group, checkedId) -> {
+ switch (checkedId) {
+ case R.id.dalDisabled:
+ mPreferences.setDalCheckRequired(Disabled);
+ break;
+ case R.id.dalLoginOnly:
+ mPreferences.setDalCheckRequired(LoginOnly);
+ break;
+ case R.id.dalAllUrls:
+ mPreferences.setDalCheckRequired(AllUrls);
+ break;
+ }
+ });
}
private AlertDialog buildClearDataDialog() {
@@ -82,10 +183,9 @@
.setTitle(R.string.settings_clear_data_confirmation_title)
.setNegativeButton(R.string.settings_cancel, null)
.setPositiveButton(R.string.settings_ok, (dialog, which) -> {
- SharedPrefsAutofillRepository.getInstance().clear(SettingsActivity.this);
- SharedPrefsPackageVerificationRepository.getInstance()
- .clear(SettingsActivity.this);
- MyPreferences.getInstance(SettingsActivity.this).clearCredentials();
+ mLocalAutofillDataSource.clear();
+ mPackageVerificationDataSource.clear();
+ mPreferences.clearCredentials();
dialog.dismiss();
})
.create();
@@ -106,35 +206,44 @@
.setView(numberOfDatasetsPicker)
.setPositiveButton(R.string.settings_ok, (dialog, which) -> {
int numOfDatasets = numberOfDatasetsPicker.getValue();
- boolean success = buildAndSaveMockedAutofillFieldCollection(
- SettingsActivity.this, numOfDatasets);
- dialog.dismiss();
- if (success) {
- Snackbar.make(SettingsActivity.this.findViewById(R.id.settings_layout),
- SettingsActivity.this.getResources().getQuantityString(
- R.plurals.settings_add_data_success, numOfDatasets,
- numOfDatasets),
- Snackbar.LENGTH_SHORT).show();
- }
+ mPreferences.setNumberDatasets(numOfDatasets);
+ mLocalAutofillDataSource.getFieldTypes(new DataCallback<List<FieldTypeWithHeuristics>>() {
+ @Override
+ public void onLoaded(List<FieldTypeWithHeuristics> fieldTypes) {
+ boolean saved = buildAndSaveMockedAutofillFieldCollections(
+ fieldTypes, numOfDatasets);
+ dialog.dismiss();
+ if (saved) {
+ Snackbar.make(findViewById(R.id.settings_layout),
+ getResources().getQuantityString(
+ R.plurals.settings_add_data_success,
+ numOfDatasets, numOfDatasets),
+ Snackbar.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onDataNotAvailable(String msg, Object... params) {
+
+ }
+ });
})
.create();
}
- /**
- * Builds mock autofill data and saves it to repository.
- */
- private boolean buildAndSaveMockedAutofillFieldCollection(Context context, int numOfDatasets) {
+ public boolean buildAndSaveMockedAutofillFieldCollections(List<FieldTypeWithHeuristics> fieldTypes,
+ int numOfDatasets) {
if (numOfDatasets < 0 || numOfDatasets > 10) {
- Log.w(TAG, "Number of Datasets out of range.");
- return false;
+ logw("Number of Datasets (%d) out of range.", numOfDatasets);
}
- for (int i = 0; i < numOfDatasets * 2; i += 2) {
- for (int partition : AutofillHints.PARTITIONS) {
- FilledAutofillFieldCollection filledAutofillFieldCollection =
- AutofillHints.getFakeFieldCollection(partition, i);
- SharedPrefsAutofillRepository.getInstance().saveFilledAutofillFieldCollection(
- context, filledAutofillFieldCollection);
- }
+ for (int i = 0; i < numOfDatasets; i++) {
+ int datasetNumber = mLocalAutofillDataSource.getDatasetNumber();
+ AutofillDataBuilder autofillDataBuilder =
+ new FakeAutofillDataBuilder(fieldTypes, mPackageName, datasetNumber);
+ List<DatasetWithFilledAutofillFields> datasetsWithFilledAutofillFields =
+ autofillDataBuilder.buildDatasetsByPartition(datasetNumber);
+ // Save datasets to database.
+ mLocalAutofillDataSource.saveAutofillDatasets(datasetsWithFilledAutofillFields);
}
return true;
}
@@ -157,7 +266,7 @@
@Override
public void onClick(DialogInterface dialog, int which) {
String password = currentPasswordField.getText().toString();
- if (MyPreferences.getInstance(SettingsActivity.this).getMasterPassword()
+ if (mPreferences.getMasterPassword()
.equals(password)) {
buildNewCredentialsDialog().show();
dialog.dismiss();
@@ -177,7 +286,7 @@
.setView(newPasswordField)
.setPositiveButton(R.string.settings_ok, (dialog, which) -> {
String password = newPasswordField.getText().toString();
- MyPreferences.getInstance(SettingsActivity.this).setMasterPassword(password);
+ mPreferences.setMasterPassword(password);
dialog.dismiss();
})
.create();
@@ -203,4 +312,61 @@
imageView.setContentDescription(buttonLabelText);
container.setOnClickListener(onClickListener);
}
+
+ private void setService(boolean enableService) {
+ if (enableService) {
+ startEnableService();
+ } else {
+ disableService();
+ }
+ }
+
+ private void disableService() {
+ if (mAutofillManager != null && mAutofillManager.hasEnabledAutofillServices()) {
+ mAutofillManager.disableAutofillServices();
+ Snackbar.make(findViewById(R.id.settings_layout),
+ R.string.settings_autofill_disabled_message, Snackbar.LENGTH_SHORT).show();
+ } else {
+ logd("Sample service already disabled.");
+ }
+ }
+
+ private void startEnableService() {
+ if (mAutofillManager != null && !mAutofillManager.hasEnabledAutofillServices()) {
+ Intent intent = new Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE);
+ intent.setData(Uri.parse("package:com.example.android.autofill.service"));
+ logd(TAG, "enableService(): intent=%s", intent);
+ startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT);
+ } else {
+ logd("Sample service already enabled.");
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ logd(TAG, "onActivityResult(): req=%s", requestCode);
+ switch (requestCode) {
+ case REQUEST_CODE_SET_DEFAULT:
+ onDefaultServiceSet(resultCode);
+ break;
+ }
+ }
+
+ private void onDefaultServiceSet(int resultCode) {
+ logd(TAG, "resultCode=%d", resultCode);
+ switch (resultCode) {
+ case RESULT_OK:
+ logd("Autofill service set.");
+ Snackbar.make(findViewById(R.id.settings_layout),
+ R.string.settings_autofill_service_set, Snackbar.LENGTH_SHORT)
+ .show();
+ break;
+ case RESULT_CANCELED:
+ logd("Autofill service not selected.");
+ Snackbar.make(findViewById(R.id.settings_layout),
+ R.string.settings_autofill_service_not_set, Snackbar.LENGTH_SHORT)
+ .show();
+ break;
+ }
+ }
}
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_add_black_24dp.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_add_black_24dp.xml
index e50269d..ed8512a 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_add_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_add_black_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_delete_forever_black_24dp.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_delete_forever_black_24dp.xml
index 4d2afb0..5b5927d 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_delete_forever_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_delete_forever_black_24dp.xml
@@ -13,8 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<vector android:alpha="0.50" android:height="24dp"
- android:viewportHeight="24.0" android:viewportWidth="24.0"
- android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:alpha="0.50"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_lock_black_24dp.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_lock_black_24dp.xml
index 6b2f014..6e18f1a 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_lock_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_lock_black_24dp.xml
@@ -14,11 +14,11 @@
* limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_person_black_24dp.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_person_black_24dp.xml
index 6534d9f..032db12 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_person_black_24dp.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/drawable-v24/ic_person_black_24dp.xml
@@ -13,8 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<vector android:alpha="0.50" android:height="24dp"
- android:viewportHeight="24.0" android:viewportWidth="24.0"
- android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:alpha="0.50"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z" />
</vector>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_auth_activity.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_auth_activity.xml
index 5430e52..844ea0a 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_auth_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_auth_activity.xml
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.constraint.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/authLayout"
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_list_item.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_list_item.xml
index ef56428..a988d67 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_list_item.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_list_item.xml
@@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@android:color/white"
android:orientation="horizontal">
<TextView
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_activity.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_activity.xml
index 1618bdc..ce77e27 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_activity.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_activity.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.support.v4.widget.NestedScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
@@ -27,8 +25,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:paddingBottom="@dimen/spacing_large"
- android:paddingTop="@dimen/spacing_large">
+ android:paddingBottom="@dimen/spacing_large">
<TextView
style="@style/Settings.Header"
@@ -48,7 +45,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:importantForAccessibility="no"
android:text="@string/settings_authenticate_responses" />
<Switch
@@ -73,7 +69,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:importantForAccessibility="no"
android:text="@string/settings_authenticate_datasets" />
<Switch
@@ -114,7 +109,6 @@
style="@style/Settings.Header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="@dimen/spacing_normal"
android:text="@string/settings_data_header" />
<LinearLayout
@@ -164,6 +158,110 @@
android:minHeight="@dimen/a11y_min_touch_target_dimen"
android:src="@drawable/ic_delete_forever_black_24dp" />
</LinearLayout>
- </LinearLayout>
+ <TextView
+ style="@style/Settings.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/settings_dal_header" />
+
+ <RadioGroup
+ android:id="@+id/dalCheckRequirementContainer"
+ style="@style/Settings.Container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/dalDisabled"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_dal_disabled" />
+
+ <RadioButton
+ android:id="@+id/dalLoginOnly"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_dal_login_only" />
+
+ <RadioButton
+ android:id="@+id/dalAllUrls"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_dal_all_urls" />
+ </RadioGroup>
+
+ <TextView
+ style="@style/Settings.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/settings_logging_header" />
+
+ <RadioGroup
+ android:id="@+id/loggingLevelContainer"
+ style="@style/Settings.Container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/loggingOff"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_logging_off" />
+
+ <RadioButton
+ android:id="@+id/loggingDebug"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_logging_debug" />
+
+ <RadioButton
+ android:id="@+id/loggingVerbose"
+ style="@style/Settings.Label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen"
+ android:text="@string/settings_logging_verbose" />
+ </RadioGroup>
+
+ <TextView
+ style="@style/Settings.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/settings_enable_header" />
+
+ <LinearLayout
+ android:id="@+id/settingsSetServiceContainer"
+ style="@style/Settings.Container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/settingsSetServiceLabel"
+ style="@style/Settings.Label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/settings_set_service" />
+
+ <Switch
+ android:id="@+id/settingsSetServiceSwitch"
+ style="@style/Settings.Switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/padding_normal"
+ android:minHeight="@dimen/a11y_min_touch_target_dimen" />
+ </LinearLayout>
+ </LinearLayout>
</android.support.v4.widget.NestedScrollView>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_add_data_dialog.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_add_data_dialog.xml
index 019a367..530451e 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_add_data_dialog.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_add_data_dialog.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<NumberPicker
- xmlns:android="http://schemas.android.com/apk/res/android"
+<NumberPicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/number_of_datasets_picker"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_authentication_dialog.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_authentication_dialog.xml
index bfd6931..a84e45f 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_authentication_dialog.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/layout/multidataset_service_settings_authentication_dialog.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<EditText
- xmlns:android="http://schemas.android.com/apk/res/android"
+<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/master_password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/colors.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/colors.xml
index 3ab3e9c..4d80b9f 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/colors.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/colors.xml
@@ -1,6 +1,21 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2018 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.
+-->
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
+ <color name="light_grey">#ffeeeeee</color>
</resources>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/dimens.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/dimens.xml
index d451580..8a21b70 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/dimens.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/dimens.xml
@@ -1,4 +1,18 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2018 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.
+-->
<resources>
<dimen name="padding_normal">16dp</dimen>
<dimen name="activity_horizontal_margin">16dp</dimen>
@@ -7,4 +21,5 @@
<dimen name="spacing_large">32dp</dimen>
<dimen name="a11y_min_touch_target_dimen">48dp</dimen>
<dimen name="text_field_width">250sp</dimen>
+ <dimen name="card_elevation">2dp</dimen>
</resources>
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/strings.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/strings.xml
index b9b5e37..e7b1f88 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/strings.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/strings.xml
@@ -1,11 +1,31 @@
+<!--
+ * Copyright (C) 2018 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.
+-->
<resources>
<string name="invalid_package_signature">Invalid package signature</string>
- <string name="invalid_link_association">Could not associate web domain %1$s with app %2$s</string>
+ <string name="security_exception">Web domain security exception.</string>
+ <string name="dal_exception">DAL verification failure.</string>
<string name="autofill_sign_in_prompt">Tap to sign in.</string>
+ <string name="autofill_manual_prompt">Tap to manually select data.</string>
+ <string name="authentication_name">Autofill Authentication</string>
+ <string name="manual_name">Manual (Auto)fill</string>
+ <string name="manual_field_picker_name">Select Field</string>
<string name="settings_name">Autofill Settings</string>
<string name="settings_cancel">Cancel</string>
<string name="settings_save">Save</string>
- <string name="settings_authenticate_responses">Authenticate responses</string>
+ <string name="settings_authenticate_responses">Authenticate Responses</string>
<string name="settings_authenticate_datasets">Authenticate Datasets</string>
<string name="settings_add_data_label">Add fake Autofill data</string>
<string name="settings_add_data_title">Add Autofill Datasets</string>
@@ -21,6 +41,22 @@
<string name="settings_clear_data_confirmation_title">Confirmation</string>
<string name="settings_authentication_header">Authentication</string>
<string name="settings_data_header">Data</string>
+ <string name="settings_logging_header">Logging</string>
+ <string name="settings_logging_off">Off</string>
+ <string name="settings_logging_debug">Debug</string>
+ <string name="settings_logging_verbose">Verbose</string>
+
+ <string name="settings_dal_header">DAL Check Requirement</string>
+ <string name="settings_dal_disabled">Disabled</string>
+ <string name="settings_dal_login_only">Login Credentials Only</string>
+ <string name="settings_dal_all_urls">Handle All URLs</string>
+
+ <string name="settings_enable_header">Enable/Disable</string>
+ <string name="settings_set_service">Set default Autofill service</string>
+ <string name="settings_disable_service">Disable Autofill services</string>
+ <string name="settings_autofill_disabled_message">Autofill service has been disabled.</string>
+ <string name="settings_autofill_service_set">Sample service set to default.</string>
+ <string name="settings_autofill_service_not_set">Sample service not set to default.</string>
<string name="settings_auth_credentials_label">Update credentials</string>
<string name="settings_auth_enter_current_password">Enter current password</string>
<string name="settings_auth_enter_new_password">Enter new password</string>
@@ -30,7 +66,10 @@
<string name="auth_password_label">Password</string>
<string name="auth_cancel">Cancel</string>
<string name="auth_login_label">Login</string>
- <string name="settings_ok">Ok</string>
+ <string name="settings_ok">OK</string>
+ <string name="manual_dataset_name_label">Dataset Name</string>
+ <string name="manual_field_types_label">Field Types</string>
+ <string name="manual_data_picker_title">Fields for %1$s</string>
<string-array name="month_array">
<item>1</item>
<item>2</item>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/styles.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/styles.xml
index b954cb6..c15a739 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/styles.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/values/styles.xml
@@ -1,13 +1,26 @@
+<!--
+ * Copyright (C) 2018 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.
+-->
<resources>
<!-- Base application theme. -->
- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
- <item name="colorPrimary">@color/colorPrimary</item>
- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
- <item name="colorAccent">@color/colorAccent</item>
</style>
- <style name="Settings.Label" parent="">
+
+ <style name="Settings.Label" parent="@style/TextAppearance.AppCompat.Body1">
<item name="android:ellipsize">end</item>
<item name="android:lines">1</item>
<item name="android:paddingBottom">@dimen/spacing_normal</item>
@@ -32,5 +45,20 @@
<style name="Settings.Header" parent="@style/TextAppearance.AppCompat.Large">
<item name="android:paddingStart">?android:listPreferredItemPaddingStart</item>
<item name="android:paddingBottom">@dimen/spacing_normal</item>
+ <item name="android:paddingTop">@dimen/spacing_large</item>
+ </style>
+
+ <style name="Manual.Header" parent="@style/TextAppearance.AppCompat.Large">
+ <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item>
+ <item name="android:paddingEnd">?android:listPreferredItemPaddingEnd</item>
+ <item name="android:paddingBottom">@dimen/spacing_normal</item>
+ <item name="android:paddingTop">@dimen/spacing_normal</item>
+ </style>
+
+ <style name="Manual.Content" parent="@style/TextAppearance.AppCompat.Medium">
+ <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item>
+ <item name="android:paddingEnd">?android:listPreferredItemPaddingEnd</item>
+ <item name="android:paddingBottom">@dimen/spacing_normal</item>
+ <item name="android:paddingTop">@dimen/spacing_normal</item>
</style>
</resources>
diff --git a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/xml/multidataset_service.xml b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/xml/multidataset_service.xml
index 8876815..de58167 100644
--- a/prebuilts/gradle/AutofillFramework/afservice/src/main/res/xml/multidataset_service.xml
+++ b/prebuilts/gradle/AutofillFramework/afservice/src/main/res/xml/multidataset_service.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +18,5 @@
Attributes for the AutoFill service that tell the framework what will act as the Autofill service's
Settings Activity. This is pointed to in the service's meta-data in the application's manifest.
-->
-<autofill-service
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity="com.example.android.autofill.service.settings.SettingsActivity"/>
\ No newline at end of file
+<autofill-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity="com.example.android.autofill.service.settings.SettingsActivity" />
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/build.gradle b/prebuilts/gradle/AutofillFramework/build.gradle
index ef010b9..8554413 100644
--- a/prebuilts/gradle/AutofillFramework/build.gradle
+++ b/prebuilts/gradle/AutofillFramework/build.gradle
@@ -1,18 +1,18 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
- jcenter()
google()
+ jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.0'
+ classpath 'com.android.tools.build:gradle:3.1.0'
}
}
allprojects {
repositories {
- jcenter()
google()
+ jcenter()
}
}
diff --git a/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.jar b/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64..13372ae 100644
--- a/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.jar
+++ b/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.properties b/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
index 15b344d..1df2551 100644
--- a/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
+++ b/prebuilts/gradle/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Oct 26 11:55:14 PDT 2017
+#Fri Jan 12 11:03:13 PST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
diff --git a/prebuilts/gradle/AutofillFramework/gradlew b/prebuilts/gradle/AutofillFramework/gradlew
index 91a7e26..9d82f78 100755
--- a/prebuilts/gradle/AutofillFramework/gradlew
+++ b/prebuilts/gradle/AutofillFramework/gradlew
@@ -42,11 +42,6 @@
;;
esac
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
- [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +56,9 @@
fi
done
SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
+cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
+cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -114,6 +109,7 @@
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
diff --git a/prebuilts/gradle/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml b/prebuilts/gradle/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
index 2470645..88a0d72 100644
--- a/prebuilts/gradle/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
+++ b/prebuilts/gradle/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
@@ -75,7 +75,7 @@
<service
android:name=".multidatasetservice.MyAutofillService"
android:label="Multi-Dataset Autofill Service"
- android:permission="android.permission.BIND_AUTOFILL">
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE" >
<meta-data
android:name="android.autofill"
android:resource="@xml/multidataset_service" />
@@ -88,4 +88,4 @@
<activity android:name=".multidatasetservice.AuthActivity" />
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/prebuilts/gradle/AutofillFramework/kotlinApp/README.md b/prebuilts/gradle/AutofillFramework/kotlinApp/README.md
index 4b58f47..d0ab0e0 100644
--- a/prebuilts/gradle/AutofillFramework/kotlinApp/README.md
+++ b/prebuilts/gradle/AutofillFramework/kotlinApp/README.md
@@ -1,3 +1,5 @@
+Warning: This sample is currently outdated and you should reference the Java version instead.
+============================================================================================
Android AutofillFramework Sample (Kotlin)
=========================================
diff --git a/prebuilts/gradle/AutofillFramework/kotlinApp/build.gradle b/prebuilts/gradle/AutofillFramework/kotlinApp/build.gradle
index 7eb0ddd..8ff27c5 100644
--- a/prebuilts/gradle/AutofillFramework/kotlinApp/build.gradle
+++ b/prebuilts/gradle/AutofillFramework/kotlinApp/build.gradle
@@ -1,9 +1,7 @@
buildscript {
repositories {
+ google()
jcenter()
- maven {
- url 'https://maven.google.com'
- }
}
ext.kotlin_version = '1.1.4-3'
dependencies {
@@ -14,9 +12,7 @@
allprojects {
repositories {
+ google()
jcenter()
- maven {
- url 'https://maven.google.com'
- }
}
}
\ No newline at end of file
diff --git a/prebuilts/gradle/AutofillFramework/kotlinApp/gradle/wrapper/gradle-wrapper.properties b/prebuilts/gradle/AutofillFramework/kotlinApp/gradle/wrapper/gradle-wrapper.properties
index 34facd6..a6dc381 100644
--- a/prebuilts/gradle/AutofillFramework/kotlinApp/gradle/wrapper/gradle-wrapper.properties
+++ b/prebuilts/gradle/AutofillFramework/kotlinApp/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip