• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.contextualsearch;
18 
19 import static android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.IntDef;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.app.contextualsearch.flags.Flags;
26 import android.content.Context;
27 import android.os.IBinder;
28 import android.os.RemoteException;
29 import android.os.ServiceManager;
30 import android.os.SystemClock;
31 import android.util.Log;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.util.Arrays;
36 import java.util.HashSet;
37 import java.util.Set;
38 
39 /**
40  * {@link ContextualSearchManager} is a system service to facilitate contextual search experience on
41  * configured Android devices.
42  * <p>
43  * This class lets a caller start contextual search by calling {@link #startContextualSearch}
44  * method.
45  */
46 @FlaggedApi(Flags.FLAG_SELF_INVOCATION)
47 public final class ContextualSearchManager {
48 
49     /**
50      * Key to get the entrypoint from the extras of the activity launched by contextual search.
51      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
52      *
53      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
54      * @hide
55      */
56     @SystemApi
57     public static final String EXTRA_ENTRYPOINT =
58             "android.app.contextualsearch.extra.ENTRYPOINT";
59 
60     /**
61      * Key to get the flag_secure value from the extras of the activity launched by contextual
62      * search. The value will be true if flag_secure is found in any of the visible activities.
63      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
64      *
65      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
66      * @hide
67      */
68     @SystemApi
69     public static final String EXTRA_FLAG_SECURE_FOUND =
70             "android.app.contextualsearch.extra.FLAG_SECURE_FOUND";
71 
72     /**
73      * Key to get the screenshot from the extras of the activity launched by contextual search.
74      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
75      *
76      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
77      * @hide
78      */
79     @SystemApi
80     public static final String EXTRA_SCREENSHOT =
81             "android.app.contextualsearch.extra.SCREENSHOT";
82 
83     /**
84      * Key to check whether managed profile is visible from the extras of the activity launched by
85      * contextual search. The value will be true if any one of the visible apps is managed.
86      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
87      *
88      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
89      * @hide
90      */
91     @SystemApi
92     public static final String EXTRA_IS_MANAGED_PROFILE_VISIBLE =
93             "android.app.contextualsearch.extra.IS_MANAGED_PROFILE_VISIBLE";
94 
95     /**
96      * Key to get the list of visible packages from the extras of the activity launched by
97      * contextual search.
98      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
99      *
100      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
101      * @hide
102      */
103     @SystemApi
104     public static final String EXTRA_VISIBLE_PACKAGE_NAMES =
105             "android.app.contextualsearch.extra.VISIBLE_PACKAGE_NAMES";
106 
107     /**
108      * Key to get the time the user made the invocation request, based on
109      * {@link SystemClock#uptimeMillis()}.
110      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
111      *
112      * TODO: un-hide in W
113      *
114      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
115      * @hide
116      */
117     public static final String EXTRA_INVOCATION_TIME_MS =
118             "android.app.contextualsearch.extra.INVOCATION_TIME_MS";
119 
120     /**
121      * Key to get the binder token from the extras of the activity launched by contextual search.
122      * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method.
123      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
124      *
125      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
126      * @hide
127      */
128     @SystemApi
129     public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN";
130 
131     /**
132      * Key to check whether audio is playing when contextual search is invoked.
133      * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
134      *
135      * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
136      *
137      * @hide
138      */
139     public static final String EXTRA_IS_AUDIO_PLAYING =
140             "android.app.contextualsearch.extra.IS_AUDIO_PLAYING";
141 
142     /**
143      * Intent action for contextual search invocation. The app providing the contextual search
144      * experience must add this intent filter action to the activity it wants to be launched.
145      * <br>
146      * <b>Note</b> This activity must not be exported.
147      *
148      * @hide
149      */
150     @SystemApi
151     public static final String ACTION_LAUNCH_CONTEXTUAL_SEARCH =
152             "android.app.contextualsearch.action.LAUNCH_CONTEXTUAL_SEARCH";
153 
154     /**
155      * System feature declaring that the device supports Contextual Search.
156      *
157      * @hide
158      */
159     public static final String FEATURE_CONTEXTUAL_SEARCH =
160             "com.google.android.feature.CONTEXTUAL_SEARCH";
161 
162     /**
163      * Entrypoint to be used when a user long presses on the nav handle.
164      *
165      * @hide
166      */
167     @SystemApi
168     public static final int ENTRYPOINT_LONG_PRESS_NAV_HANDLE = 1;
169 
170     /** Entrypoint to be used when a user long presses on the home button.
171      *
172      * @hide
173      */
174     @SystemApi
175     public static final int ENTRYPOINT_LONG_PRESS_HOME = 2;
176 
177     /** Entrypoint to be used when a user long presses on the overview button.
178      *
179      * @hide
180      */
181     @SystemApi
182     public static final int ENTRYPOINT_LONG_PRESS_OVERVIEW = 3;
183 
184     /**
185      * Entrypoint to be used when a user presses the action button in overview.
186      *
187      * @hide
188      */
189     @SystemApi
190     public static final int ENTRYPOINT_OVERVIEW_ACTION = 4;
191 
192     /**
193      * Entrypoint to be used when a user presses the context menu button in overview.
194      *
195      * @hide
196      */
197     @SystemApi
198     public static final int ENTRYPOINT_OVERVIEW_MENU = 5;
199 
200     /**
201      * Entrypoint to be used by system actions like TalkBack, Accessibility etc.
202      *
203      * @hide
204      */
205     @SystemApi
206     public static final int ENTRYPOINT_SYSTEM_ACTION = 9;
207 
208     /**
209      * Entrypoint to be used when a user long presses on the meta key.
210      *
211      * @hide
212      */
213     @SystemApi
214     public static final int ENTRYPOINT_LONG_PRESS_META = 10;
215 
216     /**
217      * The {@link Entrypoint} annotation is used to standardize the entrypoints supported by
218      * {@link #startContextualSearch(int entrypoint)} method.
219      *
220      * @hide
221      */
222     @IntDef(prefix = {"ENTRYPOINT_"}, value = {
223             ENTRYPOINT_LONG_PRESS_NAV_HANDLE,
224             ENTRYPOINT_LONG_PRESS_HOME,
225             ENTRYPOINT_LONG_PRESS_OVERVIEW,
226             ENTRYPOINT_OVERVIEW_ACTION,
227             ENTRYPOINT_OVERVIEW_MENU,
228             ENTRYPOINT_SYSTEM_ACTION,
229             ENTRYPOINT_LONG_PRESS_META
230     })
231     @Retention(RetentionPolicy.SOURCE)
232     public @interface Entrypoint {}
233 
234     private static final Set<Integer> VALID_ENTRYPOINT_VALUES = new HashSet<>(Arrays.asList(
235             ENTRYPOINT_LONG_PRESS_NAV_HANDLE,
236             ENTRYPOINT_LONG_PRESS_HOME,
237             ENTRYPOINT_LONG_PRESS_OVERVIEW,
238             ENTRYPOINT_OVERVIEW_ACTION,
239             ENTRYPOINT_OVERVIEW_MENU,
240             ENTRYPOINT_SYSTEM_ACTION,
241             ENTRYPOINT_LONG_PRESS_META
242     ));
243 
244     private static final String TAG = ContextualSearchManager.class.getSimpleName();
245     private static final boolean DEBUG = false;
246 
247     private final IContextualSearchManager mService;
248 
249     /** @hide */
ContextualSearchManager()250     public ContextualSearchManager() {
251         if (DEBUG) Log.d(TAG, "ContextualSearchManager created");
252         IBinder b = ServiceManager.getService(Context.CONTEXTUAL_SEARCH_SERVICE);
253         mService = IContextualSearchManager.Stub.asInterface(b);
254     }
255 
256     /**
257      * Used to start contextual search for a given system entrypoint.
258      * <p>
259      *     When {@link #startContextualSearch} is called, the system server does the following:
260      *     <ul>
261      *         <li>Resolves the activity using the package name and intent filter. The package name
262      *             is fetched from the config specified in ContextualSearchManagerService.
263      *             The activity must have ACTION_LAUNCH_CONTEXTUAL_SEARCH specified in its manifest.
264      *         <li>Puts the required extras in the launch intent.
265      *         <li>Launches the activity.
266      *     </ul>
267      * </p>
268      *
269      * @param entrypoint the invocation entrypoint
270      *
271      * @hide
272      */
273     @RequiresPermission(ACCESS_CONTEXTUAL_SEARCH)
274     @SystemApi
startContextualSearch(@ntrypoint int entrypoint)275     public void startContextualSearch(@Entrypoint int entrypoint) {
276         if (!VALID_ENTRYPOINT_VALUES.contains(entrypoint)) {
277             throw new IllegalArgumentException("Invalid entrypoint: " + entrypoint);
278         }
279         if (DEBUG) Log.d(TAG, "startContextualSearch for entrypoint: " + entrypoint);
280         try {
281             mService.startContextualSearch(entrypoint);
282         } catch (RemoteException e) {
283             if (DEBUG) Log.d(TAG, "Failed to startContextualSearch", e);
284             e.rethrowFromSystemServer();
285         }
286     }
287 
288     /**
289      * Used to start contextual search from within an app.
290      *
291      * <p>System apps should use the available System APIs rather than this method.
292      *
293      * @throws SecurityException if the caller does not have a foreground Activity.
294      */
295     @FlaggedApi(Flags.FLAG_SELF_INVOCATION)
startContextualSearch()296     public void startContextualSearch() {
297         if (DEBUG) Log.d(TAG, "startContextualSearch from app");
298         try {
299             mService.startContextualSearchForForegroundApp();
300         } catch (RemoteException e) {
301             if (DEBUG) Log.d(TAG, "Failed to startContextualSearch", e);
302             e.rethrowFromSystemServer();
303         }
304     }
305 }
306