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