AutofillService.java revision fc4a3004e37b25065412fa65cbe060c08bf0398a
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 onConnectedStateChanged(boolean connected) { 98 if (connected) { 99 mHandlerCaller.obtainMessage(MSG_CONNECT).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 onConnected(); 131 break; 132 } case MSG_ON_FILL_REQUEST: { 133 final SomeArgs args = (SomeArgs) msg.obj; 134 final AssistStructure structure = (AssistStructure) args.arg1; 135 final CancellationSignal cancellation = (CancellationSignal) args.arg2; 136 final Bundle extras = (Bundle) args.arg3; 137 final IFillCallback callback = (IFillCallback) args.arg4; 138 final FillCallback fillCallback = new FillCallback(callback); 139 final int flags = msg.arg1; 140 args.recycle(); 141 onFillRequest(structure, extras, flags, cancellation, fillCallback); 142 break; 143 } case MSG_ON_SAVE_REQUEST: { 144 final SomeArgs args = (SomeArgs) msg.obj; 145 final AssistStructure structure = (AssistStructure) args.arg1; 146 final Bundle extras = (Bundle) args.arg2; 147 final ISaveCallback callback = (ISaveCallback) args.arg3; 148 final SaveCallback saveCallback = new SaveCallback(callback); 149 args.recycle(); 150 onSaveRequest(structure, extras, saveCallback); 151 break; 152 } case MSG_DISCONNECT: { 153 onDisconnected(); 154 break; 155 } default: { 156 Log.w(TAG, "MyCallbacks received invalid message type: " + msg); 157 } 158 } 159 }; 160 161 private HandlerCaller mHandlerCaller; 162 163 /** 164 * {@inheritDoc} 165 * 166 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}. 167 */ 168 @Override 169 public void onCreate() { 170 super.onCreate(); 171 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true); 172 } 173 174 @Override 175 public final IBinder onBind(Intent intent) { 176 if (SERVICE_INTERFACE.equals(intent.getAction()) 177 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) { 178 return mInterface.asBinder(); 179 } 180 Log.w(TAG, "Tried to bind to wrong intent: " + intent); 181 return null; 182 } 183 184 /** 185 * Called when the Android system connects to service. 186 * 187 * <p>You should generally do initialization here rather than in {@link #onCreate}. 188 */ 189 public void onConnected() { 190 } 191 192 /** 193 * Called by the Android system do decide if an {@link Activity} can be autofilled by the 194 * service. 195 * 196 * <p>Service must call one of the {@link FillCallback} methods (like 197 * {@link FillCallback#onSuccess(FillResponse)} 198 * or {@link FillCallback#onFailure(CharSequence)}) 199 * to notify the result of the request. 200 * 201 * @param structure {@link Activity}'s view structure. 202 * @param data bundle containing data passed by the service in a last call to 203 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your 204 * service to keep state between fill and save requests as well as when filling different 205 * sections of the UI as the system will try to aggressively unbind from the service to 206 * conserve resources. 207 * See {@link FillResponse} for examples of multiple-sections requests. 208 * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}. 209 * @param cancellationSignal signal for observing cancellation requests. The system will use 210 * this to notify you that the fill result is no longer needed and you should stop 211 * handling this fill request in order to save resources. 212 * @param callback object used to notify the result of the request. 213 */ 214 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 215 int flags, @NonNull CancellationSignal cancellationSignal, 216 @NonNull FillCallback callback); 217 218 /** 219 * Called when user requests service to save the fields of an {@link Activity}. 220 * 221 * <p>Service must call one of the {@link SaveCallback} methods (like 222 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) 223 * to notify the result of the request. 224 * 225 * @param structure {@link Activity}'s view structure. 226 * @param data bundle containing data passed by the service in a last call to 227 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your 228 * service to keep state between fill and save requests as well as when filling different 229 * sections of the UI as the system will try to aggressively unbind from the service to 230 * conserve resources. 231 * See {@link FillResponse} for examples of multiple-sections requests. 232 * @param callback object used to notify the result of the request. 233 */ 234 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data, 235 @NonNull SaveCallback callback); 236 237 /** 238 * Called when the Android system disconnects from the service. 239 * 240 * <p> At this point this service may no longer be an active {@link AutofillService}. 241 */ 242 public void onDisconnected() { 243 } 244 245 @Deprecated 246 public final void disableSelf() { 247 // TODO(b/33197203): Remove when GCore has migrated off this API 248 getSystemService(AutofillManager.class).disableOwnedAutofillServices(); 249 } 250} 251