Loading services/autofill/java/com/android/server/autofill/RemoteFillService.java +44 −365 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import static com.android.server.autofill.Helper.sVerbose; Loading @@ -26,17 +25,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender; import android.content.ServiceConnection; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.ICancellationSignal; import android.os.ICancellationSignal; import android.os.IInterface; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.service.autofill.AutofillService; import android.service.autofill.AutofillService; import android.service.autofill.FillRequest; import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.FillResponse; Loading @@ -47,59 +40,17 @@ import android.service.autofill.SaveRequest; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.AbstractRemoteService; import com.android.server.FgThread; import java.io.PrintWriter; final class RemoteFillService extends AbstractRemoteService { import java.lang.ref.WeakReference; /** * This class represents a remote fill service. It abstracts away the binding * and unbinding from the remote implementation. * * <p>Clients can call methods of this class without worrying about when and * how to bind/unbind/timeout. All state of this class is modified on a handler * thread. */ final class RemoteFillService implements DeathRecipient { private static final String LOG_TAG = "RemoteFillService"; // How long after the last interaction with the service we would unbind private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; // How long after we make a remote request to a fill service we timeout private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final int MSG_UNBIND = 3; private final Context mContext; private final ComponentName mComponentName; private final Intent mIntent; private final FillServiceCallbacks mCallbacks; private final FillServiceCallbacks mCallbacks; private final int mUserId; private final ServiceConnection mServiceConnection = new RemoteServiceConnection(); private final Handler mHandler; private final boolean mBindInstantServiceAllowed; private IAutoFillService mAutoFillService; private IAutoFillService mAutoFillService; private boolean mBinding; public interface FillServiceCallbacks extends VultureCallback { private boolean mDestroyed; private boolean mServiceDied; private boolean mCompleted; private PendingRequest mPendingRequest; public interface FillServiceCallbacks { void onFillRequestSuccess(int requestId, @Nullable FillResponse response, void onFillRequestSuccess(int requestId, @Nullable FillResponse response, @NonNull String servicePackageName, int requestFlags); @NonNull String servicePackageName, int requestFlags); void onFillRequestFailure(int requestId, @Nullable CharSequence message); void onFillRequestFailure(int requestId, @Nullable CharSequence message); Loading @@ -109,48 +60,42 @@ final class RemoteFillService implements DeathRecipient { // TODO(b/80093094): add timeout here too? // TODO(b/80093094): add timeout here too? void onSaveRequestFailure(@Nullable CharSequence message, void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); @NonNull String servicePackageName); void onServiceDied(RemoteFillService service); } } public RemoteFillService(Context context, ComponentName componentName, RemoteFillService(Context context, ComponentName componentName, int userId, int userId, FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { mContext = context; super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks, bindInstantServiceAllowed, sVerbose); mCallbacks = callbacks; mCallbacks = callbacks; mComponentName = componentName; mIntent = new Intent(AutofillService.SERVICE_INTERFACE).setComponent(mComponentName); mUserId = userId; mHandler = new Handler(FgThread.getHandler().getLooper()); mBindInstantServiceAllowed = bindInstantServiceAllowed; } } public void destroy() { @Override mHandler.sendMessage(obtainMessage(RemoteFillService::handleDestroy, this)); protected void onConnectedStateChanged(boolean state) { if (mAutoFillService == null) { Slog.w(mTag, "onConnectedStateChanged(): null service"); return; } } try { private void handleDestroy() { mAutoFillService.onConnectedStateChanged(state); if (checkIfDestroyed()) return; } catch (Exception e) { if (mPendingRequest != null) { Slog.w(mTag, "Exception calling onConnectedStateChanged(): " + e); mPendingRequest.cancel(); mPendingRequest = null; } } ensureUnbound(); mDestroyed = true; } } @Override @Override public void binderDied() { protected IInterface getServiceInterface(IBinder service) { mHandler.sendMessage(obtainMessage( mAutoFillService = IAutoFillService.Stub.asInterface(service); RemoteFillService::handleBinderDied, this)); return mAutoFillService; } } private void handleBinderDied() { @Override if (checkIfDestroyed()) return; protected long getTimeoutIdleBindMillis() { if (mAutoFillService != null) { return TIMEOUT_IDLE_BIND_MILLIS; mAutoFillService.asBinder().unlinkToDeath(this, 0); } } mAutoFillService = null; mServiceDied = true; @Override mCallbacks.onServiceDied(this); protected long getRemoteRequestMillis() { return TIMEOUT_REMOTE_REQUEST_MILLIS; } } /** /** Loading @@ -162,8 +107,9 @@ final class RemoteFillService implements DeathRecipient { * @return the id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if no * @return the id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if no * {@link PendingFillRequest} was canceled. * {@link PendingFillRequest} was canceled. */ */ // TODO(b/117779333): move this logic to super class (and make mPendingRequest private) public int cancelCurrentRequest() { public int cancelCurrentRequest() { if (mDestroyed) { if (isDestroyed()) { return INVALID_REQUEST_ID; return INVALID_REQUEST_ID; } } Loading @@ -190,118 +136,6 @@ final class RemoteFillService implements DeathRecipient { scheduleRequest(new PendingSaveRequest(request, this)); scheduleRequest(new PendingSaveRequest(request, this)); } } private void scheduleRequest(PendingRequest pendingRequest) { mHandler.sendMessage(obtainMessage( RemoteFillService::handlePendingRequest, this, pendingRequest)); } // Note: we are dumping without a lock held so this is a bit racy but // adding a lock to a class that offloads to a handler thread would // mean adding a lock adding overhead to normal runtime operation. public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { String tab = " "; pw.append(prefix).append("service:").println(); pw.append(prefix).append(tab).append("userId=") .append(String.valueOf(mUserId)).println(); pw.append(prefix).append(tab).append("componentName=") .append(mComponentName.flattenToString()).println(); pw.append(prefix).append(tab).append("destroyed=") .append(String.valueOf(mDestroyed)).println(); pw.append(prefix).append(tab).append("bound=") .append(String.valueOf(isBound())).println(); pw.append(prefix).append(tab).append("hasPendingRequest=") .append(String.valueOf(mPendingRequest != null)).println(); pw.append(prefix).append("mBindInstantServiceAllowed=").println(mBindInstantServiceAllowed); pw.println(); } private void cancelScheduledUnbind() { mHandler.removeMessages(MSG_UNBIND); } private void scheduleUnbind() { cancelScheduledUnbind(); mHandler.sendMessageDelayed( obtainMessage(RemoteFillService::handleUnbind, this) .setWhat(MSG_UNBIND), TIMEOUT_IDLE_BIND_MILLIS); } private void handleUnbind() { if (checkIfDestroyed()) return; ensureUnbound(); } private void handlePendingRequest(PendingRequest pendingRequest) { if (checkIfDestroyed()) return; if (mCompleted) { return; } if (!isBound()) { if (mPendingRequest != null) { mPendingRequest.cancel(); } mPendingRequest = pendingRequest; ensureBound(); } else { if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()"); pendingRequest.run(); if (pendingRequest.isFinal()) { mCompleted = true; } } } private boolean isBound() { return mAutoFillService != null; } private void ensureBound() { if (isBound() || mBinding) { return; } if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureBound()"); mBinding = true; int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; if (mBindInstantServiceAllowed) { flags |= Context.BIND_ALLOW_INSTANT; } final boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, new UserHandle(mUserId)); if (!willBind) { Slog.w(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent + " using flags " + flags); mBinding = false; if (!mServiceDied) { handleBinderDied(); } } } private void ensureUnbound() { if (!isBound() && !mBinding) { return; } if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()"); mBinding = false; if (isBound()) { try { mAutoFillService.onConnectedStateChanged(false); } catch (Exception e) { Slog.w(LOG_TAG, "Exception calling onDisconnected(): " + e); } if (mAutoFillService != null) { mAutoFillService.asBinder().unlinkToDeath(this, 0); mAutoFillService = null; } } mContext.unbindService(mServiceConnection); } private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, @Nullable FillResponse response, int requestFlags) { @Nullable FillResponse response, int requestFlags) { mHandler.post(() -> { mHandler.post(() -> { Loading Loading @@ -334,12 +168,12 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellationSignal.cancel(); cancellationSignal.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.w(LOG_TAG, "Error calling cancellation signal: " + e); Slog.w(mTag, "Error calling cancellation signal: " + e); } } }); }); } } private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest, private void dispatchOnSaveRequestSuccess(PendingSaveRequest pendingRequest, IntentSender intentSender) { IntentSender intentSender) { mHandler.post(() -> { mHandler.post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { if (handleResponseCallbackCommon(pendingRequest)) { Loading @@ -348,7 +182,7 @@ final class RemoteFillService implements DeathRecipient { }); }); } } private void dispatchOnSaveRequestFailure(PendingRequest pendingRequest, private void dispatchOnSaveRequestFailure(PendingSaveRequest pendingRequest, @Nullable CharSequence message) { @Nullable CharSequence message) { mHandler.post(() -> { mHandler.post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { if (handleResponseCallbackCommon(pendingRequest)) { Loading @@ -357,162 +191,7 @@ final class RemoteFillService implements DeathRecipient { }); }); } } private boolean handleResponseCallbackCommon(PendingRequest pendingRequest) { private static final class PendingFillRequest extends PendingRequest<RemoteFillService> { if (mDestroyed) { return false; } if (mPendingRequest == pendingRequest) { mPendingRequest = null; } if (mPendingRequest == null) { scheduleUnbind(); } return true; } private class RemoteServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (mDestroyed || !mBinding) { // This is abnormal. Unbinding the connection has been requested already. Slog.wtf(LOG_TAG, "onServiceConnected was dispatched after unbindService."); return; } mBinding = false; mAutoFillService = IAutoFillService.Stub.asInterface(service); try { service.linkToDeath(RemoteFillService.this, 0); } catch (RemoteException re) { handleBinderDied(); return; } try { mAutoFillService.onConnectedStateChanged(true); } catch (RemoteException e) { Slog.w(LOG_TAG, "Exception calling onConnected(): " + e); } if (mPendingRequest != null) { PendingRequest pendingRequest = mPendingRequest; mPendingRequest = null; handlePendingRequest(pendingRequest); } mServiceDied = false; } @Override public void onServiceDisconnected(ComponentName name) { mBinding = true; mAutoFillService = null; } } private boolean checkIfDestroyed() { if (mDestroyed) { if (sVerbose) { Slog.v(LOG_TAG, "Not handling operation as service for " + mComponentName + " is already destroyed"); } } return mDestroyed; } private static abstract class PendingRequest implements Runnable { protected final Object mLock = new Object(); private final WeakReference<RemoteFillService> mWeakService; private final Runnable mTimeoutTrigger; private final Handler mServiceHandler; @GuardedBy("mLock") private boolean mCancelled; @GuardedBy("mLock") private boolean mCompleted; PendingRequest(RemoteFillService service) { mWeakService = new WeakReference<>(service); mServiceHandler = service.mHandler; mTimeoutTrigger = () -> { synchronized (mLock) { if (mCancelled) { return; } mCompleted = true; } Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out"); final RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out after " + TIMEOUT_REMOTE_REQUEST_MILLIS + " ms"); onTimeout(remoteService); } }; mServiceHandler.postAtTime(mTimeoutTrigger, SystemClock.uptimeMillis() + TIMEOUT_REMOTE_REQUEST_MILLIS); } protected RemoteFillService getService() { return mWeakService.get(); } /** * Sub-classes must call this method when the remote service finishes, i.e., when it * called {@code onFill...} or {@code onSave...}. * * @return {@code false} in the service is already finished, {@code true} otherwise. */ protected final boolean finish() { synchronized (mLock) { if (mCompleted || mCancelled) { return false; } mCompleted = true; } mServiceHandler.removeCallbacks(mTimeoutTrigger); return true; } @GuardedBy("mLock") protected boolean isCancelledLocked() { return mCancelled; } /** * Cancels the service. * * @return {@code false} if service is already canceled, {@code true} otherwise. */ boolean cancel() { synchronized (mLock) { if (mCancelled || mCompleted) { return false; } mCancelled = true; } mServiceHandler.removeCallbacks(mTimeoutTrigger); return true; } /** * Called by the self-destructure timeout when the AutofilllService didn't reply to the * request on time. */ abstract void onTimeout(RemoteFillService remoteService); /** * @return whether this request leads to a final state where no * other requests can be made. */ boolean isFinal() { return false; } } private static final class PendingFillRequest extends PendingRequest { private final FillRequest mRequest; private final FillRequest mRequest; private final IFillCallback mCallback; private final IFillCallback mCallback; private ICancellationSignal mCancellation; private ICancellationSignal mCancellation; Loading @@ -534,7 +213,7 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellation.cancel(); cancellation.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error requesting a cancellation", e); Slog.e(mTag, "Error requesting a cancellation", e); } } } } } } Loading Loading @@ -565,7 +244,7 @@ final class RemoteFillService implements DeathRecipient { } } @Override @Override void onTimeout(RemoteFillService remoteService) { protected void onTimeout(RemoteFillService remoteService) { // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is // handled by the service, which could block. // handled by the service, which could block. final ICancellationSignal cancellation; final ICancellationSignal cancellation; Loading @@ -582,17 +261,17 @@ final class RemoteFillService implements DeathRecipient { public void run() { public void run() { synchronized (mLock) { synchronized (mLock) { if (isCancelledLocked()) { if (isCancelledLocked()) { if (sDebug) Slog.d(LOG_TAG, "run() called after canceled: " + mRequest); if (sDebug) Slog.d(mTag, "run() called after canceled: " + mRequest); return; return; } } } } final RemoteFillService remoteService = getService(); final RemoteFillService remoteService = getService(); if (remoteService != null) { if (remoteService != null) { if (sVerbose) Slog.v(LOG_TAG, "calling onFillRequest() for id=" + mRequest.getId()); if (sVerbose) Slog.v(mTag, "calling onFillRequest() for id=" + mRequest.getId()); try { try { remoteService.mAutoFillService.onFillRequest(mRequest, mCallback); remoteService.mAutoFillService.onFillRequest(mRequest, mCallback); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on fill request", e); Slog.e(mTag, "Error calling on fill request", e); remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); } } Loading @@ -611,14 +290,14 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellation.cancel(); cancellation.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error cancelling a fill request", e); Slog.e(mTag, "Error cancelling a fill request", e); } } } } return true; return true; } } } } private static final class PendingSaveRequest extends PendingRequest { private static final class PendingSaveRequest extends PendingRequest<RemoteFillService> { private final SaveRequest mRequest; private final SaveRequest mRequest; private final ISaveCallback mCallback; private final ISaveCallback mCallback; Loading Loading @@ -653,7 +332,7 @@ final class RemoteFillService implements DeathRecipient { } } @Override @Override void onTimeout(RemoteFillService remoteService) { protected void onTimeout(RemoteFillService remoteService) { remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } } Loading @@ -661,11 +340,11 @@ final class RemoteFillService implements DeathRecipient { public void run() { public void run() { final RemoteFillService remoteService = getService(); final RemoteFillService remoteService = getService(); if (remoteService != null) { if (remoteService != null) { if (sVerbose) Slog.v(LOG_TAG, "calling onSaveRequest()"); if (sVerbose) Slog.v(mTag, "calling onSaveRequest()"); try { try { remoteService.mAutoFillService.onSaveRequest(mRequest, mCallback); remoteService.mAutoFillService.onSaveRequest(mRequest, mCallback); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on save request", e); Slog.e(mTag, "Error calling on save request", e); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } } Loading services/autofill/java/com/android/server/autofill/Session.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -92,6 +92,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils; import com.android.server.AbstractRemoteService; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.autofill.ui.PendingUi; import com.android.server.autofill.ui.PendingUi; Loading Loading @@ -901,9 +902,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState this, authenticationId, intent, fillInIntent)); this, authenticationId, intent, fillInIntent)); } } // FillServiceCallbacks // VultureCallback @Override @Override public void onServiceDied(RemoteFillService service) { public void onServiceDied(AbstractRemoteService service) { Slog.w(TAG, "removing session because service died"); Slog.w(TAG, "removing session because service died"); forceRemoveSelfLocked(); forceRemoveSelfLocked(); } } Loading services/core/java/com/android/server/AbstractRemoteService.java 0 → 100644 +442 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
services/autofill/java/com/android/server/autofill/RemoteFillService.java +44 −365 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import static com.android.server.autofill.Helper.sVerbose; Loading @@ -26,17 +25,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender; import android.content.ServiceConnection; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.ICancellationSignal; import android.os.ICancellationSignal; import android.os.IInterface; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.service.autofill.AutofillService; import android.service.autofill.AutofillService; import android.service.autofill.FillRequest; import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.FillResponse; Loading @@ -47,59 +40,17 @@ import android.service.autofill.SaveRequest; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.AbstractRemoteService; import com.android.server.FgThread; import java.io.PrintWriter; final class RemoteFillService extends AbstractRemoteService { import java.lang.ref.WeakReference; /** * This class represents a remote fill service. It abstracts away the binding * and unbinding from the remote implementation. * * <p>Clients can call methods of this class without worrying about when and * how to bind/unbind/timeout. All state of this class is modified on a handler * thread. */ final class RemoteFillService implements DeathRecipient { private static final String LOG_TAG = "RemoteFillService"; // How long after the last interaction with the service we would unbind private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; // How long after we make a remote request to a fill service we timeout private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final int MSG_UNBIND = 3; private final Context mContext; private final ComponentName mComponentName; private final Intent mIntent; private final FillServiceCallbacks mCallbacks; private final FillServiceCallbacks mCallbacks; private final int mUserId; private final ServiceConnection mServiceConnection = new RemoteServiceConnection(); private final Handler mHandler; private final boolean mBindInstantServiceAllowed; private IAutoFillService mAutoFillService; private IAutoFillService mAutoFillService; private boolean mBinding; public interface FillServiceCallbacks extends VultureCallback { private boolean mDestroyed; private boolean mServiceDied; private boolean mCompleted; private PendingRequest mPendingRequest; public interface FillServiceCallbacks { void onFillRequestSuccess(int requestId, @Nullable FillResponse response, void onFillRequestSuccess(int requestId, @Nullable FillResponse response, @NonNull String servicePackageName, int requestFlags); @NonNull String servicePackageName, int requestFlags); void onFillRequestFailure(int requestId, @Nullable CharSequence message); void onFillRequestFailure(int requestId, @Nullable CharSequence message); Loading @@ -109,48 +60,42 @@ final class RemoteFillService implements DeathRecipient { // TODO(b/80093094): add timeout here too? // TODO(b/80093094): add timeout here too? void onSaveRequestFailure(@Nullable CharSequence message, void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); @NonNull String servicePackageName); void onServiceDied(RemoteFillService service); } } public RemoteFillService(Context context, ComponentName componentName, RemoteFillService(Context context, ComponentName componentName, int userId, int userId, FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { mContext = context; super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks, bindInstantServiceAllowed, sVerbose); mCallbacks = callbacks; mCallbacks = callbacks; mComponentName = componentName; mIntent = new Intent(AutofillService.SERVICE_INTERFACE).setComponent(mComponentName); mUserId = userId; mHandler = new Handler(FgThread.getHandler().getLooper()); mBindInstantServiceAllowed = bindInstantServiceAllowed; } } public void destroy() { @Override mHandler.sendMessage(obtainMessage(RemoteFillService::handleDestroy, this)); protected void onConnectedStateChanged(boolean state) { if (mAutoFillService == null) { Slog.w(mTag, "onConnectedStateChanged(): null service"); return; } } try { private void handleDestroy() { mAutoFillService.onConnectedStateChanged(state); if (checkIfDestroyed()) return; } catch (Exception e) { if (mPendingRequest != null) { Slog.w(mTag, "Exception calling onConnectedStateChanged(): " + e); mPendingRequest.cancel(); mPendingRequest = null; } } ensureUnbound(); mDestroyed = true; } } @Override @Override public void binderDied() { protected IInterface getServiceInterface(IBinder service) { mHandler.sendMessage(obtainMessage( mAutoFillService = IAutoFillService.Stub.asInterface(service); RemoteFillService::handleBinderDied, this)); return mAutoFillService; } } private void handleBinderDied() { @Override if (checkIfDestroyed()) return; protected long getTimeoutIdleBindMillis() { if (mAutoFillService != null) { return TIMEOUT_IDLE_BIND_MILLIS; mAutoFillService.asBinder().unlinkToDeath(this, 0); } } mAutoFillService = null; mServiceDied = true; @Override mCallbacks.onServiceDied(this); protected long getRemoteRequestMillis() { return TIMEOUT_REMOTE_REQUEST_MILLIS; } } /** /** Loading @@ -162,8 +107,9 @@ final class RemoteFillService implements DeathRecipient { * @return the id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if no * @return the id of the canceled request, or {@link FillRequest#INVALID_REQUEST_ID} if no * {@link PendingFillRequest} was canceled. * {@link PendingFillRequest} was canceled. */ */ // TODO(b/117779333): move this logic to super class (and make mPendingRequest private) public int cancelCurrentRequest() { public int cancelCurrentRequest() { if (mDestroyed) { if (isDestroyed()) { return INVALID_REQUEST_ID; return INVALID_REQUEST_ID; } } Loading @@ -190,118 +136,6 @@ final class RemoteFillService implements DeathRecipient { scheduleRequest(new PendingSaveRequest(request, this)); scheduleRequest(new PendingSaveRequest(request, this)); } } private void scheduleRequest(PendingRequest pendingRequest) { mHandler.sendMessage(obtainMessage( RemoteFillService::handlePendingRequest, this, pendingRequest)); } // Note: we are dumping without a lock held so this is a bit racy but // adding a lock to a class that offloads to a handler thread would // mean adding a lock adding overhead to normal runtime operation. public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { String tab = " "; pw.append(prefix).append("service:").println(); pw.append(prefix).append(tab).append("userId=") .append(String.valueOf(mUserId)).println(); pw.append(prefix).append(tab).append("componentName=") .append(mComponentName.flattenToString()).println(); pw.append(prefix).append(tab).append("destroyed=") .append(String.valueOf(mDestroyed)).println(); pw.append(prefix).append(tab).append("bound=") .append(String.valueOf(isBound())).println(); pw.append(prefix).append(tab).append("hasPendingRequest=") .append(String.valueOf(mPendingRequest != null)).println(); pw.append(prefix).append("mBindInstantServiceAllowed=").println(mBindInstantServiceAllowed); pw.println(); } private void cancelScheduledUnbind() { mHandler.removeMessages(MSG_UNBIND); } private void scheduleUnbind() { cancelScheduledUnbind(); mHandler.sendMessageDelayed( obtainMessage(RemoteFillService::handleUnbind, this) .setWhat(MSG_UNBIND), TIMEOUT_IDLE_BIND_MILLIS); } private void handleUnbind() { if (checkIfDestroyed()) return; ensureUnbound(); } private void handlePendingRequest(PendingRequest pendingRequest) { if (checkIfDestroyed()) return; if (mCompleted) { return; } if (!isBound()) { if (mPendingRequest != null) { mPendingRequest.cancel(); } mPendingRequest = pendingRequest; ensureBound(); } else { if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()"); pendingRequest.run(); if (pendingRequest.isFinal()) { mCompleted = true; } } } private boolean isBound() { return mAutoFillService != null; } private void ensureBound() { if (isBound() || mBinding) { return; } if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureBound()"); mBinding = true; int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; if (mBindInstantServiceAllowed) { flags |= Context.BIND_ALLOW_INSTANT; } final boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, new UserHandle(mUserId)); if (!willBind) { Slog.w(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent + " using flags " + flags); mBinding = false; if (!mServiceDied) { handleBinderDied(); } } } private void ensureUnbound() { if (!isBound() && !mBinding) { return; } if (sVerbose) Slog.v(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()"); mBinding = false; if (isBound()) { try { mAutoFillService.onConnectedStateChanged(false); } catch (Exception e) { Slog.w(LOG_TAG, "Exception calling onDisconnected(): " + e); } if (mAutoFillService != null) { mAutoFillService.asBinder().unlinkToDeath(this, 0); mAutoFillService = null; } } mContext.unbindService(mServiceConnection); } private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, @Nullable FillResponse response, int requestFlags) { @Nullable FillResponse response, int requestFlags) { mHandler.post(() -> { mHandler.post(() -> { Loading Loading @@ -334,12 +168,12 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellationSignal.cancel(); cancellationSignal.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.w(LOG_TAG, "Error calling cancellation signal: " + e); Slog.w(mTag, "Error calling cancellation signal: " + e); } } }); }); } } private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest, private void dispatchOnSaveRequestSuccess(PendingSaveRequest pendingRequest, IntentSender intentSender) { IntentSender intentSender) { mHandler.post(() -> { mHandler.post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { if (handleResponseCallbackCommon(pendingRequest)) { Loading @@ -348,7 +182,7 @@ final class RemoteFillService implements DeathRecipient { }); }); } } private void dispatchOnSaveRequestFailure(PendingRequest pendingRequest, private void dispatchOnSaveRequestFailure(PendingSaveRequest pendingRequest, @Nullable CharSequence message) { @Nullable CharSequence message) { mHandler.post(() -> { mHandler.post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { if (handleResponseCallbackCommon(pendingRequest)) { Loading @@ -357,162 +191,7 @@ final class RemoteFillService implements DeathRecipient { }); }); } } private boolean handleResponseCallbackCommon(PendingRequest pendingRequest) { private static final class PendingFillRequest extends PendingRequest<RemoteFillService> { if (mDestroyed) { return false; } if (mPendingRequest == pendingRequest) { mPendingRequest = null; } if (mPendingRequest == null) { scheduleUnbind(); } return true; } private class RemoteServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (mDestroyed || !mBinding) { // This is abnormal. Unbinding the connection has been requested already. Slog.wtf(LOG_TAG, "onServiceConnected was dispatched after unbindService."); return; } mBinding = false; mAutoFillService = IAutoFillService.Stub.asInterface(service); try { service.linkToDeath(RemoteFillService.this, 0); } catch (RemoteException re) { handleBinderDied(); return; } try { mAutoFillService.onConnectedStateChanged(true); } catch (RemoteException e) { Slog.w(LOG_TAG, "Exception calling onConnected(): " + e); } if (mPendingRequest != null) { PendingRequest pendingRequest = mPendingRequest; mPendingRequest = null; handlePendingRequest(pendingRequest); } mServiceDied = false; } @Override public void onServiceDisconnected(ComponentName name) { mBinding = true; mAutoFillService = null; } } private boolean checkIfDestroyed() { if (mDestroyed) { if (sVerbose) { Slog.v(LOG_TAG, "Not handling operation as service for " + mComponentName + " is already destroyed"); } } return mDestroyed; } private static abstract class PendingRequest implements Runnable { protected final Object mLock = new Object(); private final WeakReference<RemoteFillService> mWeakService; private final Runnable mTimeoutTrigger; private final Handler mServiceHandler; @GuardedBy("mLock") private boolean mCancelled; @GuardedBy("mLock") private boolean mCompleted; PendingRequest(RemoteFillService service) { mWeakService = new WeakReference<>(service); mServiceHandler = service.mHandler; mTimeoutTrigger = () -> { synchronized (mLock) { if (mCancelled) { return; } mCompleted = true; } Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out"); final RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out after " + TIMEOUT_REMOTE_REQUEST_MILLIS + " ms"); onTimeout(remoteService); } }; mServiceHandler.postAtTime(mTimeoutTrigger, SystemClock.uptimeMillis() + TIMEOUT_REMOTE_REQUEST_MILLIS); } protected RemoteFillService getService() { return mWeakService.get(); } /** * Sub-classes must call this method when the remote service finishes, i.e., when it * called {@code onFill...} or {@code onSave...}. * * @return {@code false} in the service is already finished, {@code true} otherwise. */ protected final boolean finish() { synchronized (mLock) { if (mCompleted || mCancelled) { return false; } mCompleted = true; } mServiceHandler.removeCallbacks(mTimeoutTrigger); return true; } @GuardedBy("mLock") protected boolean isCancelledLocked() { return mCancelled; } /** * Cancels the service. * * @return {@code false} if service is already canceled, {@code true} otherwise. */ boolean cancel() { synchronized (mLock) { if (mCancelled || mCompleted) { return false; } mCancelled = true; } mServiceHandler.removeCallbacks(mTimeoutTrigger); return true; } /** * Called by the self-destructure timeout when the AutofilllService didn't reply to the * request on time. */ abstract void onTimeout(RemoteFillService remoteService); /** * @return whether this request leads to a final state where no * other requests can be made. */ boolean isFinal() { return false; } } private static final class PendingFillRequest extends PendingRequest { private final FillRequest mRequest; private final FillRequest mRequest; private final IFillCallback mCallback; private final IFillCallback mCallback; private ICancellationSignal mCancellation; private ICancellationSignal mCancellation; Loading @@ -534,7 +213,7 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellation.cancel(); cancellation.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error requesting a cancellation", e); Slog.e(mTag, "Error requesting a cancellation", e); } } } } } } Loading Loading @@ -565,7 +244,7 @@ final class RemoteFillService implements DeathRecipient { } } @Override @Override void onTimeout(RemoteFillService remoteService) { protected void onTimeout(RemoteFillService remoteService) { // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is // handled by the service, which could block. // handled by the service, which could block. final ICancellationSignal cancellation; final ICancellationSignal cancellation; Loading @@ -582,17 +261,17 @@ final class RemoteFillService implements DeathRecipient { public void run() { public void run() { synchronized (mLock) { synchronized (mLock) { if (isCancelledLocked()) { if (isCancelledLocked()) { if (sDebug) Slog.d(LOG_TAG, "run() called after canceled: " + mRequest); if (sDebug) Slog.d(mTag, "run() called after canceled: " + mRequest); return; return; } } } } final RemoteFillService remoteService = getService(); final RemoteFillService remoteService = getService(); if (remoteService != null) { if (remoteService != null) { if (sVerbose) Slog.v(LOG_TAG, "calling onFillRequest() for id=" + mRequest.getId()); if (sVerbose) Slog.v(mTag, "calling onFillRequest() for id=" + mRequest.getId()); try { try { remoteService.mAutoFillService.onFillRequest(mRequest, mCallback); remoteService.mAutoFillService.onFillRequest(mRequest, mCallback); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on fill request", e); Slog.e(mTag, "Error calling on fill request", e); remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); } } Loading @@ -611,14 +290,14 @@ final class RemoteFillService implements DeathRecipient { try { try { cancellation.cancel(); cancellation.cancel(); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error cancelling a fill request", e); Slog.e(mTag, "Error cancelling a fill request", e); } } } } return true; return true; } } } } private static final class PendingSaveRequest extends PendingRequest { private static final class PendingSaveRequest extends PendingRequest<RemoteFillService> { private final SaveRequest mRequest; private final SaveRequest mRequest; private final ISaveCallback mCallback; private final ISaveCallback mCallback; Loading Loading @@ -653,7 +332,7 @@ final class RemoteFillService implements DeathRecipient { } } @Override @Override void onTimeout(RemoteFillService remoteService) { protected void onTimeout(RemoteFillService remoteService) { remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } } Loading @@ -661,11 +340,11 @@ final class RemoteFillService implements DeathRecipient { public void run() { public void run() { final RemoteFillService remoteService = getService(); final RemoteFillService remoteService = getService(); if (remoteService != null) { if (remoteService != null) { if (sVerbose) Slog.v(LOG_TAG, "calling onSaveRequest()"); if (sVerbose) Slog.v(mTag, "calling onSaveRequest()"); try { try { remoteService.mAutoFillService.onSaveRequest(mRequest, mCallback); remoteService.mAutoFillService.onSaveRequest(mRequest, mCallback); } catch (RemoteException e) { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on save request", e); Slog.e(mTag, "Error calling on save request", e); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } } Loading
services/autofill/java/com/android/server/autofill/Session.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -92,6 +92,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils; import com.android.server.AbstractRemoteService; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.autofill.ui.AutoFillUI; import com.android.server.autofill.ui.PendingUi; import com.android.server.autofill.ui.PendingUi; Loading Loading @@ -901,9 +902,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState this, authenticationId, intent, fillInIntent)); this, authenticationId, intent, fillInIntent)); } } // FillServiceCallbacks // VultureCallback @Override @Override public void onServiceDied(RemoteFillService service) { public void onServiceDied(AbstractRemoteService service) { Slog.w(TAG, "removing session because service died"); Slog.w(TAG, "removing session because service died"); forceRemoveSelfLocked(); forceRemoveSelfLocked(); } } Loading
services/core/java/com/android/server/AbstractRemoteService.java 0 → 100644 +442 −0 File added.Preview size limit exceeded, changes collapsed. Show changes