Loading core/java/android/view/autofill/AutofillManager.java +25 −23 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.view.View; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.lang.annotation.Retention; Loading Loading @@ -428,7 +429,7 @@ public final class AutofillManager { * @hide */ public AutofillManager(Context context, IAutoFillManager service) { mContext = context; mContext = Preconditions.checkNotNull(context, "context cannot be null"); mService = service; } Loading Loading @@ -457,7 +458,7 @@ public final class AutofillManager { if (mSessionId != NO_SESSION) { ensureServiceClientAddedIfNeededLocked(); final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client != null) { try { final boolean sessionWasRestored = mService.restoreSession(mSessionId, Loading Loading @@ -1093,7 +1094,8 @@ public final class AutofillManager { } } private AutofillClient getClientLocked() { // Note: don't need to use locked suffix because mContext is final. private AutofillClient getClient() { final AutofillClient client = mContext.getAutofillClient(); if (client == null && sDebug) { Log.d(TAG, "No AutofillClient for " + mContext.getPackageName() + " on context " Loading Loading @@ -1156,16 +1158,16 @@ public final class AutofillManager { return; } try { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. mSessionId = mService.startSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, client.getComponentName()); if (mSessionId != NO_SESSION) { mState = STATE_ACTIVE; } if (client != null) { client.autofillCallbackResetableStateAvailable(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -1217,7 +1219,9 @@ public final class AutofillManager { try { if (restartIfNecessary) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. final int newId = mService.updateOrRestartSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, client.getComponentName(), mSessionId, action); Loading @@ -1225,10 +1229,8 @@ public final class AutofillManager { if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId); mSessionId = newId; mState = (mSessionId == NO_SESSION) ? STATE_UNKNOWN : STATE_ACTIVE; if (client != null) { client.autofillCallbackResetableStateAvailable(); } } } else { mService.updateSession(mSessionId, id, bounds, value, action, flags, mContext.getUserId()); Loading @@ -1240,7 +1242,7 @@ public final class AutofillManager { } private void ensureServiceClientAddedIfNeededLocked() { if (getClientLocked() == null) { if (getClient() == null) { return; } Loading Loading @@ -1323,7 +1325,7 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { if (mSessionId == sessionId) { AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (client != null) { if (client.autofillCallbackRequestShowFillUi(anchor, width, height, Loading @@ -1348,7 +1350,7 @@ public final class AutofillManager { Intent fillInIntent) { synchronized (mLock) { if (sessionId == mSessionId) { AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client != null) { client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); } Loading Loading @@ -1413,7 +1415,7 @@ public final class AutofillManager { return; } final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { return; } Loading Loading @@ -1590,7 +1592,7 @@ public final class AutofillManager { // 1. If local and remote session id are off sync the UI would be stuck shown // 2. There is a race between the user state being destroyed due the fill // service being uninstalled and the UI being dismissed. AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (client != null) { if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { callback = mCallback; Loading Loading @@ -1620,7 +1622,7 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { if (mSessionId == sessionId && getClientLocked() != null) { if (mSessionId == sessionId && getClient() != null) { callback = mCallback; } } Loading Loading @@ -1677,7 +1679,7 @@ public final class AutofillManager { * @return The view or {@code null} if view was not found */ private View findView(@NonNull AutofillId autofillId) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { return null; Loading Loading @@ -1711,7 +1713,7 @@ public final class AutofillManager { pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId); pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked()); pw.print(pfx); pw.print("context: "); pw.println(mContext); pw.print(pfx); pw.print("client: "); pw.println(getClientLocked()); pw.print(pfx); pw.print("client: "); pw.println(getClient()); pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); Loading Loading @@ -1758,7 +1760,7 @@ public final class AutofillManager { } private void post(Runnable runnable) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { if (sVerbose) Log.v(TAG, "ignoring post() because client is null"); return; Loading Loading @@ -1841,7 +1843,7 @@ public final class AutofillManager { * @param trackedIds The views to be tracked */ TrackedViews(@Nullable AutofillId[] trackedIds) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (trackedIds != null && client != null) { final boolean[] isVisible; Loading Loading @@ -1882,7 +1884,7 @@ public final class AutofillManager { * @param isVisible visible if the view is visible in the view hierarchy. */ void notifyViewVisibilityChanged(@NonNull AutofillId id, boolean isVisible) { AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (sDebug) { Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible=" Loading Loading @@ -1919,7 +1921,7 @@ public final class AutofillManager { void onVisibleForAutofillLocked() { // The visibility of the views might have changed while the client was not be visible, // hence update the visibility state for all views. AutofillClient client = getClientLocked(); AutofillClient client = getClient(); ArraySet<AutofillId> updatedVisibleTrackedIds = null; ArraySet<AutofillId> updatedInvisibleTrackedIds = null; if (client != null) { Loading proto/src/metrics_constants.proto +13 −0 Original line number Diff line number Diff line Loading @@ -4138,6 +4138,19 @@ message MetricsEvent { // OS: O FIELD_NOTIFICATION_GROUP_SUMMARY = 947; // An app attempted to forge a different component name in the AssisStructure that would be // passed to the autofill service. // OS: O (security patch) // Package: Real package of the app being autofilled // Tag FIELD_AUTOFILL_SERVICE: Package of the autofill service that processed the request // TAG FIELD_AUTOFILL_FORGED_COMPONENT_NAME: Component name being forged AUTOFILL_FORGED_COMPONENT_ATTEMPT = 948; // FIELD - The component that an app tried tro forged. // Type: string // OS: O (security patch) FIELD_AUTOFILL_FORGED_COMPONENT_NAME = 949; // ---- End O Constants, all O constants go above this line ---- // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera Loading services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +32 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.graphics.drawable.Drawable; Loading @@ -43,6 +44,7 @@ import android.os.Looper; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.service.autofill.AutofillService; Loading Loading @@ -465,6 +467,8 @@ final class AutofillManagerServiceImpl { sessionId = sRandom.nextInt(); } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0); assertCallerLocked(componentName); final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock, sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName); Loading @@ -473,6 +477,34 @@ final class AutofillManagerServiceImpl { return newSession; } /** * Asserts the component is owned by the caller. */ private void assertCallerLocked(@NonNull ComponentName componentName) { final PackageManager pm = mContext.getPackageManager(); final int callingUid = Binder.getCallingUid(); final int packageUid; try { packageUid = pm.getPackageUidAsUser(componentName.getPackageName(), UserHandle.getCallingUserId()); } catch (NameNotFoundException e) { throw new SecurityException("Could not verify UID for " + componentName); } if (callingUid != packageUid) { final String[] packages = pm.getPackagesForUid(callingUid); final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid + ") passed component (" + componentName + ") owned by UID " + packageUid); mMetricsLogger.write( Helper.newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT, callingPackage, getServicePackageName()) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME, componentName == null ? "null" : componentName.flattenToShortString())); throw new SecurityException("Invalid component: " + componentName); } } /** * Restores a session after an activity was temporarily destroyed. * Loading services/autofill/java/com/android/server/autofill/Session.java +8 −3 Original line number Diff line number Diff line Loading @@ -238,10 +238,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState structure.ensureData(); // Sanitize structure before it's sent to service. if (!mComponentName.equals(structure.getActivityComponent())) { final ComponentName componentNameFromApp = structure.getActivityComponent(); if (!mComponentName.equals(componentNameFromApp)) { Slog.w(TAG, "Activity " + mComponentName + " forged different component on " + "AssistStructure: " + structure.getActivityComponent()); + "AssistStructure: " + componentNameFromApp); structure.setActivityComponent(mComponentName); mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME, componentNameFromApp == null ? "null" : componentNameFromApp.flattenToShortString())); } structure.sanitizeForParceling(true); Loading Loading @@ -1706,7 +1711,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState break; case ACTION_VIEW_ENTERED: if (sVerbose && virtualBounds != null) { Slog.w(TAG, "entered on virtual child " + id + ": " + virtualBounds); Slog.v(TAG, "entered on virtual child " + id + ": " + virtualBounds); } requestNewFillResponseIfNecessaryLocked(id, viewState, flags); Loading Loading
core/java/android/view/autofill/AutofillManager.java +25 −23 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.view.View; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.lang.annotation.Retention; Loading Loading @@ -428,7 +429,7 @@ public final class AutofillManager { * @hide */ public AutofillManager(Context context, IAutoFillManager service) { mContext = context; mContext = Preconditions.checkNotNull(context, "context cannot be null"); mService = service; } Loading Loading @@ -457,7 +458,7 @@ public final class AutofillManager { if (mSessionId != NO_SESSION) { ensureServiceClientAddedIfNeededLocked(); final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client != null) { try { final boolean sessionWasRestored = mService.restoreSession(mSessionId, Loading Loading @@ -1093,7 +1094,8 @@ public final class AutofillManager { } } private AutofillClient getClientLocked() { // Note: don't need to use locked suffix because mContext is final. private AutofillClient getClient() { final AutofillClient client = mContext.getAutofillClient(); if (client == null && sDebug) { Log.d(TAG, "No AutofillClient for " + mContext.getPackageName() + " on context " Loading Loading @@ -1156,16 +1158,16 @@ public final class AutofillManager { return; } try { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. mSessionId = mService.startSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, client.getComponentName()); if (mSessionId != NO_SESSION) { mState = STATE_ACTIVE; } if (client != null) { client.autofillCallbackResetableStateAvailable(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -1217,7 +1219,9 @@ public final class AutofillManager { try { if (restartIfNecessary) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) return; // NOTE: getClient() already logd it.. final int newId = mService.updateOrRestartSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, client.getComponentName(), mSessionId, action); Loading @@ -1225,10 +1229,8 @@ public final class AutofillManager { if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId); mSessionId = newId; mState = (mSessionId == NO_SESSION) ? STATE_UNKNOWN : STATE_ACTIVE; if (client != null) { client.autofillCallbackResetableStateAvailable(); } } } else { mService.updateSession(mSessionId, id, bounds, value, action, flags, mContext.getUserId()); Loading @@ -1240,7 +1242,7 @@ public final class AutofillManager { } private void ensureServiceClientAddedIfNeededLocked() { if (getClientLocked() == null) { if (getClient() == null) { return; } Loading Loading @@ -1323,7 +1325,7 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { if (mSessionId == sessionId) { AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (client != null) { if (client.autofillCallbackRequestShowFillUi(anchor, width, height, Loading @@ -1348,7 +1350,7 @@ public final class AutofillManager { Intent fillInIntent) { synchronized (mLock) { if (sessionId == mSessionId) { AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client != null) { client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); } Loading Loading @@ -1413,7 +1415,7 @@ public final class AutofillManager { return; } final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { return; } Loading Loading @@ -1590,7 +1592,7 @@ public final class AutofillManager { // 1. If local and remote session id are off sync the UI would be stuck shown // 2. There is a race between the user state being destroyed due the fill // service being uninstalled and the UI being dismissed. AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (client != null) { if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { callback = mCallback; Loading Loading @@ -1620,7 +1622,7 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { if (mSessionId == sessionId && getClientLocked() != null) { if (mSessionId == sessionId && getClient() != null) { callback = mCallback; } } Loading Loading @@ -1677,7 +1679,7 @@ public final class AutofillManager { * @return The view or {@code null} if view was not found */ private View findView(@NonNull AutofillId autofillId) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { return null; Loading Loading @@ -1711,7 +1713,7 @@ public final class AutofillManager { pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId); pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked()); pw.print(pfx); pw.print("context: "); pw.println(mContext); pw.print(pfx); pw.print("client: "); pw.println(getClientLocked()); pw.print(pfx); pw.print("client: "); pw.println(getClient()); pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); Loading Loading @@ -1758,7 +1760,7 @@ public final class AutofillManager { } private void post(Runnable runnable) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (client == null) { if (sVerbose) Log.v(TAG, "ignoring post() because client is null"); return; Loading Loading @@ -1841,7 +1843,7 @@ public final class AutofillManager { * @param trackedIds The views to be tracked */ TrackedViews(@Nullable AutofillId[] trackedIds) { final AutofillClient client = getClientLocked(); final AutofillClient client = getClient(); if (trackedIds != null && client != null) { final boolean[] isVisible; Loading Loading @@ -1882,7 +1884,7 @@ public final class AutofillManager { * @param isVisible visible if the view is visible in the view hierarchy. */ void notifyViewVisibilityChanged(@NonNull AutofillId id, boolean isVisible) { AutofillClient client = getClientLocked(); AutofillClient client = getClient(); if (sDebug) { Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible=" Loading Loading @@ -1919,7 +1921,7 @@ public final class AutofillManager { void onVisibleForAutofillLocked() { // The visibility of the views might have changed while the client was not be visible, // hence update the visibility state for all views. AutofillClient client = getClientLocked(); AutofillClient client = getClient(); ArraySet<AutofillId> updatedVisibleTrackedIds = null; ArraySet<AutofillId> updatedInvisibleTrackedIds = null; if (client != null) { Loading
proto/src/metrics_constants.proto +13 −0 Original line number Diff line number Diff line Loading @@ -4138,6 +4138,19 @@ message MetricsEvent { // OS: O FIELD_NOTIFICATION_GROUP_SUMMARY = 947; // An app attempted to forge a different component name in the AssisStructure that would be // passed to the autofill service. // OS: O (security patch) // Package: Real package of the app being autofilled // Tag FIELD_AUTOFILL_SERVICE: Package of the autofill service that processed the request // TAG FIELD_AUTOFILL_FORGED_COMPONENT_NAME: Component name being forged AUTOFILL_FORGED_COMPONENT_ATTEMPT = 948; // FIELD - The component that an app tried tro forged. // Type: string // OS: O (security patch) FIELD_AUTOFILL_FORGED_COMPONENT_NAME = 949; // ---- End O Constants, all O constants go above this line ---- // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera Loading
services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +32 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.graphics.drawable.Drawable; Loading @@ -43,6 +44,7 @@ import android.os.Looper; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.service.autofill.AutofillService; Loading Loading @@ -465,6 +467,8 @@ final class AutofillManagerServiceImpl { sessionId = sRandom.nextInt(); } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0); assertCallerLocked(componentName); final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock, sessionId, uid, activityToken, appCallbackToken, hasCallback, mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName); Loading @@ -473,6 +477,34 @@ final class AutofillManagerServiceImpl { return newSession; } /** * Asserts the component is owned by the caller. */ private void assertCallerLocked(@NonNull ComponentName componentName) { final PackageManager pm = mContext.getPackageManager(); final int callingUid = Binder.getCallingUid(); final int packageUid; try { packageUid = pm.getPackageUidAsUser(componentName.getPackageName(), UserHandle.getCallingUserId()); } catch (NameNotFoundException e) { throw new SecurityException("Could not verify UID for " + componentName); } if (callingUid != packageUid) { final String[] packages = pm.getPackagesForUid(callingUid); final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid + ") passed component (" + componentName + ") owned by UID " + packageUid); mMetricsLogger.write( Helper.newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT, callingPackage, getServicePackageName()) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME, componentName == null ? "null" : componentName.flattenToShortString())); throw new SecurityException("Invalid component: " + componentName); } } /** * Restores a session after an activity was temporarily destroyed. * Loading
services/autofill/java/com/android/server/autofill/Session.java +8 −3 Original line number Diff line number Diff line Loading @@ -238,10 +238,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState structure.ensureData(); // Sanitize structure before it's sent to service. if (!mComponentName.equals(structure.getActivityComponent())) { final ComponentName componentNameFromApp = structure.getActivityComponent(); if (!mComponentName.equals(componentNameFromApp)) { Slog.w(TAG, "Activity " + mComponentName + " forged different component on " + "AssistStructure: " + structure.getActivityComponent()); + "AssistStructure: " + componentNameFromApp); structure.setActivityComponent(mComponentName); mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME, componentNameFromApp == null ? "null" : componentNameFromApp.flattenToShortString())); } structure.sanitizeForParceling(true); Loading Loading @@ -1706,7 +1711,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState break; case ACTION_VIEW_ENTERED: if (sVerbose && virtualBounds != null) { Slog.w(TAG, "entered on virtual child " + id + ": " + virtualBounds); Slog.v(TAG, "entered on virtual child " + id + ": " + virtualBounds); } requestNewFillResponseIfNecessaryLocked(id, viewState, flags); Loading