Merge "Fix some racines in AutofillManager" into oc-dev

am: 2ddd69ce1a

Change-Id: Iec8454a36985484148b821f598446d5305c601bc
This commit is contained in:
Philip P. Moltmann
2017-04-14 22:11:06 +00:00
committed by android-build-merger
3 changed files with 129 additions and 108 deletions

View File

@@ -760,8 +760,8 @@ public final class AutofillManager {
}
}
private void requestShowFillUi(IBinder windowToken, AutofillId id, int width, int height,
Rect anchorBounds, IAutofillWindowPresenter presenter) {
private void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width,
int height, Rect anchorBounds, IAutofillWindowPresenter presenter) {
final View anchor = findAchorView(windowToken, id);
if (anchor == null) {
return;
@@ -769,9 +769,15 @@ public final class AutofillManager {
AutofillCallback callback = null;
synchronized (mLock) {
if (getClientLocked().autofillCallbackRequestShowFillUi(anchor, width, height,
anchorBounds, presenter) && mCallback != null) {
callback = mCallback;
if (mSessionId == sessionId) {
AutofillClient client = getClientLocked();
if (client != null) {
if (client.autofillCallbackRequestShowFillUi(anchor, width, height,
anchorBounds, presenter) && mCallback != null) {
callback = mCallback;
}
}
}
}
@@ -785,6 +791,23 @@ public final class AutofillManager {
}
}
private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
synchronized (mLock) {
if (sessionId == mSessionId) {
AutofillClient client = getClientLocked();
if (client != null) {
client.autofillCallbackAuthenticate(intent, fillInIntent);
}
}
}
}
private void setState(boolean enabled) {
synchronized (mLock) {
mEnabled = enabled;
}
}
/**
* Sets a view as autofilled if the current value is the {code targetValue}.
*
@@ -804,80 +827,92 @@ public final class AutofillManager {
}
}
private void handleAutofill(IBinder windowToken, List<AutofillId> ids,
private void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids,
List<AutofillValue> values) {
final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
if (root == null) {
return;
}
final int itemCount = ids.size();
int numApplied = 0;
ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null;
for (int i = 0; i < itemCount; i++) {
final AutofillId id = ids.get(i);
final AutofillValue value = values.get(i);
final int viewId = id.getViewId();
final View view = root.findViewByAccessibilityIdTraversal(viewId);
if (view == null) {
Log.w(TAG, "autofill(): no View with id " + viewId);
continue;
synchronized (mLock) {
if (sessionId != mSessionId) {
return;
}
if (id.isVirtual()) {
if (virtualValues == null) {
// Most likely there will be just one view with virtual children.
virtualValues = new ArrayMap<>(1);
final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
if (root == null) {
return;
}
final int itemCount = ids.size();
int numApplied = 0;
ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null;
for (int i = 0; i < itemCount; i++) {
final AutofillId id = ids.get(i);
final AutofillValue value = values.get(i);
final int viewId = id.getViewId();
final View view = root.findViewByAccessibilityIdTraversal(viewId);
if (view == null) {
Log.w(TAG, "autofill(): no View with id " + viewId);
continue;
}
SparseArray<AutofillValue> valuesByParent = virtualValues.get(view);
if (valuesByParent == null) {
// We don't know the size yet, but usually it will be just a few fields...
valuesByParent = new SparseArray<>(5);
virtualValues.put(view, valuesByParent);
}
valuesByParent.put(id.getVirtualChildId(), value);
} else {
synchronized (mLock) {
if (id.isVirtual()) {
if (virtualValues == null) {
// Most likely there will be just one view with virtual children.
virtualValues = new ArrayMap<>(1);
}
SparseArray<AutofillValue> valuesByParent = virtualValues.get(view);
if (valuesByParent == null) {
// We don't know the size yet, but usually it will be just a few fields...
valuesByParent = new SparseArray<>(5);
virtualValues.put(view, valuesByParent);
}
valuesByParent.put(id.getVirtualChildId(), value);
} else {
// Mark the view as to be autofilled with 'value'
if (mLastAutofilledData == null) {
mLastAutofilledData = new ParcelableMap(itemCount - i);
}
mLastAutofilledData.put(id, value);
view.autofill(value);
// Set as autofilled if the values match now, e.g. when the value was updated
// synchronously.
// If autofill happens async, the view is set to autofilled in
// notifyValueChanged.
setAutofilledIfValuesIs(view, value);
numApplied++;
}
view.autofill(value);
// Set as autofilled if the values match now, e.g. when the value was updated
// synchronously.
// If autofill happens async, the view is set to autofilled in notifyValueChanged.
setAutofilledIfValuesIs(view, value);
numApplied++;
}
}
if (virtualValues != null) {
for (int i = 0; i < virtualValues.size(); i++) {
final View parent = virtualValues.keyAt(i);
final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i);
parent.autofill(childrenValues);
numApplied += childrenValues.size();
if (virtualValues != null) {
for (int i = 0; i < virtualValues.size(); i++) {
final View parent = virtualValues.keyAt(i);
final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i);
parent.autofill(childrenValues);
numApplied += childrenValues.size();
}
}
}
final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
mMetricsLogger.write(log);
final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED,
numApplied);
mMetricsLogger.write(log);
}
}
private void requestHideFillUi(IBinder windowToken, AutofillId id) {
private void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) {
final View anchor = findAchorView(windowToken, id);
AutofillCallback callback = null;
synchronized (mLock) {
if (getClientLocked().autofillCallbackRequestHideFillUi() && mCallback != null) {
callback = mCallback;
if (mSessionId == sessionId) {
AutofillClient client = getClientLocked();
if (client != null) {
if (client.autofillCallbackRequestHideFillUi() && mCallback != null) {
callback = mCallback;
}
}
}
}
@@ -891,12 +926,14 @@ public final class AutofillManager {
}
}
private void notifyNoFillUi(IBinder windowToken, AutofillId id) {
private void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) {
final View anchor = findAchorView(windowToken, id);
AutofillCallback callback;
AutofillCallback callback = null;
synchronized (mLock) {
callback = mCallback;
if (mSessionId == sessionId && getClientLocked() != null) {
callback = mCallback;
}
}
if (callback != null) {
@@ -999,73 +1036,57 @@ public final class AutofillManager {
public void setState(boolean enabled) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() -> {
synchronized (afm.mLock) {
afm.mEnabled = enabled;
}
});
afm.mContext.getMainThreadHandler().post(() -> afm.setState(enabled));
}
}
@Override
public void autofill(IBinder windowToken, List<AutofillId> ids,
public void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids,
List<AutofillValue> values) {
// TODO(b/33197203): must keep the dataset so subsequent calls pass the same
// dataset.extras to service
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() ->
afm.handleAutofill(windowToken, ids, values));
afm.mContext.getMainThreadHandler().post(
() -> afm.autofill(sessionId, windowToken, ids, values));
}
}
@Override
public void authenticate(IntentSender intent, Intent fillInIntent) {
public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() -> {
if (afm.getClientLocked() != null) {
afm.getClientLocked().autofillCallbackAuthenticate(intent, fillInIntent);
}
});
afm.mContext.getMainThreadHandler().post(
() -> afm.authenticate(sessionId, intent, fillInIntent));
}
}
@Override
public void requestShowFillUi(IBinder windowToken, AutofillId id,
public void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id,
int width, int height, Rect anchorBounds, IAutofillWindowPresenter presenter) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() -> {
if (afm.getClientLocked() != null) {
afm.requestShowFillUi(windowToken, id, width,
height, anchorBounds, presenter);
}
});
afm.mContext.getMainThreadHandler().post(
() -> afm.requestShowFillUi(sessionId, windowToken, id, width, height,
anchorBounds, presenter));
}
}
@Override
public void requestHideFillUi(IBinder windowToken, AutofillId id) {
public void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() -> {
if (afm.getClientLocked() != null) {
afm.requestHideFillUi(windowToken, id);
}
});
afm.mContext.getMainThreadHandler().post(
() -> afm.requestHideFillUi(sessionId, windowToken, id));
}
}
@Override
public void notifyNoFillUi(IBinder windowToken, AutofillId id) {
public void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(() -> {
if (afm.getClientLocked() != null) {
afm.notifyNoFillUi(windowToken, id);
}
});
afm.mContext.getMainThreadHandler().post(
() -> afm.notifyNoFillUi(sessionId, windowToken, id));
}
}

View File

@@ -40,28 +40,29 @@ oneway interface IAutoFillManagerClient {
/**
* Autofills the activity with the contents of a dataset.
*/
void autofill(in IBinder windowToken, in List<AutofillId> ids, in List<AutofillValue> values);
void autofill(int sessionId, in IBinder windowToken, in List<AutofillId> ids,
in List<AutofillValue> values);
/**
* Authenticates a fill response or a data set.
*/
void authenticate(in IntentSender intent, in Intent fillInIntent);
void authenticate(int sessionId, in IntentSender intent, in Intent fillInIntent);
/**
* Requests showing the fill UI.
*/
void requestShowFillUi(in IBinder windowToken, in AutofillId id, int width,
void requestShowFillUi(int sessionId, in IBinder windowToken, in AutofillId id, int width,
int height, in Rect anchorBounds, in IAutofillWindowPresenter presenter);
/**
* Requests hiding the fill UI.
*/
void requestHideFillUi(in IBinder windowToken, in AutofillId id);
void requestHideFillUi(int sessionId, in IBinder windowToken, in AutofillId id);
/**
* Notifies no fill UI will be shown.
*/
void notifyNoFillUi(in IBinder windowToken, in AutofillId id);
void notifyNoFillUi(int sessionId, in IBinder windowToken, in AutofillId id);
/**
* Starts the provided intent sender

View File

@@ -343,9 +343,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (id.equals(mCurrentViewId)) {
try {
final ViewState view = mViewStates.get(id);
mClient.requestShowFillUi(mWindowToken, id, width, height,
view.getVirtualBounds(),
presenter);
mClient.requestShowFillUi(this.id, mWindowToken, id, width, height,
view.getVirtualBounds(), presenter);
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting to show fill UI", e);
}
@@ -363,7 +362,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
public void requestHideFillUi(AutofillId id) {
synchronized (mLock) {
try {
mClient.requestHideFillUi(mWindowToken, id);
mClient.requestHideFillUi(this.id, mWindowToken, id);
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting to hide fill UI", e);
}
@@ -716,7 +715,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
if (!mHasCallback) return;
try {
mClient.notifyNoFillUi(mWindowToken, mCurrentViewId);
mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId);
} catch (RemoteException e) {
Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken
+ " id=" + mCurrentViewId, e);
@@ -852,7 +851,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private void startAuthentication(IntentSender intent, Intent fillInIntent) {
try {
synchronized (mLock) {
mClient.authenticate(intent, fillInIntent);
mClient.authenticate(id, intent, fillInIntent);
}
} catch (RemoteException e) {
Slog.e(TAG, "Error launching auth intent", e);
@@ -895,7 +894,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (DEBUG) {
Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
}
mClient.autofill(mWindowToken, dataset.getFieldIds(), dataset.getFieldValues());
mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues());
setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED);
} catch (RemoteException e) {
Slog.w(TAG, "Error autofilling activity: " + e);