diff options
author | 2017-01-31 02:47:25 +0000 | |
---|---|---|
committer | 2017-01-31 02:47:28 +0000 | |
commit | cf7d35e1fd756274a9a6b438e47cd0ded4540fbe (patch) | |
tree | 112094027cc551218158fdb5dc1d796fee657be1 | |
parent | a09a31f99f9d65e1100f8295c2b9db485fe68b07 (diff) | |
parent | 3922e6a8aa0072bc6048f646fdd6a4732bf04450 (diff) |
Merge "Add user picker for anchored window. Test: CtsAutoFillServiceTestCases"
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(); + } } } |