1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.compat; 6 7 import android.Manifest; 8 import android.app.ForegroundServiceStartNotAllowedException; 9 import android.app.Notification; 10 import android.app.PendingIntent; 11 import android.app.PictureInPictureParams; 12 import android.app.Service; 13 import android.content.ClipData; 14 import android.content.ClipDescription; 15 import android.content.Context; 16 import android.content.pm.PackageManager; 17 import android.os.Build; 18 import android.os.Bundle; 19 import android.os.Process; 20 import android.view.Display; 21 import android.view.textclassifier.TextClassification; 22 import android.view.textclassifier.TextLinks; 23 import android.view.textclassifier.TextSelection; 24 25 import androidx.annotation.NonNull; 26 import androidx.annotation.RequiresApi; 27 28 import org.chromium.base.ApiCompatibilityUtils; 29 import org.chromium.base.ContextUtils; 30 import org.chromium.base.Log; 31 32 /** 33 * Utility class to use new APIs that were added in S (API level 31). These need to exist in a 34 * separate class so that Android framework can successfully verify classes without 35 * encountering the new APIs. 36 */ 37 @RequiresApi(Build.VERSION_CODES.S) 38 public final class ApiHelperForS { 39 private static final String TAG = "ApiHelperForS"; 40 ApiHelperForS()41 private ApiHelperForS() {} 42 43 /** See {@link ClipDescription#isStyleText()}. */ isStyleText(ClipDescription clipDescription)44 public static boolean isStyleText(ClipDescription clipDescription) { 45 return clipDescription.isStyledText(); 46 } 47 48 /** See {@link ClipDescription#getConfidenceScore()}. */ getConfidenceScore( ClipDescription clipDescription, @NonNull String entityType)49 public static float getConfidenceScore( 50 ClipDescription clipDescription, @NonNull String entityType) { 51 return clipDescription.getConfidenceScore(entityType); 52 } 53 54 /** 55 * Return true if {@link ClipDescription#getClassificationStatus()} returns 56 * ClipDescription.CLASSIFICATION_COMPLETE. 57 */ isGetClassificationStatusIsComplete(ClipDescription clipDescription)58 public static boolean isGetClassificationStatusIsComplete(ClipDescription clipDescription) { 59 return clipDescription.getClassificationStatus() == ClipDescription.CLASSIFICATION_COMPLETE; 60 } 61 62 /** See {@link ClipData.Item#getTextLinks()}. */ getTextLinks(ClipData.Item item)63 public static TextLinks getTextLinks(ClipData.Item item) { 64 return item.getTextLinks(); 65 } 66 hasBluetoothConnectPermission()67 public static boolean hasBluetoothConnectPermission() { 68 return ApiCompatibilityUtils.checkPermission( 69 ContextUtils.getApplicationContext(), 70 Manifest.permission.BLUETOOTH_CONNECT, 71 Process.myPid(), 72 Process.myUid()) 73 == PackageManager.PERMISSION_GRANTED; 74 } 75 76 /** See {@link android.app.PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)} */ setAutoEnterEnabled( PictureInPictureParams.Builder builder, boolean enabled)77 public static void setAutoEnterEnabled( 78 PictureInPictureParams.Builder builder, boolean enabled) { 79 builder.setAutoEnterEnabled(enabled); 80 } 81 82 /** 83 * See {@link android.view.textclassifier.TextSelection.Request. 84 * Builder#setIncludeTextClassification(boolean)} 85 */ setIncludeTextClassification( TextSelection.Request.Builder builder, boolean includeTextClassification)86 public static TextSelection.Request.Builder setIncludeTextClassification( 87 TextSelection.Request.Builder builder, boolean includeTextClassification) { 88 return builder.setIncludeTextClassification(includeTextClassification); 89 } 90 91 /** See {@link android.view.textclassifier.TextSelection#getTextClassification()} */ getTextClassification(TextSelection textSelection)92 public static TextClassification getTextClassification(TextSelection textSelection) { 93 return textSelection.getTextClassification(); 94 } 95 96 /** See Context#createWindowContext. */ createWindowContext( Context context, Display display, int type, Bundle options)97 public static Context createWindowContext( 98 Context context, Display display, int type, Bundle options) { 99 return context.createWindowContext(display, type, options); 100 } 101 102 /** See {@link PendingIntent#FLAG_MUTABLE}. */ getPendingIntentMutableFlag()103 public static int getPendingIntentMutableFlag() { 104 return PendingIntent.FLAG_MUTABLE; 105 } 106 107 /** See {@link Service#startForegroung(int, Notification, int) }. */ startForeground( Service service, int id, Notification notification, int foregroundServiceType)108 public static void startForeground( 109 Service service, int id, Notification notification, int foregroundServiceType) { 110 try { 111 service.startForeground(id, notification, foregroundServiceType); 112 } catch (ForegroundServiceStartNotAllowedException e) { 113 Log.e( 114 TAG, 115 "Cannot run service as foreground: " 116 + e 117 + " for notification channel " 118 + notification.getChannelId() 119 + " notification id " 120 + id); 121 } 122 } 123 } 124