Merge "Address API council feedback" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1a5d1728af
@@ -3763,7 +3763,7 @@ package android.app {
|
||||
method public void onDetachedFromWindow();
|
||||
method public void onEnterAnimationComplete();
|
||||
method public boolean onGenericMotionEvent(android.view.MotionEvent);
|
||||
method @NonNull public java.util.List<android.app.DirectAction> onGetDirectActions();
|
||||
method public void onGetDirectActions(@NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.DirectAction>>);
|
||||
method public boolean onKeyDown(int, android.view.KeyEvent);
|
||||
method public boolean onKeyLongPress(int, android.view.KeyEvent);
|
||||
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
|
||||
@@ -3783,7 +3783,7 @@ package android.app {
|
||||
method public void onOptionsMenuClosed(android.view.Menu);
|
||||
method public void onPanelClosed(int, @NonNull android.view.Menu);
|
||||
method @CallSuper protected void onPause();
|
||||
method public void onPerformDirectAction(@NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.os.Bundle>);
|
||||
method public void onPerformDirectAction(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.os.Bundle>);
|
||||
method public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
|
||||
method @Deprecated public void onPictureInPictureModeChanged(boolean);
|
||||
method @CallSuper protected void onPostCreate(@Nullable android.os.Bundle);
|
||||
@@ -41833,7 +41833,7 @@ package android.service.voice {
|
||||
method public void onTaskStarted(android.content.Intent, int);
|
||||
method public void onTrimMemory(int);
|
||||
method public final void performDirectAction(@NonNull android.app.DirectAction, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.os.Bundle>);
|
||||
method public final void requestDirectActions(@NonNull android.service.voice.VoiceInteractionSession.ActivityId, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.DirectAction>>);
|
||||
method public final void requestDirectActions(@NonNull android.service.voice.VoiceInteractionSession.ActivityId, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.DirectAction>>);
|
||||
method public void setContentView(android.view.View);
|
||||
method public void setDisabledShowContext(int);
|
||||
method public void setKeepAwake(boolean);
|
||||
|
||||
@@ -2340,12 +2340,20 @@ public class Activity extends ContextThemeWrapper
|
||||
* <p>This method will be called only after {@link #onStart()} is being called and
|
||||
* before {@link #onStop()} is being called.
|
||||
*
|
||||
* @return The currently supported direct actions which cannot be <code>null</code>
|
||||
* or contain <code>null</null> elements.
|
||||
* <p>You should pass to the callback the currently supported direct actions which
|
||||
* cannot be <code>null</code> or contain <code>null</null> elements.
|
||||
*
|
||||
* <p>You should return the action list as soon as possible to ensure the consumer,
|
||||
* for example the assistant, is as responsive as possible which would improve user
|
||||
* experience of your app.
|
||||
*
|
||||
* @param cancellationSignal A signal to cancel the operation in progress.
|
||||
* @param callback The callback to send the action list. The actions list cannot
|
||||
* contain <code>null</code> elements.
|
||||
*/
|
||||
@NonNull
|
||||
public List<DirectAction> onGetDirectActions() {
|
||||
return Collections.emptyList();
|
||||
public void onGetDirectActions(@NonNull CancellationSignal cancellationSignal,
|
||||
@NonNull Consumer<List<DirectAction>> callback) {
|
||||
callback.accept(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2354,14 +2362,13 @@ public class Activity extends ContextThemeWrapper
|
||||
*
|
||||
* @param actionId The ID for the action
|
||||
* @param arguments Any additional arguments provided by the caller
|
||||
* @param cancellationSignal A signal to cancel the operation in progress, or {@code null}
|
||||
* if none.
|
||||
* @param cancellationSignal A signal to cancel the operation in progress.
|
||||
* @param resultListener The callback to provide the result back to the caller
|
||||
*
|
||||
* @see #onGetDirectActions()
|
||||
* @see #onGetDirectActions(CancellationSignal, Consumer)
|
||||
*/
|
||||
public void onPerformDirectAction(@NonNull String actionId,
|
||||
@Nullable Bundle arguments, @Nullable CancellationSignal cancellationSignal,
|
||||
@NonNull Bundle arguments, @NonNull CancellationSignal cancellationSignal,
|
||||
@NonNull Consumer<Bundle> resultListener) { }
|
||||
|
||||
/**
|
||||
|
||||
@@ -392,6 +392,10 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
private final ResourcesManager mResourcesManager;
|
||||
|
||||
// Registry of remote cancellation transports pending a reply with reply handles.
|
||||
@GuardedBy("this")
|
||||
private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;
|
||||
|
||||
private static final class ProviderKey {
|
||||
final String authority;
|
||||
final int userId;
|
||||
@@ -1657,32 +1661,85 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
|
||||
@Override
|
||||
public void requestDirectActions(@NonNull IBinder activityToken,
|
||||
@NonNull IVoiceInteractor interactor, @NonNull RemoteCallback callback) {
|
||||
mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
|
||||
ActivityThread.this, activityToken, interactor, callback));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performDirectAction(IBinder activityToken, String actionId, Bundle arguments,
|
||||
RemoteCallback cancellationCallback, RemoteCallback resultCallback) {
|
||||
final CancellationSignal cancellationSignal;
|
||||
@NonNull IVoiceInteractor interactor, @Nullable RemoteCallback cancellationCallback,
|
||||
@NonNull RemoteCallback callback) {
|
||||
final CancellationSignal cancellationSignal = new CancellationSignal();
|
||||
if (cancellationCallback != null) {
|
||||
final ICancellationSignal transport = CancellationSignal.createTransport();
|
||||
cancellationSignal = CancellationSignal.fromTransport(transport);
|
||||
final ICancellationSignal transport = createSafeCancellationTransport(
|
||||
cancellationSignal);
|
||||
final Bundle cancellationResult = new Bundle();
|
||||
cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
|
||||
transport.asBinder());
|
||||
cancellationCallback.sendResult(cancellationResult);
|
||||
} else {
|
||||
cancellationSignal = new CancellationSignal();
|
||||
}
|
||||
mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
|
||||
ActivityThread.this, activityToken, interactor, cancellationSignal, callback));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performDirectAction(@NonNull IBinder activityToken, @NonNull String actionId,
|
||||
@Nullable Bundle arguments, @Nullable RemoteCallback cancellationCallback,
|
||||
@NonNull RemoteCallback resultCallback) {
|
||||
final CancellationSignal cancellationSignal = new CancellationSignal();
|
||||
if (cancellationCallback != null) {
|
||||
final ICancellationSignal transport = createSafeCancellationTransport(
|
||||
cancellationSignal);
|
||||
final Bundle cancellationResult = new Bundle();
|
||||
cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
|
||||
transport.asBinder());
|
||||
cancellationCallback.sendResult(cancellationResult);
|
||||
}
|
||||
mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handlePerformDirectAction,
|
||||
ActivityThread.this, activityToken, actionId, arguments,
|
||||
cancellationSignal, resultCallback));
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull SafeCancellationTransport createSafeCancellationTransport(
|
||||
@NonNull CancellationSignal cancellationSignal) {
|
||||
synchronized (ActivityThread.this) {
|
||||
if (mRemoteCancellations == null) {
|
||||
mRemoteCancellations = new ArrayMap<>();
|
||||
}
|
||||
final SafeCancellationTransport transport = new SafeCancellationTransport(
|
||||
this, cancellationSignal);
|
||||
mRemoteCancellations.put(transport, cancellationSignal);
|
||||
return transport;
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull CancellationSignal removeSafeCancellationTransport(
|
||||
@NonNull SafeCancellationTransport transport) {
|
||||
synchronized (ActivityThread.this) {
|
||||
final CancellationSignal cancellation = mRemoteCancellations.remove(transport);
|
||||
if (mRemoteCancellations.isEmpty()) {
|
||||
mRemoteCancellations = null;
|
||||
}
|
||||
return cancellation;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SafeCancellationTransport extends ICancellationSignal.Stub {
|
||||
private final @NonNull WeakReference<ActivityThread> mWeakActivityThread;
|
||||
|
||||
SafeCancellationTransport(@NonNull ActivityThread activityThread,
|
||||
@NonNull CancellationSignal cancellation) {
|
||||
mWeakActivityThread = new WeakReference<>(activityThread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
final ActivityThread activityThread = mWeakActivityThread.get();
|
||||
if (activityThread != null) {
|
||||
final CancellationSignal cancellation = activityThread
|
||||
.removeSafeCancellationTransport(this);
|
||||
if (cancellation != null) {
|
||||
cancellation.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class H extends Handler {
|
||||
public static final int BIND_APPLICATION = 110;
|
||||
@UnsupportedAppUsage
|
||||
@@ -3491,27 +3548,31 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
|
||||
/** Fetches the user actions for the corresponding activity */
|
||||
private void handleRequestDirectActions(@NonNull IBinder activityToken,
|
||||
@NonNull IVoiceInteractor interactor, @NonNull RemoteCallback callback) {
|
||||
@NonNull IVoiceInteractor interactor, @NonNull CancellationSignal cancellationSignal,
|
||||
@NonNull RemoteCallback callback) {
|
||||
final ActivityClientRecord r = mActivities.get(activityToken);
|
||||
if (r != null) {
|
||||
final int lifecycleState = r.getLifecycleState();
|
||||
if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
|
||||
callback.sendResult(null);
|
||||
return;
|
||||
if (r == null) {
|
||||
callback.sendResult(null);
|
||||
return;
|
||||
}
|
||||
final int lifecycleState = r.getLifecycleState();
|
||||
if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
|
||||
callback.sendResult(null);
|
||||
return;
|
||||
}
|
||||
if (r.activity.mVoiceInteractor == null
|
||||
|| r.activity.mVoiceInteractor.mInteractor.asBinder()
|
||||
!= interactor.asBinder()) {
|
||||
if (r.activity.mVoiceInteractor != null) {
|
||||
r.activity.mVoiceInteractor.destroy();
|
||||
}
|
||||
if (r.activity.mVoiceInteractor == null
|
||||
|| r.activity.mVoiceInteractor.mInteractor.asBinder()
|
||||
!= interactor.asBinder()) {
|
||||
if (r.activity.mVoiceInteractor != null) {
|
||||
r.activity.mVoiceInteractor.destroy();
|
||||
}
|
||||
r.activity.mVoiceInteractor = new VoiceInteractor(interactor, r.activity,
|
||||
r.activity, Looper.myLooper());
|
||||
}
|
||||
final List<DirectAction> actions = r.activity.onGetDirectActions();
|
||||
r.activity.mVoiceInteractor = new VoiceInteractor(interactor, r.activity,
|
||||
r.activity, Looper.myLooper());
|
||||
}
|
||||
r.activity.onGetDirectActions(cancellationSignal, (actions) -> {
|
||||
Preconditions.checkNotNull(actions);
|
||||
Preconditions.checkCollectionElementsNotNull(actions, "actions");
|
||||
if (actions != null && !actions.isEmpty()) {
|
||||
if (!actions.isEmpty()) {
|
||||
final int actionCount = actions.size();
|
||||
for (int i = 0; i < actionCount; i++) {
|
||||
final DirectAction action = actions.get(i);
|
||||
@@ -3521,9 +3582,10 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
result.putParcelable(DirectAction.KEY_ACTIONS_LIST,
|
||||
new ParceledListSlice<>(actions));
|
||||
callback.sendResult(result);
|
||||
} else {
|
||||
callback.sendResult(null);
|
||||
}
|
||||
}
|
||||
callback.sendResult(null);
|
||||
});
|
||||
}
|
||||
|
||||
/** Performs an actions in the corresponding activity */
|
||||
@@ -3539,16 +3601,11 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
return;
|
||||
}
|
||||
final Bundle nonNullArguments = (arguments != null) ? arguments : Bundle.EMPTY;
|
||||
final WeakReference<RemoteCallback> weakCallback = new WeakReference<>(resultCallback);
|
||||
r.activity.onPerformDirectAction(actionId, nonNullArguments, cancellationSignal,
|
||||
(b) -> {
|
||||
final RemoteCallback strongCallback = weakCallback.get();
|
||||
if (strongCallback != null) {
|
||||
strongCallback.sendResult(b);
|
||||
}
|
||||
});
|
||||
resultCallback::sendResult);
|
||||
} else {
|
||||
resultCallback.sendResult(null);
|
||||
}
|
||||
resultCallback.sendResult(null);
|
||||
}
|
||||
|
||||
public void handleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
|
||||
|
||||
@@ -141,7 +141,7 @@ oneway interface IApplicationThread {
|
||||
void setNetworkBlockSeq(long procStateSeq);
|
||||
void scheduleTransaction(in ClientTransaction transaction);
|
||||
void requestDirectActions(IBinder activityToken, IVoiceInteractor intractor,
|
||||
in RemoteCallback callback);
|
||||
in RemoteCallback cancellationCallback, in RemoteCallback callback);
|
||||
void performDirectAction(IBinder activityToken, String actionId,
|
||||
in Bundle arguments, in RemoteCallback cancellationCallback,
|
||||
in RemoteCallback resultCallback);
|
||||
|
||||
@@ -76,6 +76,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -171,6 +172,9 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
final WeakReference<VoiceInteractionSession> mWeakRef
|
||||
= new WeakReference<VoiceInteractionSession>(this);
|
||||
|
||||
// Registry of remote callbacks pending a reply with reply handles.
|
||||
final Map<SafeResultListener, Consumer<Bundle>> mRemoteCallbacks = new ArrayMap<>();
|
||||
|
||||
ICancellationSignal mKillCallback;
|
||||
|
||||
final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
|
||||
@@ -1105,6 +1109,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
} catch (RemoteException e) {
|
||||
/* ignore */
|
||||
}
|
||||
mKillCallback = null;
|
||||
}
|
||||
if (mInitialized) {
|
||||
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
|
||||
@@ -1314,8 +1319,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Ask that a new assistant activity be started. This will create a new task in the
|
||||
* in activity manager: this means that
|
||||
@@ -1349,19 +1352,57 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
*
|
||||
* @param activityId Ths activity id of the app to get the actions from.
|
||||
* @param resultExecutor The handler to receive the callback
|
||||
* @param cancellationSignal A signal to cancel the operation in progress,
|
||||
* or {@code null} if none.
|
||||
* @param callback The callback to receive the response
|
||||
*/
|
||||
public final void requestDirectActions(@NonNull ActivityId activityId,
|
||||
@Nullable CancellationSignal cancellationSignal,
|
||||
@NonNull @CallbackExecutor Executor resultExecutor,
|
||||
@NonNull Consumer<List<DirectAction>> callback) {
|
||||
Preconditions.checkNotNull(activityId);
|
||||
Preconditions.checkNotNull(resultExecutor);
|
||||
Preconditions.checkNotNull(callback);
|
||||
if (mToken == null) {
|
||||
throw new IllegalStateException("Can't call before onCreate()");
|
||||
}
|
||||
|
||||
if (cancellationSignal != null) {
|
||||
cancellationSignal.throwIfCanceled();
|
||||
}
|
||||
|
||||
final RemoteCallback cancellationCallback = (cancellationSignal != null)
|
||||
? new RemoteCallback(b -> {
|
||||
if (b != null) {
|
||||
final IBinder cancellation = b.getBinder(
|
||||
VoiceInteractor.KEY_CANCELLATION_SIGNAL);
|
||||
if (cancellation != null) {
|
||||
cancellationSignal.setRemote(ICancellationSignal.Stub.asInterface(
|
||||
cancellation));
|
||||
}
|
||||
}
|
||||
})
|
||||
: null;
|
||||
|
||||
try {
|
||||
mSystemService.requestDirectActions(mToken, activityId.getTaskId(),
|
||||
activityId.getAssistToken(), new RemoteCallback(new DirectActionsReceiver(
|
||||
Preconditions.checkNotNull(resultExecutor),
|
||||
Preconditions.checkNotNull(callback))));
|
||||
activityId.getAssistToken(), cancellationCallback,
|
||||
new RemoteCallback(createSafeResultListener((result) -> {
|
||||
List<DirectAction> list;
|
||||
if (result == null) {
|
||||
list = Collections.emptyList();
|
||||
} else {
|
||||
final ParceledListSlice<DirectAction> pls = result.getParcelable(
|
||||
DirectAction.KEY_ACTIONS_LIST);
|
||||
if (pls != null) {
|
||||
final List<DirectAction> receivedList = pls.getList();
|
||||
list = (receivedList != null) ? receivedList : Collections.emptyList();
|
||||
} else {
|
||||
list = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
resultExecutor.execute(() -> callback.accept(list));
|
||||
})));
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -1390,8 +1431,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
* @param resultExecutor The handler to receive the callback.
|
||||
* @param resultListener The callback to receive the response.
|
||||
*
|
||||
* @see #requestDirectActions(ActivityId, Executor, Consumer)
|
||||
* @see Activity#onGetDirectActions()
|
||||
* @see #requestDirectActions(ActivityId, CancellationSignal, Executor, Consumer)
|
||||
* @see Activity#onGetDirectActions(CancellationSignal, Consumer)
|
||||
*/
|
||||
public final void performDirectAction(@NonNull DirectAction action, @Nullable Bundle extras,
|
||||
@Nullable CancellationSignal cancellationSignal,
|
||||
@@ -1407,26 +1448,31 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
cancellationSignal.throwIfCanceled();
|
||||
}
|
||||
|
||||
final RemoteCallback remoteCallback = new RemoteCallback(b -> {
|
||||
if (b != null) {
|
||||
final IBinder cancellation = b.getBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL);
|
||||
if (cancellation != null) {
|
||||
if (cancellationSignal != null) {
|
||||
cancellationSignal.setRemote(ICancellationSignal.Stub.asInterface(
|
||||
cancellation));
|
||||
final RemoteCallback cancellationCallback = (cancellationSignal != null)
|
||||
? new RemoteCallback(createSafeResultListener(b -> {
|
||||
if (b != null) {
|
||||
final IBinder cancellation = b.getBinder(
|
||||
VoiceInteractor.KEY_CANCELLATION_SIGNAL);
|
||||
if (cancellation != null) {
|
||||
cancellationSignal.setRemote(ICancellationSignal.Stub.asInterface(
|
||||
cancellation));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resultExecutor.execute(() -> resultListener.accept(b));
|
||||
}
|
||||
}))
|
||||
: null;
|
||||
|
||||
final RemoteCallback resultCallback = new RemoteCallback(createSafeResultListener(b -> {
|
||||
if (b != null) {
|
||||
resultExecutor.execute(() -> resultListener.accept(b));
|
||||
} else {
|
||||
resultExecutor.execute(() -> resultListener.accept(Bundle.EMPTY));
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
try {
|
||||
mSystemService.performDirectAction(mToken, action.getId(), extras,
|
||||
action.getTaskId(), action.getActivityId(), remoteCallback,
|
||||
remoteCallback);
|
||||
action.getTaskId(), action.getActivityId(), cancellationCallback,
|
||||
resultCallback);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -1901,33 +1947,18 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
}
|
||||
}
|
||||
|
||||
private static class DirectActionsReceiver implements RemoteCallback.OnResultListener {
|
||||
|
||||
@NonNull
|
||||
private final Executor mResultExecutor;
|
||||
private final Consumer<List<DirectAction>> mCallback;
|
||||
|
||||
DirectActionsReceiver(Executor resultExecutor, Consumer<List<DirectAction>> callback) {
|
||||
mResultExecutor = resultExecutor;
|
||||
mCallback = callback;
|
||||
private SafeResultListener createSafeResultListener(
|
||||
@NonNull Consumer<Bundle> consumer) {
|
||||
synchronized (this) {
|
||||
final SafeResultListener listener = new SafeResultListener(consumer, this);
|
||||
mRemoteCallbacks.put(listener, consumer);
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Bundle result) {
|
||||
final List<DirectAction> list;
|
||||
if (result == null) {
|
||||
list = Collections.emptyList();
|
||||
} else {
|
||||
final ParceledListSlice<DirectAction> pls = result.getParcelable(
|
||||
DirectAction.KEY_ACTIONS_LIST);
|
||||
if (pls != null) {
|
||||
final List<DirectAction> receivedList = pls.getList();
|
||||
list = (receivedList != null) ? receivedList : Collections.emptyList();
|
||||
} else {
|
||||
list = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
mResultExecutor.execute(() -> mCallback.accept(list));
|
||||
private Consumer<Bundle> removeSafeResultListener(@NonNull SafeResultListener listener) {
|
||||
synchronized (this) {
|
||||
return mRemoteCallbacks.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2062,4 +2093,24 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SafeResultListener implements RemoteCallback.OnResultListener {
|
||||
private final @NonNull WeakReference<VoiceInteractionSession> mWeakSession;
|
||||
|
||||
SafeResultListener(@NonNull Consumer<Bundle> action,
|
||||
@NonNull VoiceInteractionSession session) {
|
||||
mWeakSession = new WeakReference<>(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Bundle result) {
|
||||
final VoiceInteractionSession session = mWeakSession.get();
|
||||
if (session != null) {
|
||||
final Consumer<Bundle> consumer = session.removeSafeResultListener(this);
|
||||
if (consumer != null) {
|
||||
consumer.accept(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ interface IVoiceInteractionManagerService {
|
||||
* Requests a list of supported actions from a specific activity.
|
||||
*/
|
||||
void requestDirectActions(in IBinder token, int taskId, IBinder assistToken,
|
||||
in RemoteCallback callback);
|
||||
in RemoteCallback cancellationCallback, in RemoteCallback callback);
|
||||
|
||||
/**
|
||||
* Requests performing an action from a specific activity.
|
||||
|
||||
@@ -628,8 +628,8 @@ public class TransactionParcelTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDirectActions(IBinder activityToken, IVoiceInteractor intractor,
|
||||
RemoteCallback callback) {
|
||||
public void requestDirectActions(IBinder activityToken, IVoiceInteractor interactor,
|
||||
RemoteCallback cancellationCallback, RemoteCallback resultCallback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -714,17 +714,19 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDirectActions(@NonNull IBinder token, int taskId, IBinder assistToken,
|
||||
@NonNull RemoteCallback callback) {
|
||||
public void requestDirectActions(@NonNull IBinder token, int taskId,
|
||||
@NonNull IBinder assistToken, @Nullable RemoteCallback cancellationCallback,
|
||||
@NonNull RemoteCallback resultCallback) {
|
||||
synchronized (this) {
|
||||
if (mImpl == null) {
|
||||
Slog.w(TAG, "requestDirectActions without running voice interaction service");
|
||||
callback.sendResult(null);
|
||||
resultCallback.sendResult(null);
|
||||
return;
|
||||
}
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mImpl.requestDirectActionsLocked(token, taskId, assistToken, callback);
|
||||
mImpl.requestDirectActionsLocked(token, taskId, assistToken,
|
||||
cancellationCallback, resultCallback);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
|
||||
@@ -263,7 +263,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
|
||||
}
|
||||
|
||||
public void requestDirectActionsLocked(@NonNull IBinder token, int taskId,
|
||||
IBinder assistToken, @NonNull RemoteCallback callback) {
|
||||
@NonNull IBinder assistToken, @Nullable RemoteCallback cancellationCallback,
|
||||
@NonNull RemoteCallback callback) {
|
||||
if (mActiveSession == null || token != mActiveSession.mToken) {
|
||||
Slog.w(TAG, "requestDirectActionsLocked does not match active session");
|
||||
callback.sendResult(null);
|
||||
@@ -277,7 +278,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
|
||||
} else {
|
||||
try {
|
||||
tokens.getApplicationThread().requestDirectActions(tokens.getActivityToken(),
|
||||
mActiveSession.mInteractor, callback);
|
||||
mActiveSession.mInteractor, cancellationCallback, callback);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w("Unexpected remote error", e);
|
||||
callback.sendResult(null);
|
||||
|
||||
Reference in New Issue
Block a user