AutofillService.java revision eab62baabf290ea6671577a66cfc9fdd1b145d0e
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.service.autofill; 17 18import android.annotation.NonNull; 19import android.annotation.Nullable; 20import android.os.RemoteException; 21import com.android.internal.os.HandlerCaller; 22import android.annotation.SdkConstant; 23import android.app.Activity; 24import android.app.Service; 25import android.app.assist.AssistStructure; 26import android.content.Intent; 27import android.os.Bundle; 28import android.os.CancellationSignal; 29import android.os.IBinder; 30import android.os.ICancellationSignal; 31import android.os.Looper; 32import android.util.Log; 33import android.view.autofill.AutofillManager; 34 35import com.android.internal.os.SomeArgs; 36 37//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the 38//life-cycle (and how state could be maintained on server-side) is well documented. 39 40/** 41 * Top-level service of the current autofill service for a given user. 42 * 43 * <p>Apps providing autofill capabilities must extend this service. 44 */ 45public abstract class AutofillService extends Service { 46 private static final String TAG = "AutofillService"; 47 48 /** 49 * The {@link Intent} that must be declared as handled by the service. 50 * To be supported, the service must also require the 51 * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so 52 * that other applications can not abuse it. 53 * 54 * @hide 55 * @deprecated TODO(b/35956626): remove once clients use AutofillService 56 */ 57 @Deprecated 58 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 59 public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService"; 60 61 /** 62 * The {@link Intent} that must be declared as handled by the service. 63 * To be supported, the service must also require the 64 * {@link android.Manifest.permission#BIND_AUTOFILL} permission so 65 * that other applications can not abuse it. 66 */ 67 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 68 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; 69 70 /** 71 * Name under which a AutoFillService component publishes information about itself. 72 * This meta-data should reference an XML resource containing a 73 * <code><{@link 74 * android.R.styleable#AutofillService autofill-service}></code> tag. 75 * This is a a sample XML file configuring an AutoFillService: 76 * <pre> <autofill-service 77 * android:settingsActivity="foo.bar.SettingsActivity" 78 * . . . 79 * /></pre> 80 */ 81 public static final String SERVICE_META_DATA = "android.autofill"; 82 83 // Internal extras 84 /** @hide */ 85 public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID"; 86 87 // Handler messages. 88 private static final int MSG_CONNECT = 1; 89 private static final int MSG_DISCONNECT = 2; 90 private static final int MSG_ON_FILL_REQUEST = 3; 91 private static final int MSG_ON_SAVE_REQUEST = 4; 92 93 private static final int UNUSED_ARG = -1; 94 95 private final IAutoFillService mInterface = new IAutoFillService.Stub() { 96 @Override 97 public void onInit(IAutoFillServiceConnection connection) { 98 if (connection != null) { 99 mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget(); 100 } else { 101 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget(); 102 } 103 } 104 105 @Override 106 public void onFillRequest(AssistStructure structure, Bundle extras, 107 IFillCallback callback, int flags) { 108 ICancellationSignal transport = CancellationSignal.createTransport(); 109 try { 110 callback.onCancellable(transport); 111 } catch (RemoteException e) { 112 e.rethrowFromSystemServer(); 113 } 114 mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure, 115 CancellationSignal.fromTransport(transport), extras, callback) 116 .sendToTarget(); 117 } 118 119 @Override 120 public void onSaveRequest(AssistStructure structure, Bundle extras, 121 ISaveCallback callback) { 122 mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure, 123 extras, callback).sendToTarget(); 124 } 125 }; 126 127 private final HandlerCaller.Callback mHandlerCallback = (msg) -> { 128 switch (msg.what) { 129 case MSG_CONNECT: { 130 mConnection = (IAutoFillServiceConnection) msg.obj; 131 onConnected(); 132 break; 133 } case MSG_ON_FILL_REQUEST: { 134 final SomeArgs args = (SomeArgs) msg.obj; 135 final AssistStructure structure = (AssistStructure) args.arg1; 136 final CancellationSignal cancellation = (CancellationSignal) args.arg2; 137 final Bundle extras = (Bundle) args.arg3; 138 final IFillCallback callback = (IFillCallback) args.arg4; 139 final FillCallback fillCallback = new FillCallback(callback); 140 final int flags = msg.arg1; 141 args.recycle(); 142 onFillRequest(structure, extras, flags, cancellation, fillCallback); 143 break; 144 } case MSG_ON_SAVE_REQUEST: { 145 final SomeArgs args = (SomeArgs) msg.obj; 146 final AssistStructure structure = (AssistStructure) args.arg1; 147 final Bundle extras = (Bundle) args.arg2; 148 final ISaveCallback callback = (ISaveCallback) args.arg3; 149 final SaveCallback saveCallback = new SaveCallback(callback); 150 args.recycle(); 151 onSaveRequest(structure, extras, saveCallback); 152 break; 153 } case MSG_DISCONNECT: { 154 onDisconnected(); 155 mConnection = null; 156 break; 157 } default: { 158 Log.w(TAG, "MyCallbacks received invalid message type: " + msg); 159 } 160 } 161 }; 162 163 private HandlerCaller mHandlerCaller; 164 165 private IAutoFillServiceConnection mConnection; 166 167 /** 168 * {@inheritDoc} 169 * 170 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}. 171 */ 172 @Override 173 public void onCreate() { 174 super.onCreate(); 175 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true); 176 } 177 178 @Override 179 public final IBinder onBind(Intent intent) { 180 if (SERVICE_INTERFACE.equals(intent.getAction()) 181 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) { 182 return mInterface.asBinder(); 183 } 184 Log.w(TAG, "Tried to bind to wrong intent: " + intent); 185 return null; 186 } 187 188 /** 189 * Called when the Android system connects to service. 190 * 191 * <p>You should generally do initialization here rather than in {@link #onCreate}. 192 */ 193 public void onConnected() { 194 } 195 196 /** 197 * Called by the Android system do decide if an {@link Activity} can be autofilled by the 198 * service. 199 * 200 * <p>Service must call one of the {@link FillCallback} methods (like 201 * {@link FillCallback#onSuccess(FillResponse)} 202 * or {@link FillCallback#onFailure(CharSequence)}) 203 * to notify the result of the request. 204 * 205 * @param structure {@link Activity}'s view structure. 206 * @param data bundle containing data passed by the service in a last call to 207 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your 208 * service to keep state between fill and save requests as well as when filling different 209 * sections of the UI as the system will try to aggressively unbind from the service to 210 * conserve resources. 211 * See {@link FillResponse} for examples of multiple-sections requests. 212 * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}. 213 * @param cancellationSignal signal for observing cancellation requests. The system will use 214 * this to notify you that the fill result is no longer needed and you should stop 215 * handling this fill request in order to save resources. 216 * @param callback object used to notify the result of the request. 217 */ 218 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 219 int flags, @NonNull CancellationSignal cancellationSignal, 220 @NonNull FillCallback callback); 221 222 /** 223 * Called when user requests service to save the fields of an {@link Activity}. 224 * 225 * <p>Service must call one of the {@link SaveCallback} methods (like 226 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) 227 * to notify the result of the request. 228 * 229 * @param structure {@link Activity}'s view structure. 230 * @param data bundle containing data passed by the service in a last call to 231 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your 232 * service to keep state between fill and save requests as well as when filling different 233 * sections of the UI as the system will try to aggressively unbind from the service to 234 * conserve resources. 235 * See {@link FillResponse} for examples of multiple-sections requests. 236 * @param callback object used to notify the result of the request. 237 */ 238 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 239 @NonNull SaveCallback callback); 240 241 /** 242 * Called when the Android system disconnects from the service. 243 * 244 * <p> At this point this service may no longer be an active {@link AutofillService}. 245 */ 246 public void onDisconnected() { 247 } 248 249 /** 250 * Disables the service. After calling this method, the service will 251 * be disabled and settings will show that it is turned off. 252 * 253 * <p>You should call this method only after a call to {@link #onConnected()} 254 * and before the corresponding call to {@link #onDisconnected()}. In other words 255 * you can disable your service only while the system is connected to it.</p> 256 */ 257 public final void disableSelf() { 258 if (mConnection != null) { 259 try { 260 mConnection.disableSelf(); 261 } catch (RemoteException re) { 262 throw re.rethrowFromSystemServer(); 263 } 264 } 265 } 266} 267