1 /*
2  * Copyright (C) 2012 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 androidx.core.content;
18 
19 import static android.content.Context.ACCESSIBILITY_SERVICE;
20 import static android.content.Context.ACCOUNT_SERVICE;
21 import static android.content.Context.ACTIVITY_SERVICE;
22 import static android.content.Context.ALARM_SERVICE;
23 import static android.content.Context.APPWIDGET_SERVICE;
24 import static android.content.Context.APP_OPS_SERVICE;
25 import static android.content.Context.AUDIO_SERVICE;
26 import static android.content.Context.BATTERY_SERVICE;
27 import static android.content.Context.BLUETOOTH_SERVICE;
28 import static android.content.Context.CAMERA_SERVICE;
29 import static android.content.Context.CAPTIONING_SERVICE;
30 import static android.content.Context.CLIPBOARD_SERVICE;
31 import static android.content.Context.CONNECTIVITY_SERVICE;
32 import static android.content.Context.CONSUMER_IR_SERVICE;
33 import static android.content.Context.DEVICE_POLICY_SERVICE;
34 import static android.content.Context.DISPLAY_SERVICE;
35 import static android.content.Context.DOWNLOAD_SERVICE;
36 import static android.content.Context.DROPBOX_SERVICE;
37 import static android.content.Context.INPUT_METHOD_SERVICE;
38 import static android.content.Context.INPUT_SERVICE;
39 import static android.content.Context.JOB_SCHEDULER_SERVICE;
40 import static android.content.Context.KEYGUARD_SERVICE;
41 import static android.content.Context.LAUNCHER_APPS_SERVICE;
42 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
43 import static android.content.Context.LOCATION_SERVICE;
44 import static android.content.Context.MEDIA_PROJECTION_SERVICE;
45 import static android.content.Context.MEDIA_ROUTER_SERVICE;
46 import static android.content.Context.MEDIA_SESSION_SERVICE;
47 import static android.content.Context.NFC_SERVICE;
48 import static android.content.Context.NOTIFICATION_SERVICE;
49 import static android.content.Context.NSD_SERVICE;
50 import static android.content.Context.POWER_SERVICE;
51 import static android.content.Context.PRINT_SERVICE;
52 import static android.content.Context.RESTRICTIONS_SERVICE;
53 import static android.content.Context.SEARCH_SERVICE;
54 import static android.content.Context.SENSOR_SERVICE;
55 import static android.content.Context.STORAGE_SERVICE;
56 import static android.content.Context.TELECOM_SERVICE;
57 import static android.content.Context.TELEPHONY_SERVICE;
58 import static android.content.Context.TELEPHONY_SUBSCRIPTION_SERVICE;
59 import static android.content.Context.TEXT_SERVICES_MANAGER_SERVICE;
60 import static android.content.Context.TV_INPUT_SERVICE;
61 import static android.content.Context.UI_MODE_SERVICE;
62 import static android.content.Context.USAGE_STATS_SERVICE;
63 import static android.content.Context.USB_SERVICE;
64 import static android.content.Context.USER_SERVICE;
65 import static android.content.Context.VIBRATOR_SERVICE;
66 import static android.content.Context.WALLPAPER_SERVICE;
67 import static android.content.Context.WIFI_P2P_SERVICE;
68 import static android.content.Context.WIFI_SERVICE;
69 import static android.content.Context.WINDOW_SERVICE;
70 
71 import android.accounts.AccountManager;
72 import android.annotation.SuppressLint;
73 import android.app.Activity;
74 import android.app.ActivityManager;
75 import android.app.AlarmManager;
76 import android.app.AppOpsManager;
77 import android.app.DownloadManager;
78 import android.app.KeyguardManager;
79 import android.app.NotificationManager;
80 import android.app.SearchManager;
81 import android.app.UiModeManager;
82 import android.app.WallpaperManager;
83 import android.app.admin.DevicePolicyManager;
84 import android.app.job.JobScheduler;
85 import android.app.usage.UsageStatsManager;
86 import android.appwidget.AppWidgetManager;
87 import android.bluetooth.BluetoothManager;
88 import android.content.BroadcastReceiver;
89 import android.content.ClipboardManager;
90 import android.content.ComponentName;
91 import android.content.Context;
92 import android.content.Intent;
93 import android.content.IntentFilter;
94 import android.content.RestrictionsManager;
95 import android.content.pm.ApplicationInfo;
96 import android.content.pm.LauncherApps;
97 import android.content.pm.PackageManager;
98 import android.content.res.ColorStateList;
99 import android.content.res.Configuration;
100 import android.graphics.drawable.Drawable;
101 import android.hardware.ConsumerIrManager;
102 import android.hardware.SensorManager;
103 import android.hardware.camera2.CameraManager;
104 import android.hardware.display.DisplayManager;
105 import android.hardware.input.InputManager;
106 import android.hardware.usb.UsbManager;
107 import android.location.LocationManager;
108 import android.media.AudioManager;
109 import android.media.MediaRouter;
110 import android.media.projection.MediaProjectionManager;
111 import android.media.session.MediaSessionManager;
112 import android.media.tv.TvInputManager;
113 import android.net.ConnectivityManager;
114 import android.net.nsd.NsdManager;
115 import android.net.wifi.WifiManager;
116 import android.net.wifi.p2p.WifiP2pManager;
117 import android.nfc.NfcManager;
118 import android.os.BatteryManager;
119 import android.os.Build;
120 import android.os.Bundle;
121 import android.os.DropBoxManager;
122 import android.os.Handler;
123 import android.os.PowerManager;
124 import android.os.Process;
125 import android.os.StatFs;
126 import android.os.UserManager;
127 import android.os.Vibrator;
128 import android.os.storage.StorageManager;
129 import android.print.PrintManager;
130 import android.telecom.TelecomManager;
131 import android.telephony.SubscriptionManager;
132 import android.telephony.TelephonyManager;
133 import android.text.TextUtils;
134 import android.util.Log;
135 import android.view.Display;
136 import android.view.LayoutInflater;
137 import android.view.WindowManager;
138 import android.view.accessibility.AccessibilityManager;
139 import android.view.accessibility.CaptioningManager;
140 import android.view.inputmethod.InputMethodManager;
141 import android.view.textservice.TextServicesManager;
142 
143 import androidx.annotation.ColorInt;
144 import androidx.annotation.ColorRes;
145 import androidx.annotation.DisplayContext;
146 import androidx.annotation.DrawableRes;
147 import androidx.annotation.IntDef;
148 import androidx.annotation.RequiresApi;
149 import androidx.annotation.RestrictTo;
150 import androidx.core.app.ActivityOptionsCompat;
151 import androidx.core.app.LocaleManagerCompat;
152 import androidx.core.app.NotificationManagerCompat;
153 import androidx.core.content.res.ResourcesCompat;
154 import androidx.core.os.ConfigurationCompat;
155 import androidx.core.os.EnvironmentCompat;
156 import androidx.core.os.ExecutorCompat;
157 import androidx.core.os.LocaleListCompat;
158 import androidx.core.util.ObjectsCompat;
159 
160 import org.jspecify.annotations.NonNull;
161 import org.jspecify.annotations.Nullable;
162 
163 import java.io.File;
164 import java.lang.annotation.Retention;
165 import java.lang.annotation.RetentionPolicy;
166 import java.util.HashMap;
167 import java.util.concurrent.Executor;
168 
169 /**
170  * Helper for accessing features in {@link Context}.
171  */
172 @SuppressLint("PrivateConstructorForUtilityClass") // Already launched with public constructor
173 public class ContextCompat {
174     private static final String TAG = "ContextCompat";
175 
176     // Lock that provides similar functionality to ContextImpl.mSync.
177     private static final Object sSync = new Object();
178 
179     /**
180      * This class should not be instantiated, but the constructor must be
181      * visible for the class to be extended (ex. in ActivityCompat).
182      */
ContextCompat()183     protected ContextCompat() {
184         // Not publicly instantiable, but may be extended.
185     }
186 
187     private static final String DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX =
188             ".DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION";
189 
190 
191     @RestrictTo(RestrictTo.Scope.LIBRARY)
192     @IntDef(flag = true, value = {
193             RECEIVER_VISIBLE_TO_INSTANT_APPS, RECEIVER_EXPORTED, RECEIVER_NOT_EXPORTED,
194     })
195     @Retention(RetentionPolicy.SOURCE)
196     public @interface RegisterReceiverFlags {}
197     /**
198      * Flag for {@link #registerReceiver}: The receiver can receive broadcasts from Instant Apps.
199      */
200     public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 0x1;
201 
202     /**
203      * Flag for {@link #registerReceiver}: The receiver can receive broadcasts from other Apps.
204      * Has the same behavior as marking a statically registered receiver with "exported=true"
205      */
206     public static final int RECEIVER_EXPORTED = 0x2;
207 
208     /**
209      * Flag for {@link #registerReceiver}: The receiver cannot receive broadcasts from other Apps.
210      * Has the same behavior as marking a statically registered receiver with "exported=false"
211      */
212     public static final int RECEIVER_NOT_EXPORTED = 0x4;
213 
214     /**
215      * Start a set of activities as a synthesized task stack, if able.
216      *
217      * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
218      * app navigation using the back key changed. The back key's behavior is local
219      * to the current task and does not capture navigation across different tasks.
220      * Navigating across tasks and easily reaching the previous task is accomplished
221      * through the "recents" UI, accessible through the software-provided Recents key
222      * on the navigation or system bar. On devices with the older hardware button configuration
223      * the recents UI can be accessed with a long press on the Home key.</p>
224      *
225      * <p>When crossing from one task stack to another post-Android 3.0,
226      * the application should synthesize a back stack/history for the new task so that
227      * the user may navigate out of the new task and back to the Launcher by repeated
228      * presses of the back key. Back key presses should not navigate across task stacks.</p>
229      *
230      * <p>startActivities provides a mechanism for constructing a synthetic task stack of
231      * multiple activities. If the underlying API is not available on the system this method
232      * will return false.</p>
233      *
234      * @param context Start activities using this activity as the starting context
235      * @param intents Array of intents defining the activities that will be started. The element
236      *                length-1 will correspond to the top activity on the resulting task stack.
237      * @return true if the underlying API was available and the call was successful, false otherwise
238      */
startActivities(@onNull Context context, Intent @NonNull [] intents)239     public static boolean startActivities(@NonNull Context context, Intent @NonNull [] intents) {
240         return startActivities(context, intents, null);
241     }
242 
243     /**
244      * Start a set of activities as a synthesized task stack, if able.
245      *
246      * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
247      * app navigation using the back key changed. The back key's behavior is local
248      * to the current task and does not capture navigation across different tasks.
249      * Navigating across tasks and easily reaching the previous task is accomplished
250      * through the "recents" UI, accessible through the software-provided Recents key
251      * on the navigation or system bar. On devices with the older hardware button configuration
252      * the recents UI can be accessed with a long press on the Home key.</p>
253      *
254      * <p>When crossing from one task stack to another post-Android 3.0,
255      * the application should synthesize a back stack/history for the new task so that
256      * the user may navigate out of the new task and back to the Launcher by repeated
257      * presses of the back key. Back key presses should not navigate across task stacks.</p>
258      *
259      * <p>startActivities provides a mechanism for constructing a synthetic task stack of
260      * multiple activities. If the underlying API is not available on the system this method
261      * will return false.</p>
262      *
263      * @param context Start activities using this activity as the starting context
264      * @param intents Array of intents defining the activities that will be started. The element
265      *                length-1 will correspond to the top activity on the resulting task stack.
266      * @param options Additional options for how the Activity should be started.
267      *                See {@link Context#startActivity(Intent, Bundle)}
268      * @return true if the underlying API was available and the call was successful, false otherwise
269      */
startActivities(@onNull Context context, Intent @NonNull [] intents, @Nullable Bundle options)270     public static boolean startActivities(@NonNull Context context, Intent @NonNull [] intents,
271             @Nullable Bundle options) {
272         context.startActivities(intents, options);
273         return true;
274     }
275 
276     /**
277      * Start an activity with additional launch information, if able.
278      *
279      * <p>In Android 4.1+ additional options were introduced to allow for more
280      * control on activity launch animations. Applications can use this method
281      * along with {@link ActivityOptionsCompat} to use these animations when
282      * available. When run on versions of the platform where this feature does
283      * not exist the activity will be launched normally.</p>
284      *
285      * @param context Context to launch activity from.
286      * @param intent  The description of the activity to start.
287      * @param options Additional options for how the Activity should be started.
288      *                May be null if there are no options. See
289      *                {@link ActivityOptionsCompat} for how to build the Bundle
290      *                supplied here; there are no supported definitions for
291      *                building it manually.
292      * @deprecated Call {@link Context#startActivity()} directly.
293      */
294     @Deprecated
295     @androidx.annotation.ReplaceWith(expression = "context.startActivity(intent, options)")
startActivity(@onNull Context context, @NonNull Intent intent, @Nullable Bundle options)296     public static void startActivity(@NonNull Context context, @NonNull Intent intent,
297             @Nullable Bundle options) {
298         context.startActivity(intent, options);
299     }
300 
301     /**
302      * Returns the absolute path to the directory on the filesystem where all
303      * private files belonging to this app are stored. Apps should not use this
304      * path directly; they should instead use {@link Context#getFilesDir()},
305      * {@link Context#getCacheDir()}, {@link Context#getDir(String, int)}, or
306      * other storage APIs on {@link Context}.
307      * <p>
308      * The returned path may change over time if the calling app is moved to an
309      * adopted storage device, so only relative paths should be persisted.
310      * <p>
311      * No additional permissions are required for the calling app to read or
312      * write files under the returned path.
313      *
314      * @see ApplicationInfo#dataDir
315      */
getDataDir(@onNull Context context)316     public static @Nullable File getDataDir(@NonNull Context context) {
317         if (Build.VERSION.SDK_INT >= 24) {
318             return Api24Impl.getDataDir(context);
319         } else {
320             final String dataDir = context.getApplicationInfo().dataDir;
321             return dataDir != null ? new File(dataDir) : null;
322         }
323     }
324 
325     /**
326      * Returns absolute paths to application-specific directories on all
327      * external storage devices where the application's OBB files (if there are
328      * any) can be found. Note if the application does not have any OBB files,
329      * these directories may not exist.
330      * <p>
331      * This is like {@link Context#getFilesDir()} in that these files will be
332      * deleted when the application is uninstalled, however there are some
333      * important differences:
334      * <ul>
335      * <li>External files are not always available: they will disappear if the
336      * user mounts the external storage on a computer or removes it.
337      * <li>There is no security enforced with these files.
338      * </ul>
339      * <p>
340      * External storage devices returned here are considered a permanent part of
341      * the device, including both emulated external storage and physical media
342      * slots, such as SD cards in a battery compartment. The returned paths do
343      * not include transient devices, such as USB flash drives.
344      * <p>
345      * An application may store data on any or all of the returned devices. For
346      * example, an app may choose to store large files on the device with the
347      * most available space, as measured by {@link StatFs}.
348      * <p>
349      * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions
350      * are required to write to the returned paths; they're always accessible to
351      * the calling app. Before then,
352      * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
353      * write. Write access outside of these paths on secondary external storage
354      * devices is not available. To request external storage access in a
355      * backwards compatible way, consider using {@code android:maxSdkVersion}
356      * like this:
357      *
358      * <pre class="prettyprint">&lt;uses-permission
359      *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
360      *     android:maxSdkVersion="18" /&gt;</pre>
361      * <p>
362      * The first path returned is the same as {@link Context#getObbDir()}.
363      * Returned paths may be {@code null} if a storage device is unavailable.
364      *
365      * @see Context#getObbDir()
366      * @see EnvironmentCompat#getStorageState(File)
367      * @deprecated Call {@link Context#getObbDirs()} directly.
368      */
369     @Deprecated
370     @androidx.annotation.ReplaceWith(expression = "context.getObbDirs()")
getObbDirs(@onNull Context context)371     public static File @NonNull [] getObbDirs(@NonNull Context context) {
372         return context.getObbDirs();
373     }
374 
375     /**
376      * Returns absolute paths to application-specific directories on all
377      * external storage devices where the application can place persistent files
378      * it owns. These files are internal to the application, and not typically
379      * visible to the user as media.
380      * <p>
381      * This is like {@link Context#getFilesDir()} in that these files will be
382      * deleted when the application is uninstalled, however there are some
383      * important differences:
384      * <ul>
385      * <li>External files are not always available: they will disappear if the
386      * user mounts the external storage on a computer or removes it.
387      * <li>There is no security enforced with these files.
388      * </ul>
389      * <p>
390      * External storage devices returned here are considered a permanent part of
391      * the device, including both emulated external storage and physical media
392      * slots, such as SD cards in a battery compartment. The returned paths do
393      * not include transient devices, such as USB flash drives.
394      * <p>
395      * An application may store data on any or all of the returned devices. For
396      * example, an app may choose to store large files on the device with the
397      * most available space, as measured by {@link StatFs}.
398      * <p>
399      * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions
400      * are required to write to the returned paths; they're always accessible to
401      * the calling app. Before then,
402      * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
403      * write. Write access outside of these paths on secondary external storage
404      * devices is not available. To request external storage access in a
405      * backwards compatible way, consider using {@code android:maxSdkVersion}
406      * like this:
407      *
408      * <pre class="prettyprint">&lt;uses-permission
409      *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
410      *     android:maxSdkVersion="18" /&gt;</pre>
411      * <p>
412      * The first path returned is the same as
413      * {@link Context#getExternalFilesDir(String)}. Returned paths may be
414      * {@code null} if a storage device is unavailable.
415      *
416      * @see Context#getExternalFilesDir(String)
417      * @see EnvironmentCompat#getStorageState(File)
418      * @deprecated Call {@link Context#getExternalFilesDirs()} directly.
419      */
420     @Deprecated
421     @androidx.annotation.ReplaceWith(expression = "context.getExternalFilesDirs(type)")
getExternalFilesDirs(@onNull Context context, @Nullable String type)422     public static File @NonNull [] getExternalFilesDirs(@NonNull Context context,
423             @Nullable String type) {
424         return context.getExternalFilesDirs(type);
425     }
426 
427     /**
428      * Returns absolute paths to application-specific directories on all
429      * external storage devices where the application can place cache files it
430      * owns. These files are internal to the application, and not typically
431      * visible to the user as media.
432      * <p>
433      * This is like {@link Context#getCacheDir()} in that these files will be
434      * deleted when the application is uninstalled, however there are some
435      * important differences:
436      * <ul>
437      * <li>External files are not always available: they will disappear if the
438      * user mounts the external storage on a computer or removes it.
439      * <li>There is no security enforced with these files.
440      * </ul>
441      * <p>
442      * External storage devices returned here are considered a permanent part of
443      * the device, including both emulated external storage and physical media
444      * slots, such as SD cards in a battery compartment. The returned paths do
445      * not include transient devices, such as USB flash drives.
446      * <p>
447      * An application may store data on any or all of the returned devices. For
448      * example, an app may choose to store large files on the device with the
449      * most available space, as measured by {@link StatFs}.
450      * <p>
451      * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions
452      * are required to write to the returned paths; they're always accessible to
453      * the calling app. Before then,
454      * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
455      * write. Write access outside of these paths on secondary external storage
456      * devices is not available. To request external storage access in a
457      * backwards compatible way, consider using {@code android:maxSdkVersion}
458      * like this:
459      *
460      * <pre class="prettyprint">&lt;uses-permission
461      *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
462      *     android:maxSdkVersion="18" /&gt;</pre>
463      * <p>
464      * The first path returned is the same as
465      * {@link Context#getExternalCacheDir()}. Returned paths may be {@code null}
466      * if a storage device is unavailable.
467      *
468      * @see Context#getExternalCacheDir()
469      * @see EnvironmentCompat#getStorageState(File)
470      * @deprecated Call {@link Context#getExternalCacheDirs()} directly.
471      */
472     @Deprecated
473     @androidx.annotation.ReplaceWith(expression = "context.getExternalCacheDirs()")
getExternalCacheDirs(@onNull Context context)474     public static File @NonNull [] getExternalCacheDirs(@NonNull Context context) {
475         return context.getExternalCacheDirs();
476     }
477 
478     /**
479      * Returns a drawable object associated with a particular resource ID.
480      * <p>
481      * Starting in {@link Build.VERSION_CODES#LOLLIPOP}, the
482      * returned drawable will be styled for the specified Context's theme.
483      *
484      * @param context context to use for getting the drawable.
485      * @param id The desired resource identifier, as generated by the aapt tool.
486      *           This integer encodes the package, type, and resource entry.
487      *           The value 0 is an invalid identifier.
488      * @return Drawable An object that can be used to draw this resource.
489      */
490     @SuppressWarnings("deprecation")
getDrawable(@onNull Context context, @DrawableRes int id)491     public static @Nullable Drawable getDrawable(@NonNull Context context, @DrawableRes int id) {
492         if (Build.VERSION.SDK_INT >= 21) {
493             return Api21Impl.getDrawable(context, id);
494         } else {
495             return context.getResources().getDrawable(id);
496         }
497     }
498 
499     /**
500      * Returns a color state list associated with a particular resource ID.
501      * <p>
502      * Starting in {@link Build.VERSION_CODES#M}, the returned
503      * color state list will be styled for the specified Context's theme.
504      *
505      * @param context context to use for getting the color state list.
506      * @param id The desired resource identifier, as generated by the aapt
507      *           tool. This integer encodes the package, type, and resource
508      *           entry. The value 0 is an invalid identifier.
509      * @return A color state list, or {@code null} if the resource could not be
510      * resolved.
511      * @throws android.content.res.Resources.NotFoundException if the given ID
512      *         does not exist.
513      */
getColorStateList(@onNull Context context, @ColorRes int id)514     public static @Nullable ColorStateList getColorStateList(@NonNull Context context,
515             @ColorRes int id) {
516         return ResourcesCompat.getColorStateList(context.getResources(), id, context.getTheme());
517     }
518 
519     /**
520      * Returns a color associated with a particular resource ID
521      * <p>
522      * Starting in {@link Build.VERSION_CODES#M}, the returned
523      * color will be styled for the specified Context's theme.
524      *
525      * @param context context to use for getting the color.
526      * @param id The desired resource identifier, as generated by the aapt
527      *           tool. This integer encodes the package, type, and resource
528      *           entry. The value 0 is an invalid identifier.
529      * @return A single color value in the form 0xAARRGGBB.
530      * @throws android.content.res.Resources.NotFoundException if the given ID
531      *         does not exist.
532      */
533     @SuppressWarnings("deprecation")
534     @ColorInt
getColor(@onNull Context context, @ColorRes int id)535     public static int getColor(@NonNull Context context, @ColorRes int id) {
536         if (Build.VERSION.SDK_INT >= 23) {
537             return Api23Impl.getColor(context, id);
538         } else {
539             return context.getResources().getColor(id);
540         }
541     }
542 
543     /**
544      * Determine whether <em>you</em> have been granted a particular permission.
545      *
546      * @param context context for which to check the permission.
547      * @param permission The name of the permission being checked.
548      * @return {@link PackageManager#PERMISSION_GRANTED} if you have the
549      * permission, or {@link PackageManager#PERMISSION_DENIED} if not.
550      * @see PackageManager#checkPermission(String, String)
551      */
checkSelfPermission(@onNull Context context, @NonNull String permission)552     public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
553         ObjectsCompat.requireNonNull(permission, "permission must be non-null");
554         if (Build.VERSION.SDK_INT < 33
555                 && TextUtils.equals(android.Manifest.permission.POST_NOTIFICATIONS, permission)) {
556             return NotificationManagerCompat.from(context).areNotificationsEnabled()
557                     ? PackageManager.PERMISSION_GRANTED
558                     : PackageManager.PERMISSION_DENIED;
559         }
560         return context.checkPermission(permission, Process.myPid(), Process.myUid());
561     }
562 
563     /**
564      * Returns the absolute path to the directory on the filesystem similar to
565      * {@link Context#getFilesDir()}.  The difference is that files placed under this
566      * directory will be excluded from automatic backup to remote storage on
567      * devices running {@link Build.VERSION_CODES#LOLLIPOP} or later.
568      *
569      * <p>No permissions are required to read or write to the returned path, since this
570      * path is internal storage.
571      *
572      * @return The path of the directory holding application files that will not be
573      * automatically backed up to remote storage.
574      * @see Context#getFilesDir()
575      */
getNoBackupFilesDir(@onNull Context context)576     public static @Nullable File getNoBackupFilesDir(@NonNull Context context) {
577         if (Build.VERSION.SDK_INT >= 21) {
578             return Api21Impl.getNoBackupFilesDir(context);
579         } else {
580             ApplicationInfo appInfo = context.getApplicationInfo();
581             return createFilesDir(new File(appInfo.dataDir, "no_backup"));
582         }
583     }
584 
585     /**
586      * Returns the absolute path to the application specific cache directory on
587      * the filesystem designed for storing cached code. On devices running
588      * {@link Build.VERSION_CODES#LOLLIPOP} or later, the system will delete
589      * any files stored in this location both when your specific application is
590      * upgraded, and when the entire platform is upgraded.
591      * <p>
592      * This location is optimal for storing compiled or optimized code generated
593      * by your application at runtime.
594      * <p>
595      * Apps require no extra permissions to read or write to the returned path,
596      * since this path lives in their private storage.
597      *
598      * @return The path of the directory holding application code cache files.
599      */
getCodeCacheDir(@onNull Context context)600     public static @NonNull File getCodeCacheDir(@NonNull Context context) {
601         if (Build.VERSION.SDK_INT >= 21) {
602             return Api21Impl.getCodeCacheDir(context);
603         } else {
604             ApplicationInfo appInfo = context.getApplicationInfo();
605             return createFilesDir(new File(appInfo.dataDir, "code_cache"));
606         }
607     }
608 
createFilesDir(File file)609     private static File createFilesDir(File file) {
610         // In the platform, all operations on Context that involve creating files (codeCacheDir,
611         // noBackupFilesDir, etc.) are synchronized on a single lock owned by the Context. So, if
612         // we lock on a single static lock owned by ContextCompat then we're a bit too broad but
613         // at least we'll provide similar guarantees.
614         synchronized (sSync) {
615             if (!file.exists()) {
616                 if (file.mkdirs()) {
617                     return file;
618                 } else {
619                     // There used to be another check for file.exists() here, but that was a
620                     // side-effect of improper synchronization.
621                     Log.w(TAG, "Unable to create files subdir " + file.getPath());
622                 }
623             }
624             return file;
625         }
626     }
627 
628     /**
629      * Return a new Context object for the current Context but whose storage
630      * APIs are backed by device-protected storage.
631      * <p>
632      * On devices with direct boot, data stored in this location is encrypted
633      * with a key tied to the physical device, and it can be accessed
634      * immediately after the device has booted successfully, both
635      * <em>before and after</em> the user has authenticated with their
636      * credentials (such as a lock pattern or PIN).
637      * <p>
638      * Because device-protected data is available without user authentication,
639      * you should carefully limit the data you store using this Context. For
640      * example, storing sensitive authentication tokens or passwords in the
641      * device-protected area is strongly discouraged.
642      * <p>
643      * If the underlying device does not have the ability to store
644      * device-protected and credential-protected data using different keys, then
645      * both storage areas will become available at the same time. They remain as
646      * two distinct storage locations on disk, and only the window of
647      * availability changes.
648      * <p>
649      * Each call to this method returns a new instance of a Context object;
650      * Context objects are not shared, however common state (ClassLoader, other
651      * Resources for the same configuration) may be so the Context itself can be
652      * fairly lightweight.
653      * <p>
654      * Prior to API 24 this method returns
655      * {@code null}, since device-protected storage is not available.
656      *
657      * @see ContextCompat#isDeviceProtectedStorage(Context)
658      */
createDeviceProtectedStorageContext(@onNull Context context)659     public static @Nullable Context createDeviceProtectedStorageContext(@NonNull Context context) {
660         if (Build.VERSION.SDK_INT >= 24) {
661             return Api24Impl.createDeviceProtectedStorageContext(context);
662         } else {
663             return null;
664         }
665     }
666 
667     /**
668      * Indicates if the storage APIs of this Context are backed by
669      * device-encrypted storage.
670      *
671      * @see ContextCompat#createDeviceProtectedStorageContext(Context)
672      */
isDeviceProtectedStorage(@onNull Context context)673     public static boolean isDeviceProtectedStorage(@NonNull Context context) {
674         if (Build.VERSION.SDK_INT >= 24) {
675             return Api24Impl.isDeviceProtectedStorage(context);
676         } else {
677             return false;
678         }
679     }
680 
681     /**
682      * Return an {@link Executor} that will run enqueued tasks on the main
683      * thread associated with this context. This is the thread used to dispatch
684      * calls to application components (activities, services, etc).
685      */
getMainExecutor(@onNull Context context)686     public static @NonNull Executor getMainExecutor(@NonNull Context context) {
687         if (Build.VERSION.SDK_INT >= 28) {
688             return Api28Impl.getMainExecutor(context);
689         }
690         return ExecutorCompat.create(new Handler(context.getMainLooper()));
691     }
692 
693     /**
694      * startForegroundService() was introduced in O, just call startService
695      * for before O.
696      *
697      * @param context Context to start Service from.
698      * @param intent  The description of the Service to start.
699      * @see Context#startForegroundService(Intent)
700      * @see Context#startService(Intent)
701      */
startForegroundService(@onNull Context context, @NonNull Intent intent)702     public static void startForegroundService(@NonNull Context context, @NonNull Intent intent) {
703         if (Build.VERSION.SDK_INT >= 26) {
704             Api26Impl.startForegroundService(context, intent);
705         } else {
706             // Pre-O behavior.
707             context.startService(intent);
708         }
709     }
710 
711     /**
712      * Get the display this context is associated with or the
713      * {@link Display#DEFAULT_DISPLAY default display} as the fallback if the context is not
714      * associated with any {@link Display}.
715      * <p>
716      * Applications must use this method with {@link Activity} or a context associated with a
717      * {@link Display} via {@link Context#createDisplayContext(Display)} or
718      * {@link Context#createWindowContext(Display, int, Bundle)}, or the reported {@link Display}
719      * instance is not reliable. </p>
720      *
721      * @param context Context to obtain the associated display
722      * @return The display associated with the Context or the default display if the context
723      * doesn't associated with any display.
724      */
getDisplayOrDefault(@isplayContext @onNull Context context)725     public static @NonNull Display getDisplayOrDefault(@DisplayContext @NonNull Context context) {
726         if (Build.VERSION.SDK_INT >= 30) {
727             return Api30Impl.getDisplayOrDefault(context);
728         } else {
729             final WindowManager windowManager =
730                     (WindowManager) context.getSystemService(WINDOW_SERVICE);
731             return windowManager.getDefaultDisplay();
732         }
733     }
734 
735     /**
736      * Return the handle to a system-level service by class.
737      *
738      * @param context      Context to retrieve service from.
739      * @param serviceClass The class of the desired service.
740      * @return The service or null if the class is not a supported system service.
741      * @see Context#getSystemService(Class)
742      */
743     @SuppressWarnings("unchecked")
getSystemService(@onNull Context context, @NonNull Class<T> serviceClass)744     public static <T> @Nullable T getSystemService(@NonNull Context context,
745             @NonNull Class<T> serviceClass) {
746         if (Build.VERSION.SDK_INT >= 23) {
747             return Api23Impl.getSystemService(context, serviceClass);
748         }
749 
750         String serviceName = getSystemServiceName(context, serviceClass);
751         return serviceName != null ? (T) context.getSystemService(serviceName) : null;
752     }
753 
754     /**
755      * Register a broadcast receiver.
756      *
757      * @param context  Context to retrieve service from.
758      * @param receiver The BroadcastReceiver to handle the broadcast.
759      * @param filter   Selects the Intent broadcasts to be received.
760      * @param flags    If this receiver is listening for broadcasts sent from other apps—even other
761      *                 apps that you own—use the {@link #RECEIVER_EXPORTED} flag. If instead this
762      *                 receiver is listening only for broadcasts sent by your
763      *                 app, or from the system UID, use the {@link #RECEIVER_NOT_EXPORTED} flag.
764      * @return The first sticky intent found that matches <var>filter</var>,
765      * or null if there are none.
766      * @see Context#registerReceiver(BroadcastReceiver, IntentFilter, int)
767      * @see https://developer.android.com/develop/background-work/background-tasks/broadcasts#context-registered-receivers
768      */
registerReceiver(@onNull Context context, @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @RegisterReceiverFlags int flags)769     public static @Nullable Intent registerReceiver(@NonNull Context context,
770             @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter,
771             @RegisterReceiverFlags int flags) {
772         return registerReceiver(context, receiver, filter, null, null, flags);
773     }
774 
775     /**
776      * Register a broadcast receiver.
777      *
778      * @param context             Context to retrieve service from.
779      * @param receiver            The BroadcastReceiver to handle the broadcast.
780      * @param filter              Selects the Intent broadcasts to be received.
781      * @param broadcastPermission String naming a permission that a broadcaster must hold in
782      *                            order to send and Intent to you. If null, no permission is
783      *                            required.
784      * @param scheduler           Handler identifying the thread will receive the Intent. If
785      *                            null, the main thread of the process will be used.
786      * @param flags               If this receiver is listening for broadcasts sent from other
787      *                            apps—even other apps that you own—use the
788      *                            {@link #RECEIVER_EXPORTED} flag. If instead this receiver is
789      *                            listening only for broadcasts sent by your app, or from the
790      *                            system UID, use the {@link #RECEIVER_NOT_EXPORTED} flag.
791      * @return The first sticky intent found that matches <var>filter</var>,
792      * or null if there are none.
793      * @see Context#registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)
794      * @see https://developer.android.com/develop/background-work/background-tasks/broadcasts#context-registered-receivers
795      */
registerReceiver(@onNull Context context, @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler, @RegisterReceiverFlags int flags)796     public static @Nullable Intent registerReceiver(@NonNull Context context,
797             @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter,
798             @Nullable String broadcastPermission,
799             @Nullable Handler scheduler, @RegisterReceiverFlags int flags) {
800         if (((flags & RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0) && ((flags & RECEIVER_NOT_EXPORTED)
801                 != 0)) {
802             throw new IllegalArgumentException("Cannot specify both "
803                     + "RECEIVER_VISIBLE_TO_INSTANT_APPS and RECEIVER_NOT_EXPORTED");
804         }
805 
806         if ((flags & RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0) {
807             flags |= RECEIVER_EXPORTED;
808         }
809 
810         if (((flags & RECEIVER_EXPORTED) == 0) && ((flags & RECEIVER_NOT_EXPORTED) == 0)) {
811             throw new IllegalArgumentException("One of either RECEIVER_EXPORTED or "
812                     + "RECEIVER_NOT_EXPORTED is required");
813         }
814 
815         if (((flags & RECEIVER_EXPORTED) != 0) && ((flags & RECEIVER_NOT_EXPORTED) != 0)) {
816             throw new IllegalArgumentException("Cannot specify both RECEIVER_EXPORTED and "
817                     + "RECEIVER_NOT_EXPORTED");
818         }
819 
820         if (Build.VERSION.SDK_INT >= 33) {
821             return Api33Impl.registerReceiver(context, receiver, filter, broadcastPermission,
822                     scheduler, flags);
823         }
824         if (Build.VERSION.SDK_INT >= 26) {
825             return Api26Impl.registerReceiver(context, receiver, filter, broadcastPermission,
826                     scheduler, flags);
827         }
828         if (((flags & RECEIVER_NOT_EXPORTED) != 0) && (broadcastPermission == null)) {
829             String permission = obtainAndCheckReceiverPermission(context);
830             return context.registerReceiver(receiver, filter, permission, scheduler /* handler */);
831         }
832         return context.registerReceiver(receiver, filter, broadcastPermission,
833                 scheduler);
834     }
835 
836     /**
837      * Gets the name of the system-level service that is represented by the specified class.
838      *
839      * @param context      Context to retrieve service name from.
840      * @param serviceClass The class of the desired service.
841      * @return The service name or null if the class is not a supported system service.
842      * @see Context#getSystemServiceName(Class)
843      */
getSystemServiceName(@onNull Context context, @NonNull Class<?> serviceClass)844     public static @Nullable String getSystemServiceName(@NonNull Context context,
845             @NonNull Class<?> serviceClass) {
846         if (Build.VERSION.SDK_INT >= 23) {
847             return Api23Impl.getSystemServiceName(context, serviceClass);
848         }
849         return LegacyServiceMapHolder.SERVICES.get(serviceClass);
850     }
851 
852     /**
853      * Gets the resource string that also respects the per-app locales. If developers set the
854      * per-app locales via
855      * {@link androidx.appcompat.app.AppCompatDelegate#setApplicationLocales(LocaleListCompat)},
856      * this API returns localized strings even if the context is not
857      * {@link androidx.appcompat.app.AppCompatActivity}.
858      *
859      * <p>
860      * Compatibility behavior:
861      * <ul>
862      *     <li>API 17 and above, this method return the localized string that respects per-app
863      *     locales.</li>
864      *     <li>API 16 and earlier, this method directly return the result of
865      *     {@link Context#getString(int)}</li>
866      * </ul>
867      * </p>
868      */
getString(@onNull Context context, int resId)869     public static @NonNull String getString(@NonNull Context context, int resId) {
870         return getContextForLanguage(context).getString(resId);
871     }
872 
873     /**
874      * Gets the context which respects the per-app locales locale. This API is specifically for
875      * developers who set the per-app locales via
876      * {@link androidx.appcompat.app.AppCompatDelegate#setApplicationLocales(LocaleListCompat)},
877      * but who needs to use the context out of {@link androidx.appcompat.app.AppCompatActivity}
878      * scope.
879      *
880      * <p>The developers can override the returned context in Application's
881      * {@link android.content.ContextWrapper#attachBaseContext(Context)}, so that developers can
882      * get the localized string via application's context.</p>
883      *
884      * <p>
885      * Compatibility behavior:
886      * <ul>
887      *     <li>API 17 and above, the locale in the context returned by this method will respect the
888      *     the per-app locale.</li>
889      *     <li>API 16 and earlier, this method directly return the {@link Context}</li>
890      * </ul>
891      * </p>
892      */
getContextForLanguage(@onNull Context context)893     public static @NonNull Context getContextForLanguage(@NonNull Context context) {
894         LocaleListCompat locales = LocaleManagerCompat.getApplicationLocales(context);
895 
896         // The Android framework supports per-app locales on API 33, so we assume the
897         // configuration has been updated after API 32.
898         if (Build.VERSION.SDK_INT <= 32) {
899             if (!locales.isEmpty()) {
900                 Configuration newConfig = new Configuration(
901                         context.getResources().getConfiguration());
902                 ConfigurationCompat.setLocales(newConfig, locales);
903                 return context.createConfigurationContext(newConfig);
904             }
905         }
906         return context;
907     }
908 
909     /**
910      * Attribution can be used in complex apps to logically separate parts of the app. E.g. a
911      * blogging app might also have a instant messaging app built in. In this case two separate tags
912      * can for used each sub-feature.
913      * <p>
914      * Compatibility behavior:
915      * <ul>
916      *     <li>API 30 and above, returns the attribution tag or {@code null}
917      *     <li>API 29 and earlier, returns {@code null}
918      * </ul>
919      *
920      * @return the attribution tag this context is for or {@code null} if this is the default.
921      */
getAttributionTag(@onNull Context context)922     public static @Nullable String getAttributionTag(@NonNull Context context) {
923         if (Build.VERSION.SDK_INT >= 30) {
924             return Api30Impl.getAttributionTag(context);
925         }
926 
927         return null;
928     }
929 
930     /**
931      * Return a new Context object for the current Context but attribute to a different tag.
932      * In complex apps attribution tagging can be used to distinguish between separate logical
933      * parts.
934      * <p>
935      * Compatibility behavior:
936      * <ul>
937      *     <li>API 30 and above, returns a new Context object with the specified attribution tag
938      *     <li>API 29 and earlier, returns the original {@code context} with no attribution tag
939      * </ul>
940      *
941      * @param context The current context.
942      * @param attributionTag The tag or {@code null} to create a context for the default.
943      * @return A {@link Context} that is tagged for the new attribution
944      * @see #getAttributionTag(Context)
945      */
createAttributionContext(@onNull Context context, @Nullable String attributionTag)946     public static @NonNull Context createAttributionContext(@NonNull Context context,
947             @Nullable String attributionTag) {
948         if (Build.VERSION.SDK_INT >= 30) {
949             return Api30Impl.createAttributionContext(context, attributionTag);
950         }
951 
952         return context;
953     }
954 
955     /**
956      * Gets the name of the permission required to unexport receivers on pre Tiramisu versions of
957      * Android, and then asserts that the app registering the receiver also has that permission
958      * so it can receiver its own broadcasts.
959      *
960      * @param obj Context to check the permission in.
961      * @return The name of the permission
962      */
obtainAndCheckReceiverPermission(Context obj)963     static String obtainAndCheckReceiverPermission(Context obj) {
964         String permission = obj.getApplicationContext().getPackageName()
965                 + DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX;
966 
967         if (PermissionChecker.checkSelfPermission(obj, permission)
968                 != PermissionChecker.PERMISSION_GRANTED) {
969             if (Build.VERSION.SDK_INT >= 29) {
970                 permission =
971                         obj.getOpPackageName() + DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX;
972                 if (PermissionChecker.checkSelfPermission(obj, permission)
973                         == PermissionChecker.PERMISSION_GRANTED) {
974                     return permission;
975                 }
976             }
977             throw new RuntimeException("Permission " + permission + " is required by your "
978                     + "application to receive broadcasts, please add it to your manifest");
979         }
980         return permission;
981     }
982 
983     /** Nested class provides lazy initialization only when needed. */
984     private static final class LegacyServiceMapHolder {
985         static final HashMap<Class<?>, String> SERVICES = new HashMap<>();
986 
987         static {
988             if (Build.VERSION.SDK_INT >= 22) {
SERVICES.put(SubscriptionManager.class, TELEPHONY_SUBSCRIPTION_SERVICE)989                 SERVICES.put(SubscriptionManager.class, TELEPHONY_SUBSCRIPTION_SERVICE);
SERVICES.put(UsageStatsManager.class, USAGE_STATS_SERVICE)990                 SERVICES.put(UsageStatsManager.class, USAGE_STATS_SERVICE);
991             }
992             if (Build.VERSION.SDK_INT >= 21) {
SERVICES.put(AppWidgetManager.class, APPWIDGET_SERVICE)993                 SERVICES.put(AppWidgetManager.class, APPWIDGET_SERVICE);
SERVICES.put(BatteryManager.class, BATTERY_SERVICE)994                 SERVICES.put(BatteryManager.class, BATTERY_SERVICE);
SERVICES.put(CameraManager.class, CAMERA_SERVICE)995                 SERVICES.put(CameraManager.class, CAMERA_SERVICE);
SERVICES.put(JobScheduler.class, JOB_SCHEDULER_SERVICE)996                 SERVICES.put(JobScheduler.class, JOB_SCHEDULER_SERVICE);
SERVICES.put(LauncherApps.class, LAUNCHER_APPS_SERVICE)997                 SERVICES.put(LauncherApps.class, LAUNCHER_APPS_SERVICE);
SERVICES.put(MediaProjectionManager.class, MEDIA_PROJECTION_SERVICE)998                 SERVICES.put(MediaProjectionManager.class, MEDIA_PROJECTION_SERVICE);
SERVICES.put(MediaSessionManager.class, MEDIA_SESSION_SERVICE)999                 SERVICES.put(MediaSessionManager.class, MEDIA_SESSION_SERVICE);
SERVICES.put(RestrictionsManager.class, RESTRICTIONS_SERVICE)1000                 SERVICES.put(RestrictionsManager.class, RESTRICTIONS_SERVICE);
SERVICES.put(TelecomManager.class, TELECOM_SERVICE)1001                 SERVICES.put(TelecomManager.class, TELECOM_SERVICE);
SERVICES.put(TvInputManager.class, TV_INPUT_SERVICE)1002                 SERVICES.put(TvInputManager.class, TV_INPUT_SERVICE);
1003             }
1004 
SERVICES.put(AppOpsManager.class, APP_OPS_SERVICE)1005             SERVICES.put(AppOpsManager.class, APP_OPS_SERVICE);
SERVICES.put(CaptioningManager.class, CAPTIONING_SERVICE)1006             SERVICES.put(CaptioningManager.class, CAPTIONING_SERVICE);
SERVICES.put(ConsumerIrManager.class, CONSUMER_IR_SERVICE)1007             SERVICES.put(ConsumerIrManager.class, CONSUMER_IR_SERVICE);
SERVICES.put(PrintManager.class, PRINT_SERVICE)1008             SERVICES.put(PrintManager.class, PRINT_SERVICE);
SERVICES.put(BluetoothManager.class, BLUETOOTH_SERVICE)1009             SERVICES.put(BluetoothManager.class, BLUETOOTH_SERVICE);
SERVICES.put(DisplayManager.class, DISPLAY_SERVICE)1010             SERVICES.put(DisplayManager.class, DISPLAY_SERVICE);
SERVICES.put(UserManager.class, USER_SERVICE)1011             SERVICES.put(UserManager.class, USER_SERVICE);
1012 
SERVICES.put(InputManager.class, INPUT_SERVICE)1013             SERVICES.put(InputManager.class, INPUT_SERVICE);
SERVICES.put(MediaRouter.class, MEDIA_ROUTER_SERVICE)1014             SERVICES.put(MediaRouter.class, MEDIA_ROUTER_SERVICE);
SERVICES.put(NsdManager.class, NSD_SERVICE)1015             SERVICES.put(NsdManager.class, NSD_SERVICE);
SERVICES.put(AccessibilityManager.class, ACCESSIBILITY_SERVICE)1016             SERVICES.put(AccessibilityManager.class, ACCESSIBILITY_SERVICE);
SERVICES.put(AccountManager.class, ACCOUNT_SERVICE)1017             SERVICES.put(AccountManager.class, ACCOUNT_SERVICE);
SERVICES.put(ActivityManager.class, ACTIVITY_SERVICE)1018             SERVICES.put(ActivityManager.class, ACTIVITY_SERVICE);
SERVICES.put(AlarmManager.class, ALARM_SERVICE)1019             SERVICES.put(AlarmManager.class, ALARM_SERVICE);
SERVICES.put(AudioManager.class, AUDIO_SERVICE)1020             SERVICES.put(AudioManager.class, AUDIO_SERVICE);
SERVICES.put(ClipboardManager.class, CLIPBOARD_SERVICE)1021             SERVICES.put(ClipboardManager.class, CLIPBOARD_SERVICE);
SERVICES.put(ConnectivityManager.class, CONNECTIVITY_SERVICE)1022             SERVICES.put(ConnectivityManager.class, CONNECTIVITY_SERVICE);
SERVICES.put(DevicePolicyManager.class, DEVICE_POLICY_SERVICE)1023             SERVICES.put(DevicePolicyManager.class, DEVICE_POLICY_SERVICE);
SERVICES.put(DownloadManager.class, DOWNLOAD_SERVICE)1024             SERVICES.put(DownloadManager.class, DOWNLOAD_SERVICE);
SERVICES.put(DropBoxManager.class, DROPBOX_SERVICE)1025             SERVICES.put(DropBoxManager.class, DROPBOX_SERVICE);
SERVICES.put(InputMethodManager.class, INPUT_METHOD_SERVICE)1026             SERVICES.put(InputMethodManager.class, INPUT_METHOD_SERVICE);
SERVICES.put(KeyguardManager.class, KEYGUARD_SERVICE)1027             SERVICES.put(KeyguardManager.class, KEYGUARD_SERVICE);
SERVICES.put(LayoutInflater.class, LAYOUT_INFLATER_SERVICE)1028             SERVICES.put(LayoutInflater.class, LAYOUT_INFLATER_SERVICE);
SERVICES.put(LocationManager.class, LOCATION_SERVICE)1029             SERVICES.put(LocationManager.class, LOCATION_SERVICE);
SERVICES.put(NfcManager.class, NFC_SERVICE)1030             SERVICES.put(NfcManager.class, NFC_SERVICE);
SERVICES.put(NotificationManager.class, NOTIFICATION_SERVICE)1031             SERVICES.put(NotificationManager.class, NOTIFICATION_SERVICE);
SERVICES.put(PowerManager.class, POWER_SERVICE)1032             SERVICES.put(PowerManager.class, POWER_SERVICE);
SERVICES.put(SearchManager.class, SEARCH_SERVICE)1033             SERVICES.put(SearchManager.class, SEARCH_SERVICE);
SERVICES.put(SensorManager.class, SENSOR_SERVICE)1034             SERVICES.put(SensorManager.class, SENSOR_SERVICE);
SERVICES.put(StorageManager.class, STORAGE_SERVICE)1035             SERVICES.put(StorageManager.class, STORAGE_SERVICE);
SERVICES.put(TelephonyManager.class, TELEPHONY_SERVICE)1036             SERVICES.put(TelephonyManager.class, TELEPHONY_SERVICE);
SERVICES.put(TextServicesManager.class, TEXT_SERVICES_MANAGER_SERVICE)1037             SERVICES.put(TextServicesManager.class, TEXT_SERVICES_MANAGER_SERVICE);
SERVICES.put(UiModeManager.class, UI_MODE_SERVICE)1038             SERVICES.put(UiModeManager.class, UI_MODE_SERVICE);
SERVICES.put(UsbManager.class, USB_SERVICE)1039             SERVICES.put(UsbManager.class, USB_SERVICE);
SERVICES.put(Vibrator.class, VIBRATOR_SERVICE)1040             SERVICES.put(Vibrator.class, VIBRATOR_SERVICE);
SERVICES.put(WallpaperManager.class, WALLPAPER_SERVICE)1041             SERVICES.put(WallpaperManager.class, WALLPAPER_SERVICE);
SERVICES.put(WifiP2pManager.class, WIFI_P2P_SERVICE)1042             SERVICES.put(WifiP2pManager.class, WIFI_P2P_SERVICE);
SERVICES.put(WifiManager.class, WIFI_SERVICE)1043             SERVICES.put(WifiManager.class, WIFI_SERVICE);
SERVICES.put(WindowManager.class, WINDOW_SERVICE)1044             SERVICES.put(WindowManager.class, WINDOW_SERVICE);
1045         }
1046     }
1047 
1048     @RequiresApi(21)
1049     static class Api21Impl {
Api21Impl()1050         private Api21Impl() {
1051             // This class is not instantiable.
1052         }
1053 
getDrawable(Context obj, int id)1054         static Drawable getDrawable(Context obj, int id) {
1055             return obj.getDrawable(id);
1056         }
1057 
getNoBackupFilesDir(Context obj)1058         static File getNoBackupFilesDir(Context obj) {
1059             return obj.getNoBackupFilesDir();
1060         }
1061 
getCodeCacheDir(Context obj)1062         static File getCodeCacheDir(Context obj) {
1063             return obj.getCodeCacheDir();
1064         }
1065     }
1066 
1067     @RequiresApi(23)
1068     static class Api23Impl {
Api23Impl()1069         private Api23Impl() {
1070             // This class is not instantiable.
1071         }
1072 
getColor(Context obj, int id)1073         static int getColor(Context obj, int id) {
1074             return obj.getColor(id);
1075         }
1076 
getSystemService(Context obj, Class<T> serviceClass)1077         static <T> T getSystemService(Context obj, Class<T> serviceClass) {
1078             return obj.getSystemService(serviceClass);
1079         }
1080 
getSystemServiceName(Context obj, Class<?> serviceClass)1081         static String getSystemServiceName(Context obj, Class<?> serviceClass) {
1082             return obj.getSystemServiceName(serviceClass);
1083         }
1084     }
1085 
1086     @RequiresApi(24)
1087     static class Api24Impl {
Api24Impl()1088         private Api24Impl() {
1089             // This class is not instantiable.
1090         }
1091 
getDataDir(Context obj)1092         static File getDataDir(Context obj) {
1093             return obj.getDataDir();
1094         }
1095 
createDeviceProtectedStorageContext(Context obj)1096         static Context createDeviceProtectedStorageContext(Context obj) {
1097             return obj.createDeviceProtectedStorageContext();
1098         }
1099 
isDeviceProtectedStorage(Context obj)1100         static boolean isDeviceProtectedStorage(Context obj) {
1101             return obj.isDeviceProtectedStorage();
1102         }
1103     }
1104 
1105     @RequiresApi(26)
1106     static class Api26Impl {
Api26Impl()1107         private Api26Impl() {
1108             // This class is not instantiable.
1109         }
1110 
registerReceiver(Context obj, @Nullable BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags)1111         static Intent registerReceiver(Context obj, @Nullable BroadcastReceiver receiver,
1112                 IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
1113             if ((flags & RECEIVER_NOT_EXPORTED) != 0 && broadcastPermission == null) {
1114                 String permission = obtainAndCheckReceiverPermission(obj);
1115                 // receivers that are not exported should also not be visible to instant apps
1116                 return obj.registerReceiver(receiver, filter, permission, scheduler);
1117             }
1118             flags &= Context.RECEIVER_VISIBLE_TO_INSTANT_APPS;
1119             return obj.registerReceiver(receiver, filter, broadcastPermission, scheduler, flags);
1120         }
1121 
1122         @SuppressWarnings("UnusedReturnValue")
startForegroundService(Context obj, Intent service)1123         static ComponentName startForegroundService(Context obj, Intent service) {
1124             return obj.startForegroundService(service);
1125         }
1126     }
1127 
1128     @RequiresApi(28)
1129     static class Api28Impl {
Api28Impl()1130         private Api28Impl() {
1131             // This class is not instantiable.
1132         }
1133 
getMainExecutor(Context obj)1134         static Executor getMainExecutor(Context obj) {
1135             return obj.getMainExecutor();
1136         }
1137     }
1138 
1139     @RequiresApi(30)
1140     static class Api30Impl {
Api30Impl()1141         private Api30Impl() {
1142             // This class is not instantiable.
1143         }
1144 
getAttributionTag(Context obj)1145         static String getAttributionTag(Context obj) {
1146             return obj.getAttributionTag();
1147         }
1148 
getDisplayOrDefault(Context obj)1149         static Display getDisplayOrDefault(Context obj) {
1150             try {
1151                 return obj.getDisplay();
1152             } catch (UnsupportedOperationException e) {
1153                 // Provide a fallback display if the context is not associated with any display.
1154                 Log.w(TAG, "The context:" + obj + " is not associated with any display. Return a "
1155                         + "fallback display instead.");
1156                 return obj.getSystemService(DisplayManager.class)
1157                         .getDisplay(Display.DEFAULT_DISPLAY);
1158             }
1159         }
1160 
createAttributionContext(@onNull Context context, @Nullable String attributionTag)1161         static @NonNull Context createAttributionContext(@NonNull Context context,
1162                 @Nullable String attributionTag) {
1163             return context.createAttributionContext(attributionTag);
1164         }
1165     }
1166 
1167     @RequiresApi(33)
1168     static class Api33Impl {
Api33Impl()1169         private Api33Impl() {
1170             // This class is not instantiable
1171         }
1172 
registerReceiver(Context obj, @Nullable BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags)1173         static Intent registerReceiver(Context obj, @Nullable BroadcastReceiver receiver,
1174                 IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
1175             return obj.registerReceiver(receiver, filter, broadcastPermission, scheduler, flags);
1176         }
1177     }
1178 }
1179