1 package com.android.healthconnect.controller.utils 2 3 import android.content.ActivityNotFoundException 4 import android.content.Context 5 import android.content.Intent 6 import android.content.pm.PackageManager 7 import android.net.Uri 8 import android.os.UserManager 9 import android.text.TextUtils 10 import android.util.Log 11 import androidx.fragment.app.FragmentActivity 12 import com.android.healthconnect.controller.R 13 import com.android.healthconnect.controller.permissions.shared.HelpAndFeedbackFragment.Companion.FEEDBACK_INTENT_RESULT_CODE 14 import com.android.healthconnect.controller.permissions.shared.HelpAndFeedbackFragment.Companion.USER_INITIATED_FEEDBACK_BUCKET_ID 15 import com.android.settingslib.HelpUtils 16 import dagger.Module 17 import dagger.Provides 18 import dagger.hilt.EntryPoint 19 import dagger.hilt.InstallIn 20 import dagger.hilt.components.SingletonComponent 21 import javax.inject.Inject 22 23 interface DeviceInfoUtils { 24 isHealthConnectAvailablenull25 fun isHealthConnectAvailable(context: Context): Boolean 26 27 fun isSendFeedbackAvailable(context: Context): Boolean 28 29 fun isPlayStoreAvailable(context: Context): Boolean 30 31 fun openHCGetStartedLink(activity: FragmentActivity) 32 33 fun openSendFeedbackActivity(activity: FragmentActivity) 34 35 fun isIntentHandlerAvailable(context: Context, intent: Intent): Boolean 36 } 37 38 class DeviceInfoUtilsImpl @Inject constructor() : DeviceInfoUtils { 39 40 companion object { 41 private val TAG = "DeviceInfoUtils" 42 } 43 44 override fun isSendFeedbackAvailable(context: Context): Boolean { 45 return isIntentHandlerAvailable(context, Intent(Intent.ACTION_BUG_REPORT)) 46 } 47 48 override fun isPlayStoreAvailable(context: Context): Boolean { 49 val playStorePackageName = context.resources?.getString(R.string.playstore_collection_url) 50 val vendingPackageName = context.resources?.getString(R.string.playstore_package_name) 51 if (TextUtils.isEmpty(playStorePackageName) || playStorePackageName == null) { 52 // Package name not configured. Return. 53 return false 54 } 55 return isIntentHandlerAvailable( 56 context, 57 Intent(Intent.ACTION_VIEW).apply { 58 data = Uri.parse(playStorePackageName) 59 setPackage(vendingPackageName) 60 }) 61 } 62 63 override fun openHCGetStartedLink(activity: FragmentActivity) { 64 val helpUrlString = activity.getString(R.string.hc_get_started_link) 65 val fullUri = HelpUtils.uriWithAddedParameters(activity, Uri.parse(helpUrlString)) 66 val intent = 67 Intent(Intent.ACTION_VIEW, fullUri).apply { 68 flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 69 } 70 try { 71 activity.startActivity(intent) 72 } catch (e: ActivityNotFoundException) { 73 Log.w(TAG, "Unable to open help center URL.", e) 74 } 75 } 76 77 override fun openSendFeedbackActivity(activity: FragmentActivity) { 78 val intent = Intent(Intent.ACTION_BUG_REPORT) 79 intent.putExtra("category_tag", USER_INITIATED_FEEDBACK_BUCKET_ID) 80 activity.startActivityForResult(intent, FEEDBACK_INTENT_RESULT_CODE) 81 } 82 83 override fun isIntentHandlerAvailable(context: Context, intent: Intent): Boolean { 84 val packageManager = context.packageManager 85 if (intent.resolveActivity(packageManager) != null) { 86 return true 87 } 88 return false 89 } 90 91 override fun isHealthConnectAvailable(context: Context): Boolean { 92 return isHardwareSupported(context) && !isProfile(context) 93 } 94 95 private fun isHardwareSupported(context: Context): Boolean { 96 val pm: PackageManager = context.packageManager 97 return (!pm.hasSystemFeature(PackageManager.FEATURE_EMBEDDED) && 98 !pm.hasSystemFeature(PackageManager.FEATURE_WATCH) && 99 !pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK) && 100 !pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) 101 } 102 103 private fun isProfile(context: Context): Boolean { 104 return (context.getSystemService(Context.USER_SERVICE) as UserManager).isProfile 105 } 106 } 107 108 @EntryPoint 109 @InstallIn(SingletonComponent::class) 110 interface DeviceInfoUtilsEntryPoint { deviceInfoUtilsnull111 fun deviceInfoUtils(): DeviceInfoUtils 112 } 113 114 @Module 115 @InstallIn(SingletonComponent::class) 116 class DeviceInfoUtilsModule { 117 @Provides 118 fun providesDeviceInfoUtils(): DeviceInfoUtils { 119 return DeviceInfoUtilsImpl() 120 } 121 } 122