diff --git a/Android.mk b/Android.mk index f544620b993f2..f318a5a754c1e 100644 --- a/Android.mk +++ b/Android.mk @@ -265,6 +265,7 @@ LOCAL_SRC_FILES += \ core/java/android/security/IKeystoreService.aidl \ core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \ core/java/android/service/autofill/IAutoFillService.aidl \ + core/java/android/service/autofill/IAutoFillServiceConnection.aidl \ core/java/android/service/autofill/IFillCallback.aidl \ core/java/android/service/autofill/ISaveCallback.aidl \ core/java/android/service/carrier/ICarrierService.aidl \ diff --git a/api/current.txt b/api/current.txt index 9c443f832ae66..5099c2b62a984 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36472,6 +36472,7 @@ package android.service.autofill { public abstract class AutoFillService extends android.app.Service { ctor public AutoFillService(); + method public final void disableSelf(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); diff --git a/api/system-current.txt b/api/system-current.txt index eb237fae6a508..41b52ec999d58 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -39395,6 +39395,7 @@ package android.service.autofill { public abstract class AutoFillService extends android.app.Service { ctor public AutoFillService(); + method public final void disableSelf(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); diff --git a/api/test-current.txt b/api/test-current.txt index ccf688c67367b..5183e27a9e071 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -36611,6 +36611,7 @@ package android.service.autofill { public abstract class AutoFillService extends android.app.Service { ctor public AutoFillService(); + method public final void disableSelf(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java index 4099f59ec9ef6..3c211eb972e7d 100644 --- a/core/java/android/service/autofill/AutoFillService.java +++ b/core/java/android/service/autofill/AutoFillService.java @@ -15,9 +15,12 @@ */ package android.service.autofill; +import android.accessibilityservice.IAccessibilityServiceConnection; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Message; import android.os.RemoteException; +import android.view.accessibility.AccessibilityInteractionClient; import com.android.internal.os.HandlerCaller; import android.annotation.SdkConstant; import android.app.Activity; @@ -78,6 +81,15 @@ public abstract class AutoFillService extends Service { private static final int MSG_ON_SAVE_REQUEST = 4; private final IAutoFillService mInterface = new IAutoFillService.Stub() { + @Override + public void onInit(IAutoFillServiceConnection connection) { + if (connection != null) { + mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget(); + } else { + mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget(); + } + } + @Override public void onFillRequest(AssistStructure structure, Bundle extras, IFillCallback callback) { @@ -98,21 +110,12 @@ public abstract class AutoFillService extends Service { mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure, extras, callback).sendToTarget(); } - - @Override - public void onConnected() { - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT)); - } - - @Override - public void onDisconnected() { - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DISCONNECT)); - } }; private final HandlerCaller.Callback mHandlerCallback = (msg) -> { switch (msg.what) { case MSG_CONNECT: { + mConnection = (IAutoFillServiceConnection) msg.obj; onConnected(); break; } case MSG_ON_FILL_REQUEST: { @@ -136,6 +139,7 @@ public abstract class AutoFillService extends Service { break; } case MSG_DISCONNECT: { onDisconnected(); + mConnection = null; break; } default: { Log.w(TAG, "MyCallbacks received invalid message type: " + msg); @@ -145,6 +149,8 @@ public abstract class AutoFillService extends Service { private HandlerCaller mHandlerCaller; + private IAutoFillServiceConnection mConnection; + /** * {@inheritDoc} * @@ -223,4 +229,22 @@ public abstract class AutoFillService extends Service { public void onDisconnected() { //TODO(b/33197203): is not called anymore, fix it! } + + /** + * Disables the service. After calling this method, the service will + * be disabled and settings will show that it is turned off. + * + *
You should call this method only after a call to {@link #onConnected()} + * and before the corresponding call to {@link #onDisconnected()}. In other words + * you can disable your service only while the system is connected to it.
+ */ + public final void disableSelf() { + if (mConnection != null) { + try { + mConnection.disableSelf(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + } } diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl index fa1ea65e30b05..80685d87a7883 100644 --- a/core/java/android/service/autofill/IAutoFillService.aidl +++ b/core/java/android/service/autofill/IAutoFillService.aidl @@ -18,6 +18,7 @@ package android.service.autofill; import android.app.assist.AssistStructure; import android.os.Bundle; +import android.service.autofill.IAutoFillServiceConnection; import android.service.autofill.IFillCallback; import android.service.autofill.ISaveCallback; import com.android.internal.os.IResultReceiver; @@ -28,10 +29,9 @@ import com.android.internal.os.IResultReceiver; * @hide */ oneway interface IAutoFillService { + void onInit(in IAutoFillServiceConnection connection); void onFillRequest(in AssistStructure structure, in Bundle extras, in IFillCallback callback); void onSaveRequest(in AssistStructure structure, in Bundle extras, in ISaveCallback callback); - void onConnected(); - void onDisconnected(); } diff --git a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl new file mode 100644 index 0000000000000..cf73a10ca58ca --- /dev/null +++ b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.autofill; + +/** + * Interface from an auto fill service to the system. + * + * @hide + */ +interface IAutoFillServiceConnection { + void disableSelf(); +} diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java index 7a85d4e9b62e6..8947b7d99eef0 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java @@ -185,6 +185,29 @@ public final class AutoFillManagerService extends SystemService { } } + // Called by Shell command. + void destroySessions(int userId, IResultReceiver receiver) { + Slog.i(TAG, "destroySessions() for userId " + userId); + mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + + synchronized (mLock) { + if (userId != UserHandle.USER_ALL) { + mServicesCache.get(userId).destroySessionsLocked(); + } else { + final int size = mServicesCache.size(); + for (int i = 0; i < size; i++) { + mServicesCache.valueAt(i).destroySessionsLocked(); + } + } + } + + try { + receiver.send(0, new Bundle()); + } catch (RemoteException e) { + // Just ignore it... + } + } + // Called by Shell command. void listSessions(int userId, IResultReceiver receiver) { Slog.i(TAG, "listSessions() for userId " + userId); diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java index bfc6e836c3b0d..ad4dac070d389 100644 --- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java @@ -405,6 +405,12 @@ final class AutoFillManagerServiceImpl { } } + void destroySessionsLocked() { + for (Session session : mSessions.values()) { + session.removeSelf(); + } + } + void listSessionsLocked(ArrayList