AutofillService.java revision bce4b7f1273f1d7108ed6b649320b98b73023b15
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.CallSuper; 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.os.RemoteException; 22import com.android.internal.os.HandlerCaller; 23import android.annotation.SdkConstant; 24import android.app.Activity; 25import android.app.Service; 26import android.content.Intent; 27import android.os.CancellationSignal; 28import android.os.IBinder; 29import android.os.ICancellationSignal; 30import android.os.Looper; 31import android.util.Log; 32import android.view.autofill.AutofillManager; 33 34import com.android.internal.os.SomeArgs; 35 36/** 37 * Top-level service of the current autofill service for a given user. 38 * 39 * <p>Apps providing autofill capabilities must extend this service. 40 */ 41public abstract class AutofillService extends Service { 42 private static final String TAG = "AutofillService"; 43 44 /** 45 * The {@link Intent} that must be declared as handled by the service. 46 * To be supported, the service must also require the 47 * {@link android.Manifest.permission#BIND_AUTOFILL_SERVICE} permission so 48 * that other applications can not abuse it. 49 */ 50 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 51 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; 52 53 /** 54 * Name under which a AutoFillService component publishes information about itself. 55 * This meta-data should reference an XML resource containing a 56 * <code><{@link 57 * android.R.styleable#AutofillService autofill-service}></code> tag. 58 * This is a a sample XML file configuring an AutoFillService: 59 * <pre> <autofill-service 60 * android:settingsActivity="foo.bar.SettingsActivity" 61 * . . . 62 * /></pre> 63 */ 64 public static final String SERVICE_META_DATA = "android.autofill"; 65 66 // Handler messages. 67 private static final int MSG_CONNECT = 1; 68 private static final int MSG_DISCONNECT = 2; 69 private static final int MSG_ON_FILL_REQUEST = 3; 70 private static final int MSG_ON_SAVE_REQUEST = 4; 71 72 private final IAutoFillService mInterface = new IAutoFillService.Stub() { 73 @Override 74 public void onConnectedStateChanged(boolean connected) { 75 if (connected) { 76 mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget(); 77 } else { 78 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget(); 79 } 80 } 81 82 @Override 83 public void onFillRequest(FillRequest request, IFillCallback callback) { 84 ICancellationSignal transport = CancellationSignal.createTransport(); 85 try { 86 callback.onCancellable(transport); 87 } catch (RemoteException e) { 88 e.rethrowFromSystemServer(); 89 } 90 mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request, 91 CancellationSignal.fromTransport(transport), callback) 92 .sendToTarget(); 93 } 94 95 @Override 96 public void onSaveRequest(SaveRequest request, ISaveCallback callback) { 97 mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request, 98 callback).sendToTarget(); 99 } 100 }; 101 102 private final HandlerCaller.Callback mHandlerCallback = (msg) -> { 103 switch (msg.what) { 104 case MSG_CONNECT: { 105 onConnected(); 106 break; 107 } case MSG_ON_FILL_REQUEST: { 108 final SomeArgs args = (SomeArgs) msg.obj; 109 final FillRequest request = (FillRequest) args.arg1; 110 final CancellationSignal cancellation = (CancellationSignal) args.arg2; 111 final IFillCallback callback = (IFillCallback) args.arg3; 112 final FillCallback fillCallback = new FillCallback(callback, request.getId()); 113 args.recycle(); 114 onFillRequest(request, cancellation, fillCallback); 115 break; 116 } case MSG_ON_SAVE_REQUEST: { 117 final SomeArgs args = (SomeArgs) msg.obj; 118 final SaveRequest request = (SaveRequest) args.arg1; 119 final ISaveCallback callback = (ISaveCallback) args.arg2; 120 final SaveCallback saveCallback = new SaveCallback(callback); 121 args.recycle(); 122 onSaveRequest(request, saveCallback); 123 break; 124 } case MSG_DISCONNECT: { 125 onDisconnected(); 126 break; 127 } default: { 128 Log.w(TAG, "MyCallbacks received invalid message type: " + msg); 129 } 130 } 131 }; 132 133 private HandlerCaller mHandlerCaller; 134 135 /** 136 * {@inheritDoc} 137 * 138 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}. 139 */ 140 @CallSuper 141 @Override 142 public void onCreate() { 143 super.onCreate(); 144 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true); 145 } 146 147 @Override 148 public final IBinder onBind(Intent intent) { 149 if (SERVICE_INTERFACE.equals(intent.getAction())) { 150 return mInterface.asBinder(); 151 } 152 Log.w(TAG, "Tried to bind to wrong intent: " + intent); 153 return null; 154 } 155 156 /** 157 * Called when the Android system connects to service. 158 * 159 * <p>You should generally do initialization here rather than in {@link #onCreate}. 160 */ 161 public void onConnected() { 162 } 163 164 /** 165 * Called by the Android system do decide if an {@link Activity} can be autofilled by the 166 * service. 167 * 168 * <p>Service must call one of the {@link FillCallback} methods (like 169 * {@link FillCallback#onSuccess(FillResponse)} 170 * or {@link FillCallback#onFailure(CharSequence)}) 171 * to notify the result of the request. 172 * 173 * @param request the {@link FillRequest request} to handle. 174 * See {@link FillResponse} for examples of multiple-sections requests. 175 * @param cancellationSignal signal for observing cancellation requests. The system will use 176 * this to notify you that the fill result is no longer needed and you should stop 177 * handling this fill request in order to save resources. 178 * @param callback object used to notify the result of the request. 179 */ 180 public abstract void onFillRequest(@NonNull FillRequest request, 181 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); 182 183 /** 184 * Called when user requests service to save the fields of an {@link Activity}. 185 * 186 * <p>Service must call one of the {@link SaveCallback} methods (like 187 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) 188 * to notify the result of the request. 189 * 190 * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call 191 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls 192 * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no 193 * guarantee such method will return the most recent value of the field. 194 * 195 * @param request the {@link SaveRequest request} to handle. 196 * See {@link FillResponse} for examples of multiple-sections requests. 197 * @param callback object used to notify the result of the request. 198 */ 199 public abstract void onSaveRequest(@NonNull SaveRequest request, 200 @NonNull SaveCallback callback); 201 202 /** 203 * Called when the Android system disconnects from the service. 204 * 205 * <p> At this point this service may no longer be an active {@link AutofillService}. 206 */ 207 public void onDisconnected() { 208 } 209 210 /** 211 * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was 212 * returned. 213 * 214 * <p>The history is not persisted over reboots. 215 * 216 * @return The history or {@code null} if there are not events. 217 */ 218 @Nullable public final FillEventHistory getFillEventHistory() { 219 AutofillManager afm = getSystemService(AutofillManager.class); 220 221 if (afm == null) { 222 return null; 223 } else { 224 return afm.getFillEventHistory(); 225 } 226 } 227} 228