1 /* 2 * Copyright (C) 2024 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 com.android.car.settings.privacy; 18 19 import static com.android.car.ui.preference.CarUiTwoActionTextPreference.SECONDARY_ACTION_STYLE_BORDERLESS; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.PackageInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.PackageManager.NameNotFoundException; 27 import android.content.pm.PackageManager.PackageInfoFlags; 28 import android.net.Uri; 29 import android.os.Bundle; 30 import android.os.UserHandle; 31 import android.util.IconDrawableFactory; 32 33 import androidx.annotation.Nullable; 34 35 import com.android.car.settings.R; 36 import com.android.car.settings.common.Logger; 37 import com.android.car.ui.preference.CarUiPreference; 38 import com.android.car.ui.preference.CarUiTwoActionTextPreference; 39 40 /** Utilities related to preferences with required and infotainment apps. */ 41 public final class RequiredInfotainmentAppsUtils { 42 private static final Logger LOG = new Logger(RequiredInfotainmentAppsUtils.class); 43 private static final String PRIVACY_POLICY_KEY = "privacy_policy"; 44 RequiredInfotainmentAppsUtils()45 private RequiredInfotainmentAppsUtils() {} 46 47 /** 48 * Creates a {@link CarUiTwoActionTextPreference} for a required app with its privacy policy and 49 * a link to its permission settings. 50 */ 51 @Nullable createRequiredAppPreference( Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, String permissionGroup, boolean showSummary)52 public static CarUiTwoActionTextPreference createRequiredAppPreference( 53 Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, 54 String permissionGroup, boolean showSummary) { 55 ApplicationInfo appInfo = getApplicationInfo(packageManager, pkgName, userHandle); 56 if (appInfo == null || !appInfo.enabled) { 57 return null; 58 } 59 60 CarUiTwoActionTextPreference pref = 61 new CarUiTwoActionTextPreference(context, SECONDARY_ACTION_STYLE_BORDERLESS); 62 setAppPreference(context, packageManager, pkgName, userHandle, permissionGroup, showSummary, 63 pref, appInfo); 64 65 pref.setSecondaryActionText(R.string.required_apps_privacy_policy_button_text); 66 67 Bundle bundle = appInfo.metaData; 68 if (bundle == null) { 69 LOG.e(pkgName + "doesn't provide meta data in manifest"); 70 return pref; 71 } 72 73 CharSequence privacyPolicyLink = bundle.getCharSequence(PRIVACY_POLICY_KEY); 74 if (privacyPolicyLink == null) { 75 LOG.e(pkgName + " doesn't provide privacy policy"); 76 return pref; 77 } 78 79 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyLink.toString())); 80 pref.setOnSecondaryActionClickListener( 81 () -> { 82 context.startActivity(intent); 83 }); 84 return pref; 85 } 86 87 /** 88 * Creates a {@link CarUiPreference} for an infotainment app. 89 */ 90 @Nullable createInfotainmentAppPreference( Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, String permissionGroup, boolean showSummary)91 public static CarUiPreference createInfotainmentAppPreference( 92 Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, 93 String permissionGroup, boolean showSummary) { 94 ApplicationInfo appInfo = getApplicationInfo(packageManager, pkgName, userHandle); 95 if (appInfo == null || !appInfo.enabled) { 96 return null; 97 } 98 99 CarUiPreference pref = new CarUiPreference(context); 100 setAppPreference(context, packageManager, pkgName, userHandle, permissionGroup, showSummary, 101 pref, appInfo); 102 return pref; 103 } 104 getApplicationInfo( PackageManager packageManager, String pkgName, UserHandle userHandle)105 private static ApplicationInfo getApplicationInfo( 106 PackageManager packageManager, String pkgName, UserHandle userHandle) { 107 ApplicationInfo appInfo = null; 108 try { 109 appInfo = packageManager.getApplicationInfoAsUser( 110 pkgName, PackageManager.GET_META_DATA, userHandle.getIdentifier()); 111 } catch (NameNotFoundException ex) { 112 LOG.e("Failed to get application info for " + pkgName); 113 } 114 return appInfo; 115 } 116 setAppPreference( Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, String permissionGroup, boolean showSummary, CarUiPreference pref, ApplicationInfo appInfo)117 private static void setAppPreference( 118 Context context, PackageManager packageManager, String pkgName, UserHandle userHandle, 119 String permissionGroup, boolean showSummary, CarUiPreference pref, 120 ApplicationInfo appInfo) { 121 IconDrawableFactory drawableFactory = IconDrawableFactory.newInstance(context); 122 pref.setIcon(drawableFactory.getBadgedIcon(appInfo, userHandle.getIdentifier())); 123 124 CharSequence appLabel = packageManager.getApplicationLabel(appInfo); 125 CharSequence badgedAppLabel = packageManager.getUserBadgedLabel(appLabel, userHandle); 126 pref.setTitle(badgedAppLabel); 127 128 pref.setOnPreferenceClickListener( 129 preference -> { 130 Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION); 131 intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroup); 132 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName); 133 intent.putExtra(Intent.EXTRA_USER, userHandle); 134 context.startActivity(intent); 135 return true; 136 }); 137 138 if (showSummary) { 139 PackageInfo packageInfo; 140 try { 141 packageInfo = packageManager.getPackageInfo(pkgName, 142 PackageInfoFlags.of(PackageManager.GET_PERMISSIONS)); 143 } catch (NameNotFoundException ex) { 144 LOG.e("Failed to get package info for " + pkgName); 145 return; 146 } 147 int permGroupGrantStatus = PermissionUtils.getPermissionGroupGrantStatus( 148 context, packageInfo, permissionGroup, userHandle); 149 pref.setSummary(permGroupGrantStatus); 150 } 151 } 152 } 153