summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2017-01-31 02:47:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-01-31 02:47:28 +0000
commitcf7d35e1fd756274a9a6b438e47cd0ded4540fbe (patch)
tree112094027cc551218158fdb5dc1d796fee657be1
parenta09a31f99f9d65e1100f8295c2b9db485fe68b07 (diff)
parent3922e6a8aa0072bc6048f646fdd6a4732bf04450 (diff)
Merge "Add user picker for anchored window. Test: CtsAutoFillServiceTestCases"
-rw-r--r--core/res/res/values/dimens.xml6
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--services/autofill/java/com/android/server/autofill/AnchoredWindow.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/AutoFillUI.java26
-rw-r--r--services/autofill/java/com/android/server/autofill/DatasetPicker.java158
5 files changed, 107 insertions, 94 deletions
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4266f887abe3..927988f71283 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -174,7 +174,7 @@
<!-- height of the content margin on the bottom -->
<dimen name="notification_content_margin_bottom">16dp</dimen>
- <!-- The height of the background for a notification header on a group -->
+ <!-- The height of the background for a notification header on a group -->
<dimen name="notification_header_background_height">45.5dp</dimen>
<!-- Height of a small notification in the status bar -->
@@ -518,4 +518,8 @@
<dimen name="item_touch_helper_max_drag_scroll_per_frame">20dp</dimen>
<dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
<dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
+
+ <!-- The elevation of AutoFill fill window-->
+ <dimen name="autofill_fill_elevation">2dp</dimen>
+ <dimen name="autofill_fill_item_height">64dp</dimen>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 25ebb876da53..643dd02b5486 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2829,6 +2829,8 @@
<java-symbol type="dimen" name="item_touch_helper_swipe_escape_max_velocity"/>
<!-- com.android.server.autofill -->
+ <java-symbol type="dimen" name="autofill_fill_elevation" />
+ <java-symbol type="dimen" name="autofill_fill_item_height" />
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_no" />
diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
index e674309079dd..ecfd9b3dd6f7 100644
--- a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
+++ b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
@@ -28,6 +28,7 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
+import java.io.PrintWriter;
/**
* A window above the application that is smartly anchored to a rectangular region.
*/
@@ -114,6 +115,14 @@ final class AnchoredWindow {
return params;
}
+ void dump(PrintWriter pw) {
+ pw.println("Anchored Window");
+ final String prefix = " ";
+ pw.print(prefix); pw.print("width: "); pw.println(mWidth);
+ pw.print(prefix); pw.print("height: "); pw.println(mHeight);
+ pw.print(prefix); pw.print("visible: "); pw.println(mIsShowing);
+ }
+
/** FrameLayout that listens for touch events removes itself if the touch event is outside. */
private final class SelfRemovingView extends FrameLayout {
public SelfRemovingView(Context context) {
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index 511d3d98d666..96f340840542 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -18,6 +18,7 @@ package com.android.server.autofill;
import static com.android.server.autofill.Helper.DEBUG;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.Notification;
import android.app.Notification.Action;
@@ -38,6 +39,7 @@ import android.view.autofill.Dataset;
import android.view.autofill.FillResponse;
import android.view.Gravity;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;
@@ -60,6 +62,9 @@ final class AutoFillUI {
private final WindowManager mWm;
+ @Nullable
+ private AnchoredWindow mFillWindow;
+
/**
* Custom snackbar UI used for saving autofill or other informational messages.
*/
@@ -103,9 +108,23 @@ final class AutoFillUI {
void showResponse(int userId, int sessionId, AutoFillId autoFillId, Rect bounds,
FillResponse response) {
if (DEBUG) Slog.d(TAG, "showResponse: id=" + autoFillId + ", bounds=" + bounds);
- // TODO(b/33197203): proper implementation
- // TODO(b/33197203): make sure if removes the session from cache
- showOptionsNotification(userId, sessionId, autoFillId, response);
+
+ UiThread.getHandler().runWithScissors(() -> {
+ if (mFillWindow != null) {
+ mFillWindow.hide();
+ }
+
+ final DatasetPicker fillView = new DatasetPicker(mContext, response.getDatasets(),
+ (dataset) -> {
+ mFillWindow.hide();
+ onDatasetPicked(userId, dataset, sessionId);
+ });
+
+ // TODO(b/33197203): request width/height properly.
+ mFillWindow = new AnchoredWindow(mWm, fillView, 800,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ mFillWindow.show(bounds != null ? bounds : new Rect());
+ }, 0);
}
/**
@@ -180,6 +199,7 @@ final class AutoFillUI {
final String prefix = " ";
pw.print(prefix); pw.print("sResultCode: "); pw.println(sResultCode);
pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
+ mFillWindow.dump(pw);
}
private AutoFillManagerServiceImpl getServiceLocked(int userId) {
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
index bb641787a6d6..7245aaabfd30 100644
--- a/services/autofill/java/com/android/server/autofill/DatasetPicker.java
+++ b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
@@ -13,127 +13,105 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.server.autofill;
-import static com.android.server.autofill.Helper.DEBUG;
-
-import android.app.Activity;
import android.content.Context;
-import android.util.Slog;
-import android.view.View;
-import android.view.WindowManager;
+import android.graphics.Color;
import android.view.autofill.Dataset;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Filter.FilterListener;
+import android.widget.ListView;
import android.widget.TextView;
+import java.util.ArrayList;
import java.util.List;
/**
- * View responsible for drawing the {@link Dataset} options that can be used to auto-fill an
- * {@link Activity}.
+ * View for dataset picker.
+ *
+ * <p>A fill session starts when a View is clicked and FillResponse is supplied.
+ * <p>A fill session ends when 1) the user takes action in the UI, 2) another View is clicked, or
+ * 3) the View is detached.
*/
-final class DatasetPicker extends LinearLayout {
-
+final class DatasetPicker extends ListView implements OnItemClickListener {
private static final String TAG = "DatasetPicker";
- // TODO(b/33197203): use / calculate proper values instead of hardcoding them
- private static final LayoutParams NAME_PARAMS = new LayoutParams(400,
- WindowManager.LayoutParams.WRAP_CONTENT);
- private static final LayoutParams DROP_DOWN_PARAMS = new LayoutParams(100,
- WindowManager.LayoutParams.WRAP_CONTENT);
-
- private final Line[] mLines;
+ interface Listener {
+ void onDatasetPicked(Dataset dataset);
+ }
- private boolean mExpanded;
private final Listener mListener;
- public DatasetPicker(Context context, Listener listener, List<Dataset> datasets) {
+ DatasetPicker(Context context, List<Dataset> datasets, Listener listener) {
super(context);
-
mListener = listener;
- // TODO(b/33197203): use XML layout
- setOrientation(LinearLayout.VERTICAL);
-
- final int size = datasets.size();
- mLines = new Line[size];
+ final List<ViewItem> items = new ArrayList<>(datasets.size());
+ for (Dataset dataset : datasets) {
+ items.add(new ViewItem(dataset));
+ }
- for (int i = 0; i < size; i++) {
- final boolean first = i == 0;
- final Line line = new Line(context, datasets.get(i), first);
- mLines[i] = line;
- if (first) {
- addView(line);
+ final ArrayAdapter<ViewItem> adapter = new ArrayAdapter<ViewItem>(
+ context,
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ items) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final TextView textView = (TextView) super.getView(position, convertView, parent);
+ textView.setMinHeight(
+ getDimen(com.android.internal.R.dimen.autofill_fill_item_height));
+ return textView;
}
- }
- mExpanded = false;
+ };
+ setAdapter(adapter);
+ setBackgroundColor(Color.WHITE);
+ setDivider(null);
+ setElevation(getDimen(com.android.internal.R.dimen.autofill_fill_elevation));
+ setOnItemClickListener(this);
}
- private void togleDropDown() {
- if (mExpanded) {
- hideDropDown();
- return;
- }
- for (int i = 1; i < mLines.length; i++) {
- addView(mLines[i]);
- }
- mExpanded = true;
+ public void update(String prefix) {
+ final ArrayAdapter<ViewItem> adapter = (ArrayAdapter) getAdapter();
+ adapter.getFilter().filter(prefix, new FilterListener() {
+ @Override
+ public void onFilterComplete(int count) {
+ DatasetPicker.this.requestLayout();
+ }
+ });
}
- private void hideDropDown() {
- if (!mExpanded) return;
- // TODO(b/33197203): invert order to be less janky?
- for (int i = 1; i < mLines.length; i++) {
- removeView(mLines[i]);
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
+ if (mListener != null) {
+ final ViewItem vi = (ViewItem) adapterView.getItemAtPosition(pos);
+ mListener.onDatasetPicked(vi.getData());
}
- mExpanded = false;
}
- private class Line extends LinearLayout {
- final TextView name;
- final ImageView dropDown;
-
- private Line(Context context, Dataset dataset, boolean first) {
- super(context);
-
- final View.OnClickListener l = new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (DEBUG) Slog.d(TAG, "dataset picked: " + dataset.getName());
- mListener.onDatasetPicked(dataset);
-
- }
- };
-
- // TODO(b/33197203): use XML layout
- setOrientation(LinearLayout.HORIZONTAL);
-
- name = new TextView(context);
- name.setLayoutParams(NAME_PARAMS);
- name.setText(dataset.getName());
- name.setOnClickListener(l);
+ private int getDimen(int resId) {
+ return getContext().getResources().getDimensionPixelSize(resId);
+ }
- dropDown = new ImageView(context);
- dropDown.setLayoutParams(DROP_DOWN_PARAMS);
- // TODO(b/33197203): use proper icon
- dropDown.setImageResource(com.android.internal.R.drawable.arrow_down_float);
- dropDown.setOnClickListener((v) -> {
- togleDropDown();
- });
+ private static class ViewItem {
+ private final Dataset mData;
- if (!first) {
- dropDown.setVisibility(View.INVISIBLE);
- }
+ ViewItem(Dataset data) {
+ mData = data;
+ }
- addView(name);
- addView(dropDown);
+ public Dataset getData() {
+ return mData;
}
- }
- static interface Listener {
- void onDatasetPicked(Dataset dataset);
+ @Override
+ public String toString() {
+ // used by ArrayAdapter
+ return mData.getName().toString();
+ }
}
}