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