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 /** 44 * See {@link ClipDescription#isStyleText()}. 45 */ isStyleText(ClipDescription clipDescription)46 public static boolean isStyleText(ClipDescription clipDescription) { 47 return clipDescription.isStyledText(); 48 } 49 50 /** 51 * See {@link ClipDescription#getConfidenceScore()}. 52 */ getConfidenceScore( ClipDescription clipDescription, @NonNull String entityType)53 public static float getConfidenceScore( 54 ClipDescription clipDescription, @NonNull String entityType) { 55 return clipDescription.getConfidenceScore(entityType); 56 } 57 58 /** 59 * Return true if {@link ClipDescription#getClassificationStatus()} returns 60 * ClipDescription.CLASSIFICATION_COMPLETE. 61 */ isGetClassificationStatusIsComplete(ClipDescription clipDescription)62 public static boolean isGetClassificationStatusIsComplete(ClipDescription clipDescription) { 63 return clipDescription.getClassificationStatus() == ClipDescription.CLASSIFICATION_COMPLETE; 64 } 65 66 /** 67 * See {@link ClipData.Item#getTextLinks()}. 68 */ getTextLinks(ClipData.Item item)69 public static TextLinks getTextLinks(ClipData.Item item) { 70 return item.getTextLinks(); 71 } 72 hasBluetoothConnectPermission()73 public static boolean hasBluetoothConnectPermission() { 74 return ApiCompatibilityUtils.checkPermission(ContextUtils.getApplicationContext(), 75 Manifest.permission.BLUETOOTH_CONNECT, Process.myPid(), Process.myUid()) 76 == PackageManager.PERMISSION_GRANTED; 77 } 78 79 /** 80 * See {@link android.app.PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)} 81 */ setAutoEnterEnabled( PictureInPictureParams.Builder builder, boolean enabled)82 public static void setAutoEnterEnabled( 83 PictureInPictureParams.Builder builder, boolean enabled) { 84 builder.setAutoEnterEnabled(enabled); 85 } 86 87 /** 88 * See {@link android.view.textclassifier.TextSelection.Request. 89 * Builder#setIncludeTextClassification(boolean)} 90 */ setIncludeTextClassification( TextSelection.Request.Builder builder, boolean includeTextClassification)91 public static TextSelection.Request.Builder setIncludeTextClassification( 92 TextSelection.Request.Builder builder, boolean includeTextClassification) { 93 return builder.setIncludeTextClassification(includeTextClassification); 94 } 95 96 /** 97 * See {@link android.view.textclassifier.TextSelection#getTextClassification()} 98 */ getTextClassification(TextSelection textSelection)99 public static TextClassification getTextClassification(TextSelection textSelection) { 100 return textSelection.getTextClassification(); 101 } 102 103 /** 104 * See Context#createWindowContext. 105 */ createWindowContext( Context context, Display display, int type, Bundle options)106 public static Context createWindowContext( 107 Context context, Display display, int type, Bundle options) { 108 return context.createWindowContext(display, type, options); 109 } 110 111 /** 112 * See {@link PendingIntent#FLAG_MUTABLE}. 113 */ getPendingIntentMutableFlag()114 public static int getPendingIntentMutableFlag() { 115 return PendingIntent.FLAG_MUTABLE; 116 } 117 118 /** See {@link Service#startForegroung(int, Notification, int) }. */ startForeground( Service service, int id, Notification notification, int foregroundServiceType)119 public static void startForeground( 120 Service service, int id, Notification notification, int foregroundServiceType) { 121 try { 122 service.startForeground(id, notification, foregroundServiceType); 123 } catch (ForegroundServiceStartNotAllowedException e) { 124 Log.e(TAG, 125 "Cannot run service as foreground: " + e + " for notification channel " 126 + notification.getChannelId() + " notification id " + id); 127 } 128 } 129 } 130