AutofillService.java revision f78e952d8df7074aa7380c5998826a4dffe335e7
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_ACTIVITY_TOKEN = 86 "android.service.autofill.extra.ACTIVITY_TOKEN"; 87 88 // Handler messages. 89 private static final int MSG_CONNECT = 1; 90 private static final int MSG_DISCONNECT = 2; 91 private static final int MSG_ON_FILL_REQUEST = 3; 92 private static final int MSG_ON_SAVE_REQUEST = 4; 93 94 private static final int UNUSED_ARG = -1; 95 96 private final IAutoFillService mInterface = new IAutoFillService.Stub() { 97 @Override 98 public void onInit(IAutoFillServiceConnection connection) { 99 if (connection != null) { 100 mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget(); 101 } else { 102 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget(); 103 } 104 } 105 106 @Override 107 public void onFillRequest(AssistStructure structure, Bundle extras, 108 IFillCallback callback, int flags) { 109 ICancellationSignal transport = CancellationSignal.createTransport(); 110 try { 111 callback.onCancellable(transport); 112 } catch (RemoteException e) { 113 e.rethrowFromSystemServer(); 114 } 115 mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure, 116 CancellationSignal.fromTransport(transport), extras, callback) 117 .sendToTarget(); 118 } 119 120 @Override 121 public void onSaveRequest(AssistStructure structure, Bundle extras, 122 ISaveCallback callback) { 123 mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure, 124 extras, callback).sendToTarget(); 125 } 126 }; 127 128 private final HandlerCaller.Callback mHandlerCallback = (msg) -> { 129 switch (msg.what) { 130 case MSG_CONNECT: { 131 mConnection = (IAutoFillServiceConnection) msg.obj; 132 onConnected(); 133 break; 134 } case MSG_ON_FILL_REQUEST: { 135 final SomeArgs args = (SomeArgs) msg.obj; 136 final AssistStructure structure = (AssistStructure) args.arg1; 137 final CancellationSignal cancellation = (CancellationSignal) args.arg2; 138 final Bundle extras = (Bundle) args.arg3; 139 final IFillCallback callback = (IFillCallback) args.arg4; 140 final FillCallback fillCallback = new FillCallback(callback); 141 final int flags = msg.arg1; 142 args.recycle(); 143 onFillRequest(structure, extras, flags, cancellation, fillCallback); 144 break; 145 } case MSG_ON_SAVE_REQUEST: { 146 final SomeArgs args = (SomeArgs) msg.obj; 147 final AssistStructure structure = (AssistStructure) args.arg1; 148 final Bundle extras = (Bundle) args.arg2; 149 final ISaveCallback callback = (ISaveCallback) args.arg3; 150 final SaveCallback saveCallback = new SaveCallback(callback); 151 args.recycle(); 152 onSaveRequest(structure, extras, saveCallback); 153 break; 154 } case MSG_DISCONNECT: { 155 onDisconnected(); 156 mConnection = null; 157 break; 158 } default: { 159 Log.w(TAG, "MyCallbacks received invalid message type: " + msg); 160 } 161 } 162 }; 163 164 private HandlerCaller mHandlerCaller; 165 166 private IAutoFillServiceConnection mConnection; 167 168 /** 169 * {@inheritDoc} 170 * 171 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}. 172 */ 173 @Override 174 public void onCreate() { 175 super.onCreate(); 176 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true); 177 } 178 179 @Override 180 public final IBinder onBind(Intent intent) { 181 if (SERVICE_INTERFACE.equals(intent.getAction()) 182 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) { 183 return mInterface.asBinder(); 184 } 185 Log.w(TAG, "Tried to bind to wrong intent: " + intent); 186 return null; 187 } 188 189 /** 190 * Called when the Android system connects to service. 191 * 192 * <p>You should generally do initialization here rather than in {@link #onCreate}. 193 */ 194 public void onConnected() { 195 } 196 197 /** 198 * Called by the Android system do decide if an {@link Activity} can be autofilled by the 199 * service. 200 * 201 * <p>Service must call one of the {@link FillCallback} methods (like 202 * {@link FillCallback#onSuccess(FillResponse)} 203 * or {@link FillCallback#onFailure(CharSequence)}) 204 * to notify the result of the request. 205 * 206 * @param structure {@link Activity}'s view structure. 207 * @param data bundle containing data passed by the service on previous calls to fill. 208 * This bundle allows your service to keep state between fill and save requests 209 * as well as when filling different sections of the UI as the system will try to 210 * aggressively unbind from the service to conserve resources. See {@link 211 * FillResponse} Javadoc 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 void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, int flags, 219 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) { 220 //TODO(b/33197203): make non-abstract once older method is removed 221 onFillRequest(structure, data, cancellationSignal, callback); 222 } 223 224 /** 225 * @hide 226 * @deprecated - use {@link #onFillRequest(AssistStructure, Bundle, int, 227 * CancellationSignal, FillCallback)} instead 228 */ 229 //TODO(b/33197203): remove once clients are not using anymore 230 @Deprecated 231 public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 232 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) { 233 // Should never be called because it was abstract before. 234 throw new UnsupportedOperationException("deprecated"); 235 } 236 237 /** 238 * Called when user requests service to save the fields of an {@link Activity}. 239 * 240 * <p>Service must call one of the {@link SaveCallback} methods (like 241 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) 242 * to notify the result of the request. 243 * 244 * @param structure {@link Activity}'s view structure. 245 * @param data bundle containing data passed by the service on previous calls to fill. 246 * This bundle allows your service to keep state between fill and save requests 247 * as well as when filling different sections of the UI as the system will try to 248 * aggressively unbind from the service to conserve resources. See {@link 249 * FillResponse} Javadoc for examples of multiple-sections requests. 250 * @param callback object used to notify the result of the request. 251 */ 252 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 253 @NonNull SaveCallback callback); 254 255 /** 256 * Called when the Android system disconnects from the service. 257 * 258 * <p> At this point this service may no longer be an active {@link AutofillService}. 259 */ 260 public void onDisconnected() { 261 } 262 263 /** 264 * Disables the service. After calling this method, the service will 265 * be disabled and settings will show that it is turned off. 266 * 267 * <p>You should call this method only after a call to {@link #onConnected()} 268 * and before the corresponding call to {@link #onDisconnected()}. In other words 269 * you can disable your service only while the system is connected to it.</p> 270 */ 271 public final void disableSelf() { 272 if (mConnection != null) { 273 try { 274 mConnection.disableSelf(); 275 } catch (RemoteException re) { 276 throw re.rethrowFromSystemServer(); 277 } 278 } 279 } 280} 281