Loading core/java/android/app/Activity.java +16 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.autofill.AutofillClientController; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager.AutofillClient; import android.view.autofill.AutofillValue; import android.view.contentcapture.ContentCaptureContext; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient; Loading Loading @@ -10197,4 +10198,19 @@ public class Activity extends ContextThemeWrapper mJankTracker.disableAppJankTracking(); } } final void autofillViewIfAvailable( @NonNull AutofillId targetAutofillId, @NonNull AutofillValue autofillValue) { if (false) Log.v(TAG, "autofill view in client app Activity, id: " + targetAutofillId); runOnUiThread( () -> { View view = getAutofillClientController() .autofillClientFindViewByAutofillIdTraversal(targetAutofillId); if (view != null) { // TODO: b/410146465 support virtual views view.autofill(autofillValue); } }); } } core/java/android/app/ActivityThread.java +15 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,8 @@ import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.contentcapture.IContentCaptureManager; import android.view.contentcapture.IContentCaptureOptionsCallback; import android.view.translation.TranslationSpec; Loading Loading @@ -4723,6 +4725,19 @@ public final class ActivityThread extends ClientTransactionHandler resultCallback.sendResult(null); return; } if (actionId.equals(AutofillManager.DIRECT_ACTION_ID_REMOTE_AUTOFILL)) { AutofillId autofillId = arguments.getParcelable( AutofillManager.EXTRA_REMOTE_AUTOFILL_ID, AutofillId.class); AutofillValue autofillValue = arguments.getParcelable( AutofillManager.EXTRA_REMOTE_AUTOFILL_VALUE, AutofillValue.class); if (autofillId != null && autofillValue != null) { r.activity.autofillViewIfAvailable(autofillId, autofillValue); } } final Bundle nonNullArguments = (arguments != null) ? arguments : Bundle.EMPTY; r.activity.onPerformDirectAction(actionId, nonNullArguments, cancellationSignal, resultCallback::sendResult); Loading core/java/android/view/autofill/AutofillManager.java +58 −2 Original line number Diff line number Diff line Loading @@ -318,6 +318,32 @@ public final class AutofillManager { public static final String EXTRA_AUTOFILL_REQUEST_ID = "android.view.autofill.extra.AUTOFILL_REQUEST_ID"; /** * Internal {@link DirectAction#getId()} used to pass to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String DIRECT_ACTION_ID_REMOTE_AUTOFILL = "android.REMOTE_AUTOFILL"; /** * Internal extra used to pass an {@link AutofillId} to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String EXTRA_REMOTE_AUTOFILL_ID = "android.view.autofill.extra.REMOTE_AUTOFILL_ID"; /** * Internal extra used to pass an {@link AutofillValue} to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String EXTRA_REMOTE_AUTOFILL_VALUE = "android.view.autofill.extra.REMOTE_AUTOFILL_VALUE"; /** * Autofill Hint to indicate that it can match any field. * Loading Loading @@ -3945,7 +3971,9 @@ public final class AutofillManager { pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')'); } pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly); pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled); Loading @@ -3958,7 +3986,9 @@ public final class AutofillManager { final String pfx2 = pfx + " "; pw.println(); pw.print(pfx2); pw.print("visible:"); pw.println(mTrackedViews.mVisibleTrackedIds); pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds); pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds); } pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds); pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds); Loading Loading @@ -4120,6 +4150,32 @@ public final class AutofillManager { return false; } /** * This method is used for a system component like SystemUI to autofill a remote app. * * @hide */ public void autofillRemoteApp( @NonNull AutofillId autofillId, @NonNull String value, @NonNull IBinder shareableActivityToken, int taskId) { if (android.view.contentcapture.flags.Flags.enableSystemUiUnderlay() && mService != null) { final AutofillValue autofillValue = AutofillValue.forText(value); try { mService.autofillRemoteApp( shareableActivityToken, taskId, autofillId, autofillValue, mContext.getUserId()); } catch (Exception e) { Log.e(TAG, "autofillRemoteApp() - cannot autofill remote app", e); } } } /** * If autofill suggestions for a * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI"> Loading core/java/android/view/autofill/IAutoFillManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,7 @@ oneway interface IAutoFillManager { void setAutofillIdsAttemptedForRefill(int sessionId, in List<AutofillId> ids, int userId); void notifyImeAnimationStart(int sessionId, long startTimeMs, int userId); void notifyImeAnimationEnd(int sessionId, long endTimeMs, int userId); // For SystemUI to notify AutofillManager that a remote fill has occurred. void autofillRemoteApp(IBinder activityToken, int taskId, in AutofillId id, in AutofillValue value, int userId); } core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import android.hardware.display.VirtualDisplay; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallback; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; Loading @@ -88,6 +89,10 @@ import android.util.MergedConfiguration; import android.view.Display; import android.view.Surface; import android.view.View; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.widget.EditText; import android.window.ActivityWindowInfo; import android.window.WindowContextInfo; import android.window.WindowTokenClientController; Loading Loading @@ -187,6 +192,33 @@ public class ActivityThreadTest { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @Test public void testPerformDirectAction_remoteAutofill() throws Exception { final TestActivity activity = mActivityTestRule.launchActivity(new Intent()); final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); EditText editText = activity.mEditText; AutofillId autofillId = editText.getAutofillId(); AutofillValue autofillValue = AutofillValue.forText("test"); Bundle bundle = new Bundle(); bundle.putParcelable(AutofillManager.EXTRA_REMOTE_AUTOFILL_ID, autofillId); bundle.putParcelable(AutofillManager.EXTRA_REMOTE_AUTOFILL_VALUE, autofillValue); final RemoteCallback remoteCallback = new RemoteCallback((unused) -> {}); appThread.performDirectAction( activity.getActivityToken(), AutofillManager.DIRECT_ACTION_ID_REMOTE_AUTOFILL, bundle, null, remoteCallback); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); assertEquals("test", editText.getText().toString()); } @Test public void testResumeAfterRelaunch() throws Exception { final Activity activity = mActivityTestRule.launchActivity(new Intent()); Loading Loading @@ -1269,12 +1301,16 @@ public class ActivityThreadTest { */ volatile CountDownLatch mPipUiStateLatch; private EditText mEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().getDecorView().setKeepScreenOn(true); setShowWhenLocked(true); setTurnScreenOn(true); mEditText = new EditText(this); setContentView(mEditText); } @Override Loading Loading
core/java/android/app/Activity.java +16 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.autofill.AutofillClientController; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager.AutofillClient; import android.view.autofill.AutofillValue; import android.view.contentcapture.ContentCaptureContext; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient; Loading Loading @@ -10197,4 +10198,19 @@ public class Activity extends ContextThemeWrapper mJankTracker.disableAppJankTracking(); } } final void autofillViewIfAvailable( @NonNull AutofillId targetAutofillId, @NonNull AutofillValue autofillValue) { if (false) Log.v(TAG, "autofill view in client app Activity, id: " + targetAutofillId); runOnUiThread( () -> { View view = getAutofillClientController() .autofillClientFindViewByAutofillIdTraversal(targetAutofillId); if (view != null) { // TODO: b/410146465 support virtual views view.autofill(autofillValue); } }); } }
core/java/android/app/ActivityThread.java +15 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,8 @@ import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.contentcapture.IContentCaptureManager; import android.view.contentcapture.IContentCaptureOptionsCallback; import android.view.translation.TranslationSpec; Loading Loading @@ -4723,6 +4725,19 @@ public final class ActivityThread extends ClientTransactionHandler resultCallback.sendResult(null); return; } if (actionId.equals(AutofillManager.DIRECT_ACTION_ID_REMOTE_AUTOFILL)) { AutofillId autofillId = arguments.getParcelable( AutofillManager.EXTRA_REMOTE_AUTOFILL_ID, AutofillId.class); AutofillValue autofillValue = arguments.getParcelable( AutofillManager.EXTRA_REMOTE_AUTOFILL_VALUE, AutofillValue.class); if (autofillId != null && autofillValue != null) { r.activity.autofillViewIfAvailable(autofillId, autofillValue); } } final Bundle nonNullArguments = (arguments != null) ? arguments : Bundle.EMPTY; r.activity.onPerformDirectAction(actionId, nonNullArguments, cancellationSignal, resultCallback::sendResult); Loading
core/java/android/view/autofill/AutofillManager.java +58 −2 Original line number Diff line number Diff line Loading @@ -318,6 +318,32 @@ public final class AutofillManager { public static final String EXTRA_AUTOFILL_REQUEST_ID = "android.view.autofill.extra.AUTOFILL_REQUEST_ID"; /** * Internal {@link DirectAction#getId()} used to pass to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String DIRECT_ACTION_ID_REMOTE_AUTOFILL = "android.REMOTE_AUTOFILL"; /** * Internal extra used to pass an {@link AutofillId} to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String EXTRA_REMOTE_AUTOFILL_ID = "android.view.autofill.extra.REMOTE_AUTOFILL_ID"; /** * Internal extra used to pass an {@link AutofillValue} to the {@link ActivityThread} to fill a * remote app. * * @hide */ public static final String EXTRA_REMOTE_AUTOFILL_VALUE = "android.view.autofill.extra.REMOTE_AUTOFILL_VALUE"; /** * Autofill Hint to indicate that it can match any field. * Loading Loading @@ -3945,7 +3971,9 @@ public final class AutofillManager { pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')'); } pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly); pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled); Loading @@ -3958,7 +3986,9 @@ public final class AutofillManager { final String pfx2 = pfx + " "; pw.println(); pw.print(pfx2); pw.print("visible:"); pw.println(mTrackedViews.mVisibleTrackedIds); pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds); pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds); } pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds); pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds); Loading Loading @@ -4120,6 +4150,32 @@ public final class AutofillManager { return false; } /** * This method is used for a system component like SystemUI to autofill a remote app. * * @hide */ public void autofillRemoteApp( @NonNull AutofillId autofillId, @NonNull String value, @NonNull IBinder shareableActivityToken, int taskId) { if (android.view.contentcapture.flags.Flags.enableSystemUiUnderlay() && mService != null) { final AutofillValue autofillValue = AutofillValue.forText(value); try { mService.autofillRemoteApp( shareableActivityToken, taskId, autofillId, autofillValue, mContext.getUserId()); } catch (Exception e) { Log.e(TAG, "autofillRemoteApp() - cannot autofill remote app", e); } } } /** * If autofill suggestions for a * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI"> Loading
core/java/android/view/autofill/IAutoFillManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,7 @@ oneway interface IAutoFillManager { void setAutofillIdsAttemptedForRefill(int sessionId, in List<AutofillId> ids, int userId); void notifyImeAnimationStart(int sessionId, long startTimeMs, int userId); void notifyImeAnimationEnd(int sessionId, long endTimeMs, int userId); // For SystemUI to notify AutofillManager that a remote fill has occurred. void autofillRemoteApp(IBinder activityToken, int taskId, in AutofillId id, in AutofillValue value, int userId); }
core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ import android.hardware.display.VirtualDisplay; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallback; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; Loading @@ -88,6 +89,10 @@ import android.util.MergedConfiguration; import android.view.Display; import android.view.Surface; import android.view.View; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.widget.EditText; import android.window.ActivityWindowInfo; import android.window.WindowContextInfo; import android.window.WindowTokenClientController; Loading Loading @@ -187,6 +192,33 @@ public class ActivityThreadTest { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @Test public void testPerformDirectAction_remoteAutofill() throws Exception { final TestActivity activity = mActivityTestRule.launchActivity(new Intent()); final IApplicationThread appThread = activity.getActivityThread().getApplicationThread(); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); EditText editText = activity.mEditText; AutofillId autofillId = editText.getAutofillId(); AutofillValue autofillValue = AutofillValue.forText("test"); Bundle bundle = new Bundle(); bundle.putParcelable(AutofillManager.EXTRA_REMOTE_AUTOFILL_ID, autofillId); bundle.putParcelable(AutofillManager.EXTRA_REMOTE_AUTOFILL_VALUE, autofillValue); final RemoteCallback remoteCallback = new RemoteCallback((unused) -> {}); appThread.performDirectAction( activity.getActivityToken(), AutofillManager.DIRECT_ACTION_ID_REMOTE_AUTOFILL, bundle, null, remoteCallback); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); assertEquals("test", editText.getText().toString()); } @Test public void testResumeAfterRelaunch() throws Exception { final Activity activity = mActivityTestRule.launchActivity(new Intent()); Loading Loading @@ -1269,12 +1301,16 @@ public class ActivityThreadTest { */ volatile CountDownLatch mPipUiStateLatch; private EditText mEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().getDecorView().setKeepScreenOn(true); setShowWhenLocked(true); setTurnScreenOn(true); mEditText = new EditText(this); setContentView(mEditText); } @Override Loading