1 /*
2  * Copyright (C) 2016 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  */
16 
17 package android.service.autofill;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.Activity;
22 import android.content.IntentSender;
23 import android.os.RemoteException;
24 import android.util.Log;
25 
26 import java.util.Objects;
27 
28 /**
29  * Handles save requests from the {@link AutofillService} into the {@link Activity} being
30  * autofilled.
31  */
32 public final class SaveCallback {
33 
34     private static final String TAG = "SaveCallback";
35 
36     private final ISaveCallback mCallback;
37     private boolean mCalled;
38 
39     /** @hide */
SaveCallback(ISaveCallback callback)40     SaveCallback(ISaveCallback callback) {
41         mCallback = callback;
42     }
43 
44     /**
45      * Notifies the Android System that an
46      * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully handled
47      * by the service.
48      *
49      * @throws IllegalStateException if this method, {@link #onSuccess(IntentSender)}, or
50      * {@link #onFailure(CharSequence)} was already called.
51      */
onSuccess()52     public void onSuccess() {
53         onSuccessInternal(null);
54     }
55 
56     /**
57      * Notifies the Android System that an
58      * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully handled
59      * by the service.
60      *
61      * <p>This method is useful when the service requires extra work&mdash;for example, launching an
62      * activity asking the user to authenticate first &mdash;before it can process the request,
63      * as the intent will be launched from the context of the activity being autofilled and hence
64      * will be part of that activity's stack.
65      *
66      * @param intentSender intent that will be launched from the context of activity being
67      * autofilled.
68      *
69      * @throws IllegalStateException if this method, {@link #onSuccess()},
70      * or {@link #onFailure(CharSequence)} was already called.
71      */
onSuccess(@onNull IntentSender intentSender)72     public void onSuccess(@NonNull IntentSender intentSender) {
73         onSuccessInternal(Objects.requireNonNull(intentSender));
74     }
75 
onSuccessInternal(@ullable IntentSender intentSender)76     private void onSuccessInternal(@Nullable IntentSender intentSender) {
77         assertNotCalled();
78         mCalled = true;
79         try {
80             mCallback.onSuccess(intentSender);
81         } catch (RemoteException e) {
82             e.rethrowAsRuntimeException();
83         }
84     }
85 
86 
87 
88 
89     /**
90      * Notifies the Android System that an
91      * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} could not be handled
92      * by the service.
93      *
94      * <p>This method is just used for logging purposes, the Android System won't call the service
95      * again in case of failures&mdash;if you need to recover from the failure, just save the
96      * {@link SaveRequest} and try again later.
97      *
98      * <p><b>Note: </b>for apps targeting {@link android.os.Build.VERSION_CODES#Q} or higher, this
99      * method just logs the message on {@code logcat}; for apps targetting older SDKs, it also
100      * displays the message to user using a {@link android.widget.Toast}.
101      *
102      * @param message error message. <b>Note: </b> this message should <b>not</b> contain PII
103      * (Personally Identifiable Information, such as username or email address).
104      *
105      * @throws IllegalStateException if this method, {@link #onSuccess()},
106      * or {@link #onSuccess(IntentSender)} was already called.
107      */
onFailure(CharSequence message)108     public void onFailure(CharSequence message) {
109         Log.w(TAG, "onFailure(): " + message);
110         assertNotCalled();
111         mCalled = true;
112         try {
113             mCallback.onFailure(message);
114         } catch (RemoteException e) {
115             e.rethrowAsRuntimeException();
116         }
117     }
118 
assertNotCalled()119     private void assertNotCalled() {
120         if (mCalled) {
121             throw new IllegalStateException("Already called");
122         }
123     }
124 }
125