/** * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.voice; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.Activity; import android.app.ActivityOptions; import android.app.Dialog; import android.app.DirectAction; import android.app.Instrumentation; import android.app.VoiceInteractor; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Handler; import android.os.IBinder; import android.os.ICancellationSignal; import android.os.Message; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.service.voice.flags.Flags; import android.util.ArrayMap; import android.util.DebugUtils; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.FrameLayout; import com.android.internal.annotations.Immutable; import com.android.internal.app.IVoiceInteractionManagerService; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractorCallback; import com.android.internal.app.IVoiceInteractorRequest; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; import com.android.internal.util.function.pooled.PooledLambda; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * An active voice interaction session, providing a facility for the implementation * to interact with the user in the voice interaction layer. The user interface is * initially shown by default, and can be created by overriding {@link #onCreateContentView()} * in which the UI can be built. * *
A voice interaction session can be self-contained, ultimately calling {@link #finish} * when done. It can also initiate voice interactions with applications by calling * {@link #startVoiceActivity}
. */ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCallbacks2 { static final String TAG = "VoiceInteractionSession"; static final boolean DEBUG = false; /** * Flag received in {@link #onShow}: originator requested that the session be started with * assist data from the currently focused activity. */ public static final int SHOW_WITH_ASSIST = 1<<0; /** * Flag received in {@link #onShow}: originator requested that the session be started with * a screen shot of the currently focused activity. */ public static final int SHOW_WITH_SCREENSHOT = 1<<1; /** * Flag for use with {@link #onShow}: indicates that the session has been started from the * system assist gesture. */ public static final int SHOW_SOURCE_ASSIST_GESTURE = 1<<2; /** * Flag for use with {@link #onShow}: indicates that the application itself has invoked * the assistant. */ public static final int SHOW_SOURCE_APPLICATION = 1<<3; /** * Flag for use with {@link #onShow}: indicates that an Activity has invoked the voice * interaction service for a local interaction using * {@link Activity#startLocalVoiceInteraction(Bundle)}. */ public static final int SHOW_SOURCE_ACTIVITY = 1<<4; /** * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked * from a physical button. */ public static final int SHOW_SOURCE_PUSH_TO_TALK = 1 << 5; /** * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked * from a notification. */ public static final int SHOW_SOURCE_NOTIFICATION = 1 << 6; /** * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked * from an Android automotive system UI. */ public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_START = 1; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_RESUME = 2; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE = 3; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_STOP = 4; /** @hide */ @IntDef(prefix = { "VOICE_INTERACTION_ACTIVITY_EVENT_" }, value = { VOICE_INTERACTION_ACTIVITY_EVENT_START, VOICE_INTERACTION_ACTIVITY_EVENT_RESUME, VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE, VOICE_INTERACTION_ACTIVITY_EVENT_STOP }) @Retention(RetentionPolicy.SOURCE) public @interface VoiceInteractionActivityEventType{} /** * Bundle key used to specify the id when the system prepares to show session. It increases for * each request. ** Type: int *
* @see VoiceInteractionService#showSession(Bundle, int) * @see VoiceInteractionService#onPrepareToShowSession(Bundle, int) * @see VoiceInteractionService#onShowSessionFailed(Bundle) * @see #onShow(Bundle, int) * @see #show(Bundle, int) */ public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID"; /** * Bundle key used to specify foreground activity app components. ** Type: ArrayList<ComponentName> *
* @see #onShow(Bundle, int) */ @FlaggedApi(Flags.FLAG_ALLOW_FOREGROUND_ACTIVITIES_IN_ON_SHOW) public static final String KEY_FOREGROUND_ACTIVITIES = "android.service.voice.FOREGROUND_ACTIVITIES"; final Context mContext; final HandlerCaller mHandlerCaller; final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState(); IVoiceInteractionManagerService mSystemService; IBinder mToken; int mTheme = 0; LayoutInflater mInflater; TypedArray mThemeAttrs; View mRootView; FrameLayout mContentFrame; VoiceInteractionWindow mWindow; boolean mUiEnabled = true; boolean mInitialized; boolean mWindowAdded; boolean mWindowVisible; boolean mWindowWasVisible; boolean mInShowWindow; final ArrayMapThe newly started activity will be displayed to the user in a special way, as * a layer under the voice interaction UI.
* *As the voice activity runs, it can retrieve a {@link android.app.VoiceInteractor} * through which it can perform voice interactions through your session. These requests * for voice interactions will appear as callbacks on {@link #onGetSupportedCommands}, * {@link #onRequestConfirmation}, {@link #onRequestPickOption}, * {@link #onRequestCompleteVoice}, {@link #onRequestAbortVoice}, * or {@link #onRequestCommand} * *
You will receive a call to {@link #onTaskStarted} when the task starts up * and {@link #onTaskFinished} when the last activity has finished. * * @param intent The Intent to start this voice interaction. The given Intent will * always have {@link Intent#CATEGORY_VOICE Intent.CATEGORY_VOICE} added to it, since * this is part of a voice interaction. */ public void startVoiceActivity(Intent intent) { if (mToken == null) { throw new IllegalStateException("Can't call before onCreate()"); } try { intent.migrateExtraStreamToClipData(mContext); intent.prepareToLeaveProcess(mContext); int res = mSystemService.startVoiceActivity(mToken, intent, intent.resolveType(mContext.getContentResolver()), mContext.getAttributionTag()); Instrumentation.checkStartActivityResult(res, intent); } catch (RemoteException e) { } } /** *
Ask that a new assistant activity be started. This will create a new task in the * in activity manager: this means that * {@link Intent#FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_NEW_TASK} * will be set for you to make it a new task.
* *The newly started activity will be displayed on top of other activities in the system * in a new layer that is not affected by multi-window mode. Tasks started from this activity * will go into the normal activity layer and not this new layer.
* *By default, the system will create a window for the UI for this session. If you are using * an assistant activity instead, then you can disable the window creation by calling * {@link #setUiEnabled} in {@link #onPrepareShow(Bundle, int)}.
* * NOTE: if the app would like to override some options to start the Activity, * use {@link #startAssistantActivity(Intent, Bundle)} instead. */ public void startAssistantActivity(Intent intent) { startAssistantActivity(intent, ActivityOptions.makeBasic().toBundle()); } /** *Ask that a new assistant activity be started. This will create a new task in the * in activity manager: this means that * {@link Intent#FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_NEW_TASK} * will be set for you to make it a new task.
* *The newly started activity will be displayed on top of other activities in the system * in a new layer that is not affected by multi-window mode. Tasks started from this activity * will go into the normal activity layer and not this new layer.
* *By default, the system will create a window for the UI for this session. If you are using * an assistant activity instead, then you can disable the window creation by calling * {@link #setUiEnabled} in {@link #onPrepareShow(Bundle, int)}.
* * @param intent the intent used to start an assistant activity * @param bundle Additional options for how the Activity should be started. See * {@link ActivityOptions} for how to build the Bundle supplied here. */ public void startAssistantActivity(@NonNull Intent intent, @NonNull Bundle bundle) { Objects.requireNonNull(bundle); if (mToken == null) { throw new IllegalStateException("Can't call before onCreate()"); } try { intent.migrateExtraStreamToClipData(mContext); intent.prepareToLeaveProcess(mContext); int res = mSystemService.startAssistantActivity(mToken, intent, intent.resolveType(mContext.getContentResolver()), mContext.getAttributionTag(), bundle); Instrumentation.checkStartActivityResult(res, intent); } catch (RemoteException e) { } } /** * Requests a list of supported actions from an app. * * @param activityId Ths activity id of the app to get the actions from. * @param cancellationSignal A signal to cancel the operation in progress, * or {@code null} if none. * @param resultExecutor The handler to receive the callback. * @param callback The callback to receive the response. */ public final void requestDirectActions(@NonNull ActivityId activityId, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor resultExecutor, @NonNull Consumer An action could take time to execute and the result is provided asynchronously
* via a callback. If the action is taking longer and you want to cancel its execution
* you can pass in a cancellation signal through which to notify the app to abort the
* action.
*
* @param action The action to be performed.
* @param extras Any optional extras sent to the app as part of the request
* @param cancellationSignal A signal to cancel the operation in progress,
* or {@code null} if none.
* @param resultExecutor The handler to receive the callback.
* @param resultListener The callback to receive the response.
*
* @see #requestDirectActions(ActivityId, CancellationSignal, Executor, Consumer)
* @see Activity#onGetDirectActions(CancellationSignal, Consumer)
*/
public final void performDirectAction(@NonNull DirectAction action, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal,
@NonNull @CallbackExecutor Executor resultExecutor,
@NonNull Consumer Passing false here will release the wake lock, and you can call later with
* true to re-acquire it. It will also be automatically re-acquired for you each
* time you start a new voice activity task -- that is when you call
* {@link #startVoiceActivity}. This method is called for all activities along with an index and count that indicates
* which activity the data is for. {@code index} will be between 0 and {@code count}-1 and
* this method is called once for each activity in no particular order. The {@code count}
* indicates how many activities to expect assist data for, including the top focused one.
* The focused activity can be determined by calling {@link AssistState#isFocused()}.
*
* To be responsive to assist requests, process assist data as soon as it is received,
* without waiting for all queued activities to return assist data.
*
* @param state The state object capturing the state of an activity.
*/
public void onHandleAssist(@NonNull AssistState state) {
if (state.getAssistData() == null && state.getAssistStructure() == null
&& state.getAssistContent() == null) {
return;
} else if (state.getIndex() == 0) {
onHandleAssist(state.getAssistData(), state.getAssistStructure(),
state.getAssistContent());
} else {
onHandleAssistSecondary(state.getAssistData(), state.getAssistStructure(),
state.getAssistContent(), state.getIndex(), state.getCount());
}
}
/**
* Called to receive data from other applications that the user was or is interacting with,
* that are currently on the screen in a multi-window display environment, not including the
* currently focused activity. This could be
* a free-form window, a picture-in-picture window, or another window in a split-screen display.
*
* This method is very similar to
* {@link #onHandleAssist} except that it is called
* for additional non-focused activities along with an index and count that indicates
* which additional activity the data is for. {@code index} will be between 1 and
* {@code count}-1 and this method is called once for each additional window, in no particular
* order. The {@code count} indicates how many windows to expect assist data for, including the
* top focused activity, which continues to be returned via {@link #onHandleAssist}.
*
* To be responsive to assist requests, process assist data as soon as it is received,
* without waiting for all queued activities to return assist data.
*
* @param data Arbitrary data supplied by the app through
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
* May be null if assist data has been disabled by the user or device policy.
* @param structure If available, the structure definition of all windows currently
* displayed by the app. May be null if assist data has been disabled by the user
* or device policy; will be an empty stub if the application has disabled assist
* by marking its window as secure.
* @param content Additional content data supplied by the app through
* {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
* May be null if assist data has been disabled by the user or device policy; will
* not be automatically filled in with data from the app if the app has marked its
* window as secure.
* @param index the index of the additional activity that this data
* is for.
* @param count the total number of additional activities for which the assist data is being
* returned, including the focused activity that is returned via
* {@link #onHandleAssist}.
*
* @deprecated use {@link #onHandleAssist(AssistState)}
*/
@Deprecated
public void onHandleAssistSecondary(@Nullable Bundle data, @Nullable AssistStructure structure,
@Nullable AssistContent content, int index, int count) {
}
/**
* Called to receive a screenshot of what the user was currently viewing when an assist
* session is started. May be null if screenshots are disabled by the user, policy,
* or application. If the original show request did not specify
* {@link #SHOW_WITH_SCREENSHOT}, this method will not be called.
*/
public void onHandleScreenshot(@Nullable Bitmap screenshot) {
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
return false;
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
return false;
}
public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
return false;
}
/**
* Called when the user presses the back button while focus is in the session UI. Note
* that this will only happen if the session UI has requested input focus in its window;
* otherwise, the back key will go to whatever window has focus and do whatever behavior
* it normally has there. The default implementation simply calls {@link #hide}.
*/
public void onBackPressed() {
hide();
}
/**
* Sessions automatically watch for requests that all system UI be closed (such as when
* the user presses HOME), which will appear here. The default implementation always
* calls {@link #hide}.
*/
public void onCloseSystemDialogs() {
hide();
}
/**
* Called when the lockscreen was shown.
*/
public void onLockscreenShown() {
hide();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
/**
* Compute the interesting insets into your UI. The default implementation
* sets {@link Insets#contentInsets outInsets.contentInsets.top} to the height
* of the window, meaning it should not adjust content underneath. The default touchable
* insets are {@link Insets#TOUCHABLE_INSETS_FRAME}, meaning it consumes all touch
* events within its window frame.
*
* @param outInsets Fill in with the current UI insets.
*/
public void onComputeInsets(Insets outInsets) {
outInsets.contentInsets.left = 0;
outInsets.contentInsets.bottom = 0;
outInsets.contentInsets.right = 0;
View decor = getWindow().getWindow().getDecorView();
outInsets.contentInsets.top = decor.getHeight();
outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_FRAME;
outInsets.touchableRegion.setEmpty();
}
/**
* Called when a task initiated by {@link #startVoiceActivity(android.content.Intent)}
* has actually started.
*
* @param intent The original {@link Intent} supplied to
* {@link #startVoiceActivity(android.content.Intent)}.
* @param taskId Unique ID of the now running task.
*/
public void onTaskStarted(Intent intent, int taskId) {
}
/**
* Called when the last activity of a task initiated by
* {@link #startVoiceActivity(android.content.Intent)} has finished. The default
* implementation calls {@link #finish()} on the assumption that this represents
* the completion of a voice action. You can override the implementation if you would
* like a different behavior.
*
* @param intent The original {@link Intent} supplied to
* {@link #startVoiceActivity(android.content.Intent)}.
* @param taskId Unique ID of the finished task.
*/
public void onTaskFinished(Intent intent, int taskId) {
hide();
}
/**
* Request to query for what extended commands the session supports.
*
* @param commands An array of commands that are being queried.
* @return Return an array of booleans indicating which of each entry in the
* command array is supported. A true entry in the array indicates the command
* is supported; false indicates it is not. The default implementation returns
* an array of all false entries.
*/
public boolean[] onGetSupportedCommands(String[] commands) {
return new boolean[commands.length];
}
/**
* Request to confirm with the user before proceeding with an unrecoverable operation,
* corresponding to a {@link android.app.VoiceInteractor.ConfirmationRequest
* VoiceInteractor.ConfirmationRequest}.
*
* @param request The active request.
*/
public void onRequestConfirmation(ConfirmationRequest request) {
}
/**
* Request for the user to pick one of N options, corresponding to a
* {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
*
* @param request The active request.
*/
public void onRequestPickOption(PickOptionRequest request) {
}
/**
* Request to complete the voice interaction session because the voice activity successfully
* completed its interaction using voice. Corresponds to
* {@link android.app.VoiceInteractor.CompleteVoiceRequest
* VoiceInteractor.CompleteVoiceRequest}. The default implementation just sends an empty
* confirmation back to allow the activity to exit.
*
* @param request The active request.
*/
public void onRequestCompleteVoice(CompleteVoiceRequest request) {
}
/**
* Request to abort the voice interaction session because the voice activity can not
* complete its interaction using voice. Corresponds to
* {@link android.app.VoiceInteractor.AbortVoiceRequest
* VoiceInteractor.AbortVoiceRequest}. The default implementation just sends an empty
* confirmation back to allow the activity to exit.
*
* @param request The active request.
*/
public void onRequestAbortVoice(AbortVoiceRequest request) {
}
/**
* Process an arbitrary extended command from the caller,
* corresponding to a {@link android.app.VoiceInteractor.CommandRequest
* VoiceInteractor.CommandRequest}.
*
* @param request The active request.
*/
public void onRequestCommand(CommandRequest request) {
}
/**
* Called when the {@link android.app.VoiceInteractor} has asked to cancel a {@link Request}
* that was previously delivered to {@link #onRequestConfirmation},
* {@link #onRequestPickOption}, {@link #onRequestCompleteVoice}, {@link #onRequestAbortVoice},
* or {@link #onRequestCommand}.
*
* @param request The request that is being canceled.
*/
public void onCancelRequest(Request request) {
}
/**
* Registers a callback that will be notified when visible activities have been changed.
*
* Note: The {@link VisibleActivityCallback#onVisible(VisibleActivityInfo)} will be called
* immediately with current visible activities when the callback is registered for the first
* time. If the callback is already registered, this method does nothing.
*
* @param executor The executor which will be used to invoke the callback.
* @param callback The callback to receive the response.
*
* @throws IllegalStateException if calling this method before onCreate().
*/
public final void registerVisibleActivityCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull VisibleActivityCallback callback) {
if (DEBUG) {
Log.d(TAG, "registerVisibleActivityCallback");
}
if (mToken == null) {
throw new IllegalStateException("Can't call before onCreate()");
}
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
mHandlerCaller.sendMessage(
mHandlerCaller.obtainMessageOO(MSG_REGISTER_VISIBLE_ACTIVITY_CALLBACK, executor,
callback));
}
/**
* Unregisters the callback.
*
* @param callback The callback to receive the response.
*/
public final void unregisterVisibleActivityCallback(@NonNull VisibleActivityCallback callback) {
if (DEBUG) {
Log.d(TAG, "unregisterVisibleActivityCallback");
}
Objects.requireNonNull(callback);
mHandlerCaller.sendMessage(
mHandlerCaller.obtainMessageO(MSG_UNREGISTER_VISIBLE_ACTIVITY_CALLBACK, callback));
}
/**
* Print the Service's state into the given stream. This gets invoked by
* {@link VoiceInteractionSessionService} when its Service
* {@link android.app.Service#dump} method is called.
*
* @param prefix Text to print at the front of each line.
* @param fd The raw file descriptor that the dump is being sent to.
* @param writer The PrintWriter to which you should dump your state. This will be
* closed for you after you return.
* @param args additional arguments to the dump request.
*/
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
writer.print(prefix); writer.print("mToken="); writer.println(mToken);
writer.print(prefix); writer.print("mTheme=#"); writer.println(Integer.toHexString(mTheme));
writer.print(prefix); writer.print("mUiEnabled="); writer.println(mUiEnabled);
writer.print(" mInitialized="); writer.println(mInitialized);
writer.print(prefix); writer.print("mWindowAdded="); writer.print(mWindowAdded);
writer.print(" mWindowVisible="); writer.println(mWindowVisible);
writer.print(prefix); writer.print("mWindowWasVisible="); writer.print(mWindowWasVisible);
writer.print(" mInShowWindow="); writer.println(mInShowWindow);
if (mActiveRequests.size() > 0) {
writer.print(prefix); writer.println("Active requests:");
String innerPrefix = prefix + " ";
for (int i=0; i
*
*
* @param showFlags The show flags originally provided to
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
*/
public void onShow(@Nullable Bundle args, int showFlags) {
}
/**
* Called immediately after stopping to show the session UI.
*/
public void onHide() {
}
/**
* Last callback to the session as it is being finished.
*/
public void onDestroy() {
}
/**
* Hook in which to create the session's UI.
*/
public View onCreateContentView() {
return null;
}
public void setContentView(View view) {
ensureWindowCreated();
mContentFrame.removeAllViews();
mContentFrame.addView(view, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentFrame.requestApplyInsets();
}
void doOnHandleAssist(int taskId, IBinder assistToken, Bundle data, AssistStructure structure,
Throwable failure, AssistContent content, int index, int count) {
if (failure != null) {
onAssistStructureFailure(failure);
}
AssistState assistState = new AssistState(new ActivityId(taskId, assistToken),
data, structure, content, index, count);
onHandleAssist(assistState);
}
/**
* Called when there has been a failure transferring the {@link AssistStructure} to
* the assistant. This may happen, for example, if the data is too large and results
* in an out of memory exception, the data has been cleared during transferring due to
* the new incoming assist data, or the client has provided corrupt data. This will be
* called immediately before {@link #onHandleAssist} and the AssistStructure supplied
* there afterwards will be null.
*
* @param failure The failure exception that was thrown when building the
* {@link AssistStructure}.
*/
public void onAssistStructureFailure(Throwable failure) {
}
/**
* Called to receive data from the application that the user was currently viewing when
- * an assist session is started. If the original show request did not specify
* {@link #SHOW_WITH_ASSIST}, this method will not be called.
*
* @param data Arbitrary data supplied by the app through
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
* May be null if assist data has been disabled by the user or device policy.
* @param structure If available, the structure definition of all windows currently
* displayed by the app. May be null if assist data has been disabled by the user
* or device policy; will be an empty stub if the application has disabled assist
* by marking its window as secure.
* @param content Additional content data supplied by the app through
* {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
* May be null if assist data has been disabled by the user or device policy; will
* not be automatically filled in with data from the app if the app has marked its
* window as secure.
*
* @deprecated use {@link #onHandleAssist(AssistState)}
*/
@Deprecated
public void onHandleAssist(@Nullable Bundle data, @Nullable AssistStructure structure,
@Nullable AssistContent content) {
}
/**
* Called to receive data from the application that the user was currently viewing when
* an assist session is started. If the original show request did not specify
* {@link #SHOW_WITH_ASSIST}, {@link AssistState} parameter will only provide
* {@link ActivityId}. If there was a failure to write the assist data to
* {@link AssistStructure}, the {@link AssistState#getAssistStructure()} will return null.
*
*