Loading core/api/system-current.txt +8 −1 Original line number Diff line number Diff line Loading @@ -2178,8 +2178,15 @@ package android.app.contentsuggestions { package android.app.contextualsearch { @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable { ctor public CallbackToken(); method public int describeContents(); method public void getContextualSearchState(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.contextualsearch.CallbackToken> CREATOR; } @FlaggedApi("android.app.contextualsearch.flags.enable_service") public class ContextualSearchManager { method public void getContextualSearchState(@NonNull android.os.IBinder, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>); method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH) public void startContextualSearch(int); field public static final String ACTION_LAUNCH_CONTEXTUAL_SEARCH = "android.app.contextualsearch.action.LAUNCH_CONTEXTUAL_SEARCH"; field public static final int ENTRYPOINT_LONG_PRESS_HOME = 2; // 0x2 core/api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -803,6 +803,14 @@ package android.app.contentsuggestions { } package android.app.contextualsearch { @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable { method @NonNull public android.os.IBinder getToken(); } } package android.app.job { public class JobParameters implements android.os.Parcelable { Loading core/java/android/app/contextualsearch/CallbackToken.java 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.app.contextualsearch; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.contextualsearch.flags.Flags; import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.OutcomeReceiver; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelableException; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import androidx.annotation.NonNull; import java.util.concurrent.Executor; /** * Used to share a single use token with the contextual search handling activity via the launch * extras bundle. * The caller can then use this token to get {@link ContextualSearchState} by calling * {@link #getContextualSearchState}. * * @hide */ @FlaggedApi(Flags.FLAG_ENABLE_SERVICE) @SystemApi public final class CallbackToken implements Parcelable { private static final boolean DEBUG = true; private static final String TAG = CallbackToken.class.getSimpleName(); private final IBinder mToken; private boolean mTokenUsed = false; public CallbackToken() { mToken = new Binder(); } private CallbackToken(Parcel in) { mToken = in.readStrongBinder(); } /** * Returns the {@link ContextualSearchState} to the handler via the provided callback. The * method can only be invoked to provide the {@link OutcomeReceiver} once and all subsequent * invocations of this method will result in {@link OutcomeReceiver#onError} being called with * an {@link IllegalAccessException}. * * @param executor The executor which will be used to invoke the callback. * @param callback The callback which will be used to return {@link ContextualSearchState} * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be * used to return errors via {@link OutcomeReceiver#onError}. */ public void getContextualSearchState(@NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + mToken); if (mTokenUsed) { callback.onError(new IllegalAccessException("Token already used.")); } mTokenUsed = true; try { // Get the service from the system server. IBinder b = ServiceManager.getService(Context.CONTEXTUAL_SEARCH_SERVICE); IContextualSearchManager service = IContextualSearchManager.Stub.asInterface(b); final CallbackWrapper wrapper = new CallbackWrapper(executor, callback); // If the service is not null, hand over the call to the service. if (service != null) { service.getContextualSearchState(mToken, wrapper); } else { Log.w(TAG, "Failed to getContextualSearchState. Service null."); } } catch (RemoteException e) { if (DEBUG) Log.d(TAG, "Failed to call getContextualSearchState", e); e.rethrowFromSystemServer(); } } /** * Return the token necessary for validating the caller of {@link #getContextualSearchState}. * * @hide */ @TestApi @NonNull public IBinder getToken() { return mToken; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeStrongBinder(mToken); } @NonNull public static final Creator<CallbackToken> CREATOR = new Creator<>() { @Override public CallbackToken createFromParcel(Parcel in) { return new CallbackToken(in); } @Override public CallbackToken[] newArray(int size) { return new CallbackToken[size]; } }; private static class CallbackWrapper extends IContextualSearchCallback.Stub { private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback; private final Executor mExecutor; CallbackWrapper(@NonNull Executor callbackExecutor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { mCallback = callback; mExecutor = callbackExecutor; } @Override public void onResult(ContextualSearchState state) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.d(TAG, "onResult state:" + state); mExecutor.execute(() -> mCallback.onResult(state)); }); } @Override public void onError(ParcelableException error) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.w(TAG, "onError", error); mExecutor.execute(() -> mCallback.onError(error)); }); } } } core/java/android/app/contextualsearch/ContextualSearchManager.java +3 −67 Original line number Diff line number Diff line Loading @@ -18,37 +18,26 @@ package android.app.contextualsearch; import static android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.contextualsearch.flags.Flags; import android.content.Context; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.OutcomeReceiver; import android.os.ParcelableException; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; /** * {@link ContextualSearchManager} is a system service to facilitate contextual search experience on * configured Android devices. * <p> * This class lets * <ul> * <li> a caller start contextual search by calling {@link #startContextualSearch} method. * <li> a handler request {@link ContextualSearchState} by calling the * {@link #getContextualSearchState} method. * </ul> * This class lets a caller start contextual search by calling {@link #startContextualSearch} * method. * * @hide */ Loading Loading @@ -92,7 +81,7 @@ public class ContextualSearchManager { /** * Key to get the binder token from the extras of the activity launched by contextual search. * This token is needed to invoke {@link #getContextualSearchState} method. * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method. * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH. */ public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN"; Loading Loading @@ -174,57 +163,4 @@ public class ContextualSearchManager { e.rethrowFromSystemServer(); } } /** * Returns the {@link ContextualSearchState} to the handler via the provided callback. * * @param token The caller is expected to get the token from the launch extras of the handling * activity using {@link Bundle#getIBinder} with {@link #EXTRA_TOKEN} key. * <br> * <b>Note</b> This token is for one time use only. Subsequent uses will invoke * callback's {@link OutcomeReceiver#onError}. * @param executor The executor which will be used to invoke the callback. * @param callback The callback which will be used to return {@link ContextualSearchState} * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be * used to return errors via {@link OutcomeReceiver#onError}. */ public void getContextualSearchState(@NonNull IBinder token, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + token); try { final CallbackWrapper wrapper = new CallbackWrapper(executor, callback); mService.getContextualSearchState(token, wrapper); } catch (RemoteException e) { if (DEBUG) Log.d(TAG, "Failed to getContextualSearchState", e); e.rethrowFromSystemServer(); } } private static class CallbackWrapper extends IContextualSearchCallback.Stub { private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback; private final Executor mExecutor; CallbackWrapper(@NonNull Executor callbackExecutor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { mCallback = callback; mExecutor = callbackExecutor; } @Override public void onResult(ContextualSearchState state) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.d(TAG, "onResult state:" + state); mExecutor.execute(() -> mCallback.onResult(state)); }); } @Override public void onError(ParcelableException error) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.w(TAG, "onError", error); mExecutor.execute(() -> mCallback.onError(error)); }); } } } core/java/android/app/contextualsearch/ContextualSearchState.java +10 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ import androidx.annotation.NonNull; * {@link ContextualSearchState} contains additional data a contextual search handler can request * via {@link ContextualSearchManager#getContextualSearchState} method. * * It provides the caller of {@link ContextualSearchManager#getContextualSearchState} with an * {@link AssistStructure}, {@link AssistContent} and a {@link Bundle} extras containing any * relevant data added by th system server. When invoked via the Launcher, this bundle is empty. * * @hide */ @FlaggedApi(Flags.FLAG_ENABLE_SERVICE) Loading @@ -41,6 +45,12 @@ public final class ContextualSearchState implements Parcelable { private final @Nullable AssistStructure mStructure; private final @Nullable AssistContent mContent; /** * {@link ContextualSearchState} contains non-essential data which can be requested by the * Contextual Search activity. * The activity can request an instance of {@link ContextualSearchState} by calling * {@link CallbackToken#getContextualSearchState} and passing a valid token as an argument. */ public ContextualSearchState(@Nullable AssistStructure structure, @Nullable AssistContent content, @NonNull Bundle extras) { mStructure = structure; Loading Loading
core/api/system-current.txt +8 −1 Original line number Diff line number Diff line Loading @@ -2178,8 +2178,15 @@ package android.app.contentsuggestions { package android.app.contextualsearch { @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable { ctor public CallbackToken(); method public int describeContents(); method public void getContextualSearchState(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.contextualsearch.CallbackToken> CREATOR; } @FlaggedApi("android.app.contextualsearch.flags.enable_service") public class ContextualSearchManager { method public void getContextualSearchState(@NonNull android.os.IBinder, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>); method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH) public void startContextualSearch(int); field public static final String ACTION_LAUNCH_CONTEXTUAL_SEARCH = "android.app.contextualsearch.action.LAUNCH_CONTEXTUAL_SEARCH"; field public static final int ENTRYPOINT_LONG_PRESS_HOME = 2; // 0x2
core/api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -803,6 +803,14 @@ package android.app.contentsuggestions { } package android.app.contextualsearch { @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable { method @NonNull public android.os.IBinder getToken(); } } package android.app.job { public class JobParameters implements android.os.Parcelable { Loading
core/java/android/app/contextualsearch/CallbackToken.java 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.app.contextualsearch; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.contextualsearch.flags.Flags; import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.OutcomeReceiver; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelableException; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import androidx.annotation.NonNull; import java.util.concurrent.Executor; /** * Used to share a single use token with the contextual search handling activity via the launch * extras bundle. * The caller can then use this token to get {@link ContextualSearchState} by calling * {@link #getContextualSearchState}. * * @hide */ @FlaggedApi(Flags.FLAG_ENABLE_SERVICE) @SystemApi public final class CallbackToken implements Parcelable { private static final boolean DEBUG = true; private static final String TAG = CallbackToken.class.getSimpleName(); private final IBinder mToken; private boolean mTokenUsed = false; public CallbackToken() { mToken = new Binder(); } private CallbackToken(Parcel in) { mToken = in.readStrongBinder(); } /** * Returns the {@link ContextualSearchState} to the handler via the provided callback. The * method can only be invoked to provide the {@link OutcomeReceiver} once and all subsequent * invocations of this method will result in {@link OutcomeReceiver#onError} being called with * an {@link IllegalAccessException}. * * @param executor The executor which will be used to invoke the callback. * @param callback The callback which will be used to return {@link ContextualSearchState} * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be * used to return errors via {@link OutcomeReceiver#onError}. */ public void getContextualSearchState(@NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + mToken); if (mTokenUsed) { callback.onError(new IllegalAccessException("Token already used.")); } mTokenUsed = true; try { // Get the service from the system server. IBinder b = ServiceManager.getService(Context.CONTEXTUAL_SEARCH_SERVICE); IContextualSearchManager service = IContextualSearchManager.Stub.asInterface(b); final CallbackWrapper wrapper = new CallbackWrapper(executor, callback); // If the service is not null, hand over the call to the service. if (service != null) { service.getContextualSearchState(mToken, wrapper); } else { Log.w(TAG, "Failed to getContextualSearchState. Service null."); } } catch (RemoteException e) { if (DEBUG) Log.d(TAG, "Failed to call getContextualSearchState", e); e.rethrowFromSystemServer(); } } /** * Return the token necessary for validating the caller of {@link #getContextualSearchState}. * * @hide */ @TestApi @NonNull public IBinder getToken() { return mToken; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeStrongBinder(mToken); } @NonNull public static final Creator<CallbackToken> CREATOR = new Creator<>() { @Override public CallbackToken createFromParcel(Parcel in) { return new CallbackToken(in); } @Override public CallbackToken[] newArray(int size) { return new CallbackToken[size]; } }; private static class CallbackWrapper extends IContextualSearchCallback.Stub { private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback; private final Executor mExecutor; CallbackWrapper(@NonNull Executor callbackExecutor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { mCallback = callback; mExecutor = callbackExecutor; } @Override public void onResult(ContextualSearchState state) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.d(TAG, "onResult state:" + state); mExecutor.execute(() -> mCallback.onResult(state)); }); } @Override public void onError(ParcelableException error) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.w(TAG, "onError", error); mExecutor.execute(() -> mCallback.onError(error)); }); } } }
core/java/android/app/contextualsearch/ContextualSearchManager.java +3 −67 Original line number Diff line number Diff line Loading @@ -18,37 +18,26 @@ package android.app.contextualsearch; import static android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.contextualsearch.flags.Flags; import android.content.Context; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.OutcomeReceiver; import android.os.ParcelableException; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.Executor; /** * {@link ContextualSearchManager} is a system service to facilitate contextual search experience on * configured Android devices. * <p> * This class lets * <ul> * <li> a caller start contextual search by calling {@link #startContextualSearch} method. * <li> a handler request {@link ContextualSearchState} by calling the * {@link #getContextualSearchState} method. * </ul> * This class lets a caller start contextual search by calling {@link #startContextualSearch} * method. * * @hide */ Loading Loading @@ -92,7 +81,7 @@ public class ContextualSearchManager { /** * Key to get the binder token from the extras of the activity launched by contextual search. * This token is needed to invoke {@link #getContextualSearchState} method. * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method. * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH. */ public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN"; Loading Loading @@ -174,57 +163,4 @@ public class ContextualSearchManager { e.rethrowFromSystemServer(); } } /** * Returns the {@link ContextualSearchState} to the handler via the provided callback. * * @param token The caller is expected to get the token from the launch extras of the handling * activity using {@link Bundle#getIBinder} with {@link #EXTRA_TOKEN} key. * <br> * <b>Note</b> This token is for one time use only. Subsequent uses will invoke * callback's {@link OutcomeReceiver#onError}. * @param executor The executor which will be used to invoke the callback. * @param callback The callback which will be used to return {@link ContextualSearchState} * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be * used to return errors via {@link OutcomeReceiver#onError}. */ public void getContextualSearchState(@NonNull IBinder token, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + token); try { final CallbackWrapper wrapper = new CallbackWrapper(executor, callback); mService.getContextualSearchState(token, wrapper); } catch (RemoteException e) { if (DEBUG) Log.d(TAG, "Failed to getContextualSearchState", e); e.rethrowFromSystemServer(); } } private static class CallbackWrapper extends IContextualSearchCallback.Stub { private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback; private final Executor mExecutor; CallbackWrapper(@NonNull Executor callbackExecutor, @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) { mCallback = callback; mExecutor = callbackExecutor; } @Override public void onResult(ContextualSearchState state) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.d(TAG, "onResult state:" + state); mExecutor.execute(() -> mCallback.onResult(state)); }); } @Override public void onError(ParcelableException error) { Binder.withCleanCallingIdentity(() -> { if (DEBUG) Log.w(TAG, "onError", error); mExecutor.execute(() -> mCallback.onError(error)); }); } } }
core/java/android/app/contextualsearch/ContextualSearchState.java +10 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ import androidx.annotation.NonNull; * {@link ContextualSearchState} contains additional data a contextual search handler can request * via {@link ContextualSearchManager#getContextualSearchState} method. * * It provides the caller of {@link ContextualSearchManager#getContextualSearchState} with an * {@link AssistStructure}, {@link AssistContent} and a {@link Bundle} extras containing any * relevant data added by th system server. When invoked via the Launcher, this bundle is empty. * * @hide */ @FlaggedApi(Flags.FLAG_ENABLE_SERVICE) Loading @@ -41,6 +45,12 @@ public final class ContextualSearchState implements Parcelable { private final @Nullable AssistStructure mStructure; private final @Nullable AssistContent mContent; /** * {@link ContextualSearchState} contains non-essential data which can be requested by the * Contextual Search activity. * The activity can request an instance of {@link ContextualSearchState} by calling * {@link CallbackToken#getContextualSearchState} and passing a valid token as an argument. */ public ContextualSearchState(@Nullable AssistStructure structure, @Nullable AssistContent content, @NonNull Bundle extras) { mStructure = structure; Loading