Loading services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +89 −2 Original line number Diff line number Diff line Loading @@ -19,17 +19,21 @@ package com.android.server.autofill; import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.NO_SESSION; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.IActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; Loading @@ -46,6 +50,7 @@ import android.service.autofill.FillEventHistory.Event; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.ArrayMap; import android.util.LocalLog; import android.util.Slog; import android.util.SparseArray; Loading @@ -72,6 +77,9 @@ final class AutofillManagerServiceImpl { private static final String TAG = "AutofillManagerServiceImpl"; private static final int MAX_SESSION_ID_CREATE_TRIES = 2048; /** Minimum interval to prune abandoned sessions */ private static final int MAX_ABANDONED_SESSION_MILLIS = 30000; static final int MSG_SERVICE_SAVE = 1; private final int mUserId; Loading Loading @@ -104,10 +112,10 @@ final class AutofillManagerServiceImpl { mHandlerCallback, true); /** * Cache of pending {@link Session}s, keyed by {@code activityToken}. * Cache of pending {@link Session}s, keyed by sessionId. * * <p>They're kept until the {@link AutofillService} finished handling a request, an error * occurs, or the session times out. * occurs, or the session is abandoned. */ @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); Loading @@ -116,6 +124,9 @@ final class AutofillManagerServiceImpl { @GuardedBy("mLock") private FillEventHistory mEventHistory; /** When was {@link PruneTask} last executed? */ private long mLastPrune = 0; AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory, int userId, AutoFillUI ui, boolean disabled) { mContext = context; Loading Loading @@ -260,6 +271,9 @@ final class AutofillManagerServiceImpl { return 0; } // Occasionally clean up abandoned sessions pruneAbandonedSessionsLocked(); final Session newSession = createSessionByTokenLocked(activityToken, uid, windowToken, appCallbackToken, hasCallback, flags, packageName); if (newSession == null) { Loading @@ -277,6 +291,20 @@ final class AutofillManagerServiceImpl { return newSession.id; } /** * Remove abandoned sessions if needed. */ private void pruneAbandonedSessionsLocked() { long now = System.currentTimeMillis(); if (mLastPrune < now - MAX_ABANDONED_SESSION_MILLIS) { mLastPrune = now; if (mSessions.size() > 0) { (new PruneTask()).execute(); } } } void finishSessionLocked(int sessionId, int uid) { if (!isEnabled()) { return; Loading Loading @@ -513,6 +541,7 @@ final class AutofillManagerServiceImpl { pw.print(prefix); pw.print("Default component: "); pw.println(mContext.getString(R.string.config_defaultAutofillService)); pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled); pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune); final int size = mSessions.size(); if (size == 0) { Loading Loading @@ -604,4 +633,62 @@ final class AutofillManagerServiceImpl { + ", component=" + (mInfo != null ? mInfo.getServiceInfo().getComponentName() : null) + "]"; } /** Task used to prune abandoned session */ private class PruneTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... ignored) { int numSessionsToRemove; ArrayMap<IBinder, Integer> sessionsToRemove; synchronized (mLock) { numSessionsToRemove = mSessions.size(); sessionsToRemove = new ArrayMap<>(numSessionsToRemove); for (int i = 0; i < numSessionsToRemove; i++) { Session session = mSessions.valueAt(i); sessionsToRemove.put(session.getActivityTokenLocked(), session.id); } } IActivityManager am = ActivityManager.getService(); // Only remove sessions which's activities are not known to the activity manager anymore for (int i = 0; i < numSessionsToRemove; i++) { try { // The activity manager cannot resolve activities that have been removed if (am.getActivityClassForToken(sessionsToRemove.keyAt(i)) != null) { sessionsToRemove.removeAt(i); i--; numSessionsToRemove--; } } catch (RemoteException e) { Slog.w(TAG, "Cannot figure out if activity is finished", e); } } synchronized (mLock) { for (int i = 0; i < numSessionsToRemove; i++) { Session sessionToRemove = mSessions.get(sessionsToRemove.valueAt(i)); if (sessionToRemove != null) { if (sessionToRemove.isSavingLocked()) { if (sVerbose) { Slog.v(TAG, "Session " + sessionToRemove.id + " is saving"); } } else { if (sDebug) { Slog.i(TAG, "Prune session " + sessionToRemove.id + " (" + sessionToRemove.getActivityTokenLocked() + ")"); } sessionToRemove.removeSelfLocked(); } } } } return null; } } } services/autofill/java/com/android/server/autofill/Session.java +21 −1 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private boolean mDestroyed; /** Whether the session is currently saving */ @GuardedBy("mLock") private boolean mIsSaving; /** * Receiver of assist data from the app's {@link Activity}. */ Loading Loading @@ -361,7 +365,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * * @return The activity token */ IBinder getActivityTokenLocked() { @NonNull IBinder getActivityTokenLocked() { return mActivityToken; } Loading Loading @@ -474,6 +478,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onSaveRequestSuccess(@NonNull String servicePackageName) { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestSuccess() rejected - session: " + id + " destroyed"); Loading @@ -496,6 +502,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName) { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestFailure() rejected - session: " + id + " destroyed"); Loading Loading @@ -596,6 +604,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void cancelSave() { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#cancelSave() rejected - session: " + id + " destroyed"); Loading Loading @@ -831,6 +841,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (atLeastOneChanged) { mService.setSaveShown(); getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName); mIsSaving = true; return false; } } Loading @@ -843,6 +855,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } /** * Returns whether the session is currently showing the save UI */ boolean isSavingLocked() { return mIsSaving; } /** * Calls service when user requested save. */ Loading Loading @@ -1349,6 +1368,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId); pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size()); pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed); pw.print(prefix); pw.print("mIsSaving: "); pw.println(mIsSaving); final String prefix2 = prefix + " "; for (Map.Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); Loading services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +4 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,10 @@ public final class AutoFillUI { public void onDestroy() { if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) { log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE); if (mCallback != null) { mCallback.cancelSave(); } } mMetricsLogger.write(log); } Loading Loading
services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +89 −2 Original line number Diff line number Diff line Loading @@ -19,17 +19,21 @@ package com.android.server.autofill; import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.NO_SESSION; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.IActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; Loading @@ -46,6 +50,7 @@ import android.service.autofill.FillEventHistory.Event; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.ArrayMap; import android.util.LocalLog; import android.util.Slog; import android.util.SparseArray; Loading @@ -72,6 +77,9 @@ final class AutofillManagerServiceImpl { private static final String TAG = "AutofillManagerServiceImpl"; private static final int MAX_SESSION_ID_CREATE_TRIES = 2048; /** Minimum interval to prune abandoned sessions */ private static final int MAX_ABANDONED_SESSION_MILLIS = 30000; static final int MSG_SERVICE_SAVE = 1; private final int mUserId; Loading Loading @@ -104,10 +112,10 @@ final class AutofillManagerServiceImpl { mHandlerCallback, true); /** * Cache of pending {@link Session}s, keyed by {@code activityToken}. * Cache of pending {@link Session}s, keyed by sessionId. * * <p>They're kept until the {@link AutofillService} finished handling a request, an error * occurs, or the session times out. * occurs, or the session is abandoned. */ @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); Loading @@ -116,6 +124,9 @@ final class AutofillManagerServiceImpl { @GuardedBy("mLock") private FillEventHistory mEventHistory; /** When was {@link PruneTask} last executed? */ private long mLastPrune = 0; AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory, int userId, AutoFillUI ui, boolean disabled) { mContext = context; Loading Loading @@ -260,6 +271,9 @@ final class AutofillManagerServiceImpl { return 0; } // Occasionally clean up abandoned sessions pruneAbandonedSessionsLocked(); final Session newSession = createSessionByTokenLocked(activityToken, uid, windowToken, appCallbackToken, hasCallback, flags, packageName); if (newSession == null) { Loading @@ -277,6 +291,20 @@ final class AutofillManagerServiceImpl { return newSession.id; } /** * Remove abandoned sessions if needed. */ private void pruneAbandonedSessionsLocked() { long now = System.currentTimeMillis(); if (mLastPrune < now - MAX_ABANDONED_SESSION_MILLIS) { mLastPrune = now; if (mSessions.size() > 0) { (new PruneTask()).execute(); } } } void finishSessionLocked(int sessionId, int uid) { if (!isEnabled()) { return; Loading Loading @@ -513,6 +541,7 @@ final class AutofillManagerServiceImpl { pw.print(prefix); pw.print("Default component: "); pw.println(mContext.getString(R.string.config_defaultAutofillService)); pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled); pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune); final int size = mSessions.size(); if (size == 0) { Loading Loading @@ -604,4 +633,62 @@ final class AutofillManagerServiceImpl { + ", component=" + (mInfo != null ? mInfo.getServiceInfo().getComponentName() : null) + "]"; } /** Task used to prune abandoned session */ private class PruneTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... ignored) { int numSessionsToRemove; ArrayMap<IBinder, Integer> sessionsToRemove; synchronized (mLock) { numSessionsToRemove = mSessions.size(); sessionsToRemove = new ArrayMap<>(numSessionsToRemove); for (int i = 0; i < numSessionsToRemove; i++) { Session session = mSessions.valueAt(i); sessionsToRemove.put(session.getActivityTokenLocked(), session.id); } } IActivityManager am = ActivityManager.getService(); // Only remove sessions which's activities are not known to the activity manager anymore for (int i = 0; i < numSessionsToRemove; i++) { try { // The activity manager cannot resolve activities that have been removed if (am.getActivityClassForToken(sessionsToRemove.keyAt(i)) != null) { sessionsToRemove.removeAt(i); i--; numSessionsToRemove--; } } catch (RemoteException e) { Slog.w(TAG, "Cannot figure out if activity is finished", e); } } synchronized (mLock) { for (int i = 0; i < numSessionsToRemove; i++) { Session sessionToRemove = mSessions.get(sessionsToRemove.valueAt(i)); if (sessionToRemove != null) { if (sessionToRemove.isSavingLocked()) { if (sVerbose) { Slog.v(TAG, "Session " + sessionToRemove.id + " is saving"); } } else { if (sDebug) { Slog.i(TAG, "Prune session " + sessionToRemove.id + " (" + sessionToRemove.getActivityTokenLocked() + ")"); } sessionToRemove.removeSelfLocked(); } } } } return null; } } }
services/autofill/java/com/android/server/autofill/Session.java +21 −1 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private boolean mDestroyed; /** Whether the session is currently saving */ @GuardedBy("mLock") private boolean mIsSaving; /** * Receiver of assist data from the app's {@link Activity}. */ Loading Loading @@ -361,7 +365,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * * @return The activity token */ IBinder getActivityTokenLocked() { @NonNull IBinder getActivityTokenLocked() { return mActivityToken; } Loading Loading @@ -474,6 +478,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onSaveRequestSuccess(@NonNull String servicePackageName) { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestSuccess() rejected - session: " + id + " destroyed"); Loading @@ -496,6 +502,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName) { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#onSaveRequestFailure() rejected - session: " + id + " destroyed"); Loading Loading @@ -596,6 +604,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void cancelSave() { synchronized (mLock) { mIsSaving = false; if (mDestroyed) { Slog.w(TAG, "Call to Session#cancelSave() rejected - session: " + id + " destroyed"); Loading Loading @@ -831,6 +841,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (atLeastOneChanged) { mService.setSaveShown(); getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName); mIsSaving = true; return false; } } Loading @@ -843,6 +855,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } /** * Returns whether the session is currently showing the save UI */ boolean isSavingLocked() { return mIsSaving; } /** * Calls service when user requested save. */ Loading Loading @@ -1349,6 +1368,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId); pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size()); pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed); pw.print(prefix); pw.print("mIsSaving: "); pw.println(mIsSaving); final String prefix2 = prefix + " "; for (Map.Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); Loading
services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +4 −0 Original line number Diff line number Diff line Loading @@ -264,6 +264,10 @@ public final class AutoFillUI { public void onDestroy() { if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) { log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE); if (mCallback != null) { mCallback.cancelSave(); } } mMetricsLogger.write(log); } Loading