Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 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 | */ |
| 16 | |
| 17 | package com.android.server.am; |
| 18 | |
| 19 | import static android.app.ActivityManager.ASSIST_CONTEXT_FULL; |
| 20 | import static android.app.AppOpsManager.MODE_ALLOWED; |
| 21 | import static android.app.AppOpsManager.OP_NONE; |
Winson Chung | fbbb158 | 2018-11-13 16:09:01 -0800 | [diff] [blame] | 22 | |
Wale Ogunwale | 9e4f3e0 | 2018-05-17 09:35:39 -0700 | [diff] [blame] | 23 | import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 24 | |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 25 | import android.app.ActivityTaskManager; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 26 | import android.app.AppOpsManager; |
Winson Chung | e210468 | 2017-11-08 17:31:14 -0800 | [diff] [blame] | 27 | import android.app.IAssistDataReceiver; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 28 | import android.content.Context; |
| 29 | import android.graphics.Bitmap; |
| 30 | import android.os.Bundle; |
| 31 | import android.os.IBinder; |
| 32 | import android.os.RemoteException; |
| 33 | import android.view.IWindowManager; |
| 34 | |
| 35 | import com.android.internal.annotations.GuardedBy; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 36 | import com.android.internal.logging.MetricsLogger; |
| 37 | |
| 38 | import java.io.PrintWriter; |
| 39 | import java.util.ArrayList; |
| 40 | import java.util.List; |
| 41 | |
| 42 | /** |
| 43 | * Helper class to asynchronously fetch the assist data and screenshot from the current running |
| 44 | * activities. It manages received data and calls back to the owner when the owner is ready to |
| 45 | * receive the data itself. |
| 46 | */ |
| 47 | public class AssistDataRequester extends IAssistDataReceiver.Stub { |
| 48 | |
| 49 | public static final String KEY_RECEIVER_EXTRA_COUNT = "count"; |
| 50 | public static final String KEY_RECEIVER_EXTRA_INDEX = "index"; |
| 51 | |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 52 | private IWindowManager mWindowManager; |
| 53 | private Context mContext; |
| 54 | private AppOpsManager mAppOpsManager; |
| 55 | |
| 56 | private AssistDataRequesterCallbacks mCallbacks; |
| 57 | private Object mCallbacksLock; |
| 58 | |
| 59 | private int mRequestStructureAppOps; |
| 60 | private int mRequestScreenshotAppOps; |
| 61 | private boolean mCanceled; |
| 62 | private int mPendingDataCount; |
| 63 | private int mPendingScreenshotCount; |
| 64 | private final ArrayList<Bundle> mAssistData = new ArrayList<>(); |
| 65 | private final ArrayList<Bitmap> mAssistScreenshot = new ArrayList<>(); |
| 66 | |
| 67 | |
| 68 | /** |
| 69 | * Interface to handle the events from the fetcher. |
| 70 | */ |
| 71 | public interface AssistDataRequesterCallbacks { |
| 72 | /** |
| 73 | * @return whether the currently received assist data can be handled by the callbacks. |
| 74 | */ |
| 75 | @GuardedBy("mCallbacksLock") |
| 76 | boolean canHandleReceivedAssistDataLocked(); |
| 77 | |
| 78 | /** |
| 79 | * Called when we receive asynchronous assist data. This call is only made if the |
| 80 | * {@param fetchData} argument to requestAssistData() is true, and if the current activity |
| 81 | * allows assist data to be fetched. In addition, the callback will be made with the |
| 82 | * {@param mCallbacksLock} held, and only if {@link #canHandleReceivedAssistDataLocked()} |
| 83 | * is true. |
| 84 | */ |
| 85 | @GuardedBy("mCallbacksLock") |
Winson Chung | fbbb158 | 2018-11-13 16:09:01 -0800 | [diff] [blame] | 86 | default void onAssistDataReceivedLocked(Bundle data, int activityIndex, int activityCount) { |
| 87 | // Do nothing |
| 88 | } |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 89 | |
| 90 | /** |
| 91 | * Called when we receive asynchronous assist screenshot. This call is only made if |
| 92 | * {@param fetchScreenshot} argument to requestAssistData() is true, and if the current |
| 93 | * activity allows assist data to be fetched. In addition, the callback will be made with |
| 94 | * the {@param mCallbacksLock} held, and only if |
| 95 | * {@link #canHandleReceivedAssistDataLocked()} is true. |
| 96 | */ |
| 97 | @GuardedBy("mCallbacksLock") |
Winson Chung | fbbb158 | 2018-11-13 16:09:01 -0800 | [diff] [blame] | 98 | default void onAssistScreenshotReceivedLocked(Bitmap screenshot) { |
| 99 | // Do nothing |
| 100 | } |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 101 | |
| 102 | /** |
| 103 | * Called when there is no more pending assist data or screenshots for the last request. |
| 104 | * If the request was canceled, then this callback will not be made. In addition, the |
| 105 | * callback will be made with the {@param mCallbacksLock} held, and only if |
| 106 | * {@link #canHandleReceivedAssistDataLocked()} is true. |
| 107 | */ |
| 108 | @GuardedBy("mCallbacksLock") |
| 109 | default void onAssistRequestCompleted() { |
| 110 | // Do nothing |
| 111 | } |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | /** |
| 115 | * @param callbacks The callbacks to handle the asynchronous reply with the assist data. |
| 116 | * @param callbacksLock The lock for the requester to hold when calling any of the |
| 117 | * {@param callbacks}. The owner should also take care in locking |
| 118 | * appropriately when calling into this requester. |
| 119 | * @param requestStructureAppOps The app ops to check before requesting the assist structure |
| 120 | * @param requestScreenshotAppOps The app ops to check before requesting the assist screenshot. |
| 121 | * This can be {@link AppOpsManager#OP_NONE} to indicate that |
| 122 | * screenshots should never be fetched. |
| 123 | */ |
Wale Ogunwale | a6191b4 | 2018-05-09 07:41:32 -0700 | [diff] [blame] | 124 | public AssistDataRequester(Context context, |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 125 | IWindowManager windowManager, AppOpsManager appOpsManager, |
| 126 | AssistDataRequesterCallbacks callbacks, Object callbacksLock, |
| 127 | int requestStructureAppOps, int requestScreenshotAppOps) { |
| 128 | mCallbacks = callbacks; |
| 129 | mCallbacksLock = callbacksLock; |
| 130 | mWindowManager = windowManager; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 131 | mContext = context; |
| 132 | mAppOpsManager = appOpsManager; |
| 133 | mRequestStructureAppOps = requestStructureAppOps; |
| 134 | mRequestScreenshotAppOps = requestScreenshotAppOps; |
| 135 | } |
| 136 | |
| 137 | /** |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 138 | * Request that autofill data be loaded asynchronously. The resulting data will be provided |
| 139 | * through the {@link AssistDataRequesterCallbacks}. |
| 140 | * |
| 141 | * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String)}. |
| 142 | */ |
| 143 | public void requestAutofillData(List<IBinder> activityTokens, int callingUid, |
| 144 | String callingPackage) { |
| 145 | requestData(activityTokens, true /* requestAutofillData */, |
| 146 | true /* fetchData */, false /* fetchScreenshot */, |
| 147 | true /* allowFetchData */, false /* allowFetchScreenshot */, |
| 148 | callingUid, callingPackage); |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * Request that assist data be loaded asynchronously. The resulting data will be provided |
| 153 | * through the {@link AssistDataRequesterCallbacks}. |
| 154 | * |
| 155 | * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String)}. |
| 156 | */ |
| 157 | public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData, |
| 158 | final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot, |
| 159 | int callingUid, String callingPackage) { |
| 160 | requestData(activityTokens, false /* requestAutofillData */, fetchData, fetchScreenshot, |
| 161 | allowFetchData, allowFetchScreenshot, callingUid, callingPackage); |
| 162 | } |
| 163 | |
| 164 | /** |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 165 | * Request that assist data be loaded asynchronously. The resulting data will be provided |
| 166 | * through the {@link AssistDataRequesterCallbacks}. |
| 167 | * |
| 168 | * @param activityTokens the list of visible activities |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 169 | * @param requestAutofillData if true, will fetch the autofill data, otherwise, will fetch the |
| 170 | * assist context data |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 171 | * @param fetchData whether or not to fetch the assist data, only applies if the caller is |
| 172 | * allowed to fetch the assist data, and the current activity allows assist data to be |
| 173 | * fetched from it |
| 174 | * @param fetchScreenshot whether or not to fetch the screenshot, only applies if fetchData is |
| 175 | * true, the caller is allowed to fetch the assist data, and the current activity allows |
| 176 | * assist data to be fetched from it |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 177 | * @param allowFetchData to be joined with other checks, determines whether or not the requester |
| 178 | * is allowed to fetch the assist data |
| 179 | * @param allowFetchScreenshot to be joined with other checks, determines whether or not the |
| 180 | * requester is allowed to fetch the assist screenshot |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 181 | */ |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 182 | private void requestData(List<IBinder> activityTokens, final boolean requestAutofillData, |
| 183 | final boolean fetchData, final boolean fetchScreenshot, boolean allowFetchData, |
| 184 | boolean allowFetchScreenshot, int callingUid, String callingPackage) { |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 185 | // TODO(b/34090158): Known issue, if the assist data is not allowed on the current activity, |
| 186 | // then no assist data is requested for any of the other activities |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 187 | |
| 188 | // Early exit if there are no activity to fetch for |
| 189 | if (activityTokens.isEmpty()) { |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 190 | // No activities, just dispatch request-complete |
| 191 | tryDispatchRequestComplete(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 192 | return; |
| 193 | } |
| 194 | |
| 195 | // Ensure that the current activity supports assist data |
| 196 | boolean isAssistDataAllowed = false; |
| 197 | try { |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 198 | isAssistDataAllowed = |
| 199 | ActivityTaskManager.getService().isAssistDataAllowedOnCurrentActivity(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 200 | } catch (RemoteException e) { |
| 201 | // Should never happen |
| 202 | } |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 203 | allowFetchData &= isAssistDataAllowed; |
| 204 | allowFetchScreenshot &= fetchData && isAssistDataAllowed |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 205 | && (mRequestScreenshotAppOps != OP_NONE); |
| 206 | |
| 207 | mCanceled = false; |
| 208 | mPendingDataCount = 0; |
| 209 | mPendingScreenshotCount = 0; |
| 210 | mAssistData.clear(); |
| 211 | mAssistScreenshot.clear(); |
| 212 | |
| 213 | if (fetchData) { |
| 214 | if (mAppOpsManager.checkOpNoThrow(mRequestStructureAppOps, callingUid, callingPackage) |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 215 | == MODE_ALLOWED && allowFetchData) { |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 216 | final int numActivities = activityTokens.size(); |
| 217 | for (int i = 0; i < numActivities; i++) { |
| 218 | IBinder topActivity = activityTokens.get(i); |
| 219 | try { |
| 220 | MetricsLogger.count(mContext, "assist_with_context", 1); |
| 221 | Bundle receiverExtras = new Bundle(); |
| 222 | receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i); |
| 223 | receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, numActivities); |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 224 | boolean result = requestAutofillData |
Winson Chung | 91f8c35 | 2018-11-26 13:32:06 -0800 | [diff] [blame] | 225 | ? ActivityTaskManager.getService().requestAutofillData(this, |
| 226 | receiverExtras, topActivity, 0 /* flags */) |
| 227 | : ActivityTaskManager.getService().requestAssistContextExtras( |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 228 | ASSIST_CONTEXT_FULL, this, receiverExtras, topActivity, |
Winson Chung | 91f8c35 | 2018-11-26 13:32:06 -0800 | [diff] [blame] | 229 | /* focused= */ i == 0, /* newSessionId= */ i == 0); |
Winson Chung | 48b2bbd | 2018-11-15 16:02:56 -0800 | [diff] [blame] | 230 | if (result) { |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 231 | mPendingDataCount++; |
| 232 | } else if (i == 0) { |
| 233 | // Wasn't allowed... given that, let's not do the screenshot either. |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 234 | if (mCallbacks.canHandleReceivedAssistDataLocked()) { |
| 235 | dispatchAssistDataReceived(null); |
| 236 | } else { |
| 237 | mAssistData.add(null); |
| 238 | } |
| 239 | allowFetchScreenshot = false; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 240 | break; |
| 241 | } |
| 242 | } catch (RemoteException e) { |
| 243 | // Can't happen |
| 244 | } |
| 245 | } |
| 246 | } else { |
| 247 | // Wasn't allowed... given that, let's not do the screenshot either. |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 248 | if (mCallbacks.canHandleReceivedAssistDataLocked()) { |
| 249 | dispatchAssistDataReceived(null); |
| 250 | } else { |
| 251 | mAssistData.add(null); |
| 252 | } |
| 253 | allowFetchScreenshot = false; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 254 | } |
| 255 | } |
| 256 | |
| 257 | if (fetchScreenshot) { |
| 258 | if (mAppOpsManager.checkOpNoThrow(mRequestScreenshotAppOps, callingUid, callingPackage) |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 259 | == MODE_ALLOWED && allowFetchScreenshot) { |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 260 | try { |
| 261 | MetricsLogger.count(mContext, "assist_with_screen", 1); |
| 262 | mPendingScreenshotCount++; |
| 263 | mWindowManager.requestAssistScreenshot(this); |
| 264 | } catch (RemoteException e) { |
| 265 | // Can't happen |
| 266 | } |
| 267 | } else { |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 268 | if (mCallbacks.canHandleReceivedAssistDataLocked()) { |
| 269 | dispatchAssistScreenshotReceived(null); |
| 270 | } else { |
| 271 | mAssistScreenshot.add(null); |
| 272 | } |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 273 | } |
| 274 | } |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 275 | // For the cases where we dispatch null data/screenshot due to permissions, just dispatch |
| 276 | // request-complete after those are made |
| 277 | tryDispatchRequestComplete(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | /** |
| 281 | * This call should only be made when the callbacks are capable of handling the received assist |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 282 | * data. The owner is also responsible for locking before calling this method. |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 283 | */ |
| 284 | public void processPendingAssistData() { |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 285 | flushPendingAssistData(); |
| 286 | tryDispatchRequestComplete(); |
| 287 | } |
| 288 | |
| 289 | private void flushPendingAssistData() { |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 290 | final int dataCount = mAssistData.size(); |
| 291 | for (int i = 0; i < dataCount; i++) { |
| 292 | dispatchAssistDataReceived(mAssistData.get(i)); |
| 293 | } |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 294 | mAssistData.clear(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 295 | final int screenshotsCount = mAssistScreenshot.size(); |
| 296 | for (int i = 0; i < screenshotsCount; i++) { |
| 297 | dispatchAssistScreenshotReceived(mAssistScreenshot.get(i)); |
| 298 | } |
Winson Chung | 60f493d | 2017-11-01 16:02:22 -0700 | [diff] [blame] | 299 | mAssistScreenshot.clear(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 300 | } |
| 301 | |
| 302 | public int getPendingDataCount() { |
| 303 | return mPendingDataCount; |
| 304 | } |
| 305 | |
| 306 | public int getPendingScreenshotCount() { |
| 307 | return mPendingScreenshotCount; |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * Cancels the current request for the assist data. |
| 312 | */ |
| 313 | public void cancel() { |
| 314 | // Reset the pending data count, if we receive new assist data after this point, it will |
| 315 | // be ignored |
| 316 | mCanceled = true; |
| 317 | mPendingDataCount = 0; |
| 318 | mPendingScreenshotCount = 0; |
| 319 | mAssistData.clear(); |
| 320 | mAssistScreenshot.clear(); |
| 321 | } |
| 322 | |
| 323 | @Override |
| 324 | public void onHandleAssistData(Bundle data) { |
| 325 | synchronized (mCallbacksLock) { |
| 326 | if (mCanceled) { |
| 327 | return; |
| 328 | } |
| 329 | mPendingDataCount--; |
| 330 | |
| 331 | if (mCallbacks.canHandleReceivedAssistDataLocked()) { |
| 332 | // Process any pending data and dispatch the new data as well |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 333 | flushPendingAssistData(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 334 | dispatchAssistDataReceived(data); |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 335 | tryDispatchRequestComplete(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 336 | } else { |
| 337 | // Queue up the data for processing later |
| 338 | mAssistData.add(data); |
| 339 | } |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | @Override |
| 344 | public void onHandleAssistScreenshot(Bitmap screenshot) { |
| 345 | synchronized (mCallbacksLock) { |
| 346 | if (mCanceled) { |
| 347 | return; |
| 348 | } |
| 349 | mPendingScreenshotCount--; |
| 350 | |
| 351 | if (mCallbacks.canHandleReceivedAssistDataLocked()) { |
| 352 | // Process any pending data and dispatch the new data as well |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 353 | flushPendingAssistData(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 354 | dispatchAssistScreenshotReceived(screenshot); |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 355 | tryDispatchRequestComplete(); |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 356 | } else { |
| 357 | // Queue up the data for processing later |
| 358 | mAssistScreenshot.add(screenshot); |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | private void dispatchAssistDataReceived(Bundle data) { |
| 364 | int activityIndex = 0; |
| 365 | int activityCount = 0; |
Winson Chung | ec1ef09 | 2017-10-25 16:22:34 -0700 | [diff] [blame] | 366 | final Bundle receiverExtras = data != null |
| 367 | ? data.getBundle(ASSIST_KEY_RECEIVER_EXTRAS) : null; |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 368 | if (receiverExtras != null) { |
| 369 | activityIndex = receiverExtras.getInt(KEY_RECEIVER_EXTRA_INDEX); |
| 370 | activityCount = receiverExtras.getInt(KEY_RECEIVER_EXTRA_COUNT); |
| 371 | } |
| 372 | mCallbacks.onAssistDataReceivedLocked(data, activityIndex, activityCount); |
| 373 | } |
| 374 | |
| 375 | private void dispatchAssistScreenshotReceived(Bitmap screenshot) { |
| 376 | mCallbacks.onAssistScreenshotReceivedLocked(screenshot); |
| 377 | } |
| 378 | |
Winson Chung | 397967f | 2017-11-01 16:21:35 -0700 | [diff] [blame] | 379 | private void tryDispatchRequestComplete() { |
| 380 | if (mPendingDataCount == 0 && mPendingScreenshotCount == 0 && |
| 381 | mAssistData.isEmpty() && mAssistScreenshot.isEmpty()) { |
| 382 | mCallbacks.onAssistRequestCompleted(); |
| 383 | } |
| 384 | } |
| 385 | |
Winson Chung | da2818f | 2017-10-23 16:25:49 -0700 | [diff] [blame] | 386 | public void dump(String prefix, PrintWriter pw) { |
| 387 | pw.print(prefix); pw.print("mPendingDataCount="); pw.println(mPendingDataCount); |
| 388 | pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData); |
| 389 | pw.print(prefix); pw.print("mPendingScreenshotCount="); pw.println(mPendingScreenshotCount); |
| 390 | pw.print(prefix); pw.print("mAssistScreenshot="); pw.println(mAssistScreenshot); |
| 391 | } |
| 392 | } |