1 /* 2 * Copyright (C) 2021 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.settings.emergency; 18 19 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 20 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; 21 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; 22 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.ResolveInfo; 28 import android.graphics.Bitmap; 29 import android.graphics.Canvas; 30 import android.graphics.drawable.BitmapDrawable; 31 import android.graphics.drawable.Drawable; 32 import android.os.Bundle; 33 import android.text.TextUtils; 34 import android.util.DisplayMetrics; 35 import android.util.Log; 36 import android.util.TypedValue; 37 import android.view.View; 38 import android.widget.Button; 39 40 import androidx.annotation.VisibleForTesting; 41 import androidx.preference.PreferenceScreen; 42 43 import com.android.settings.R; 44 import com.android.settings.Utils; 45 import com.android.settings.core.BasePreferenceController; 46 import com.android.settings.overlay.FeatureFactory; 47 import com.android.settingslib.widget.LayoutPreference; 48 49 import java.util.List; 50 51 /** 52 * Preference controller for More settings button 53 */ 54 public class MoreSettingsPreferenceController extends BasePreferenceController implements 55 View.OnClickListener { 56 57 private static final String EXTRA_KEY_ATTRIBUTION = "attribution"; 58 private static final String TAG = "MoreSettingsPrefCtrl"; 59 @VisibleForTesting 60 Intent mIntent; 61 private LayoutPreference mPreference; 62 MoreSettingsPreferenceController(Context context, String preferenceKey)63 public MoreSettingsPreferenceController(Context context, String preferenceKey) { 64 super(context, preferenceKey); 65 final String packageName = mContext.getResources().getString( 66 R.string.config_emergency_package_name); 67 68 if (TextUtils.isEmpty(packageName)) { 69 return; 70 } 71 mIntent = new Intent(Intent.ACTION_MAIN) 72 .setPackage(packageName); 73 74 final List<ResolveInfo> info = mContext.getPackageManager() 75 .queryIntentActivities(mIntent, MATCH_SYSTEM_ONLY); 76 77 if (info != null && !info.isEmpty()) { 78 mIntent.setClassName(packageName, info.get(0).activityInfo.name); 79 } else { 80 mIntent = null; 81 } 82 } 83 84 @Override displayPreference(PreferenceScreen screen)85 public void displayPreference(PreferenceScreen screen) { 86 super.displayPreference(screen); 87 mPreference = screen.findPreference(getPreferenceKey()); 88 final Button button = mPreference.findViewById(R.id.button); 89 final Drawable icon = getIcon(); 90 button.setText(getButtonText()); 91 if (icon != null) { 92 button.setCompoundDrawablesWithIntrinsicBounds( 93 /* left= */ icon, 94 /* top= */null, 95 /* right= */ null, 96 /* bottom= */ null); 97 button.setVisibility(View.VISIBLE); 98 } 99 100 button.setOnClickListener(this); 101 } 102 103 @Override getAvailabilityStatus()104 public int getAvailabilityStatus() { 105 if (mIntent == null) { 106 return UNSUPPORTED_ON_DEVICE; 107 } else { 108 return AVAILABLE; 109 } 110 } 111 112 @Override onClick(View v)113 public void onClick(View v) { 114 FeatureFactory.getFeatureFactory().getMetricsFeatureProvider() 115 .logClickedPreference(mPreference, getMetricsCategory()); 116 final Intent intent = new Intent(mIntent) 117 .addCategory(Intent.CATEGORY_LAUNCHER) 118 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 119 Bundle bundle = new Bundle(); 120 bundle.putString(EXTRA_KEY_ATTRIBUTION, mContext.getPackageName()); 121 mContext.startActivity(intent, bundle); 122 } 123 getIcon()124 private Drawable getIcon() { 125 final String packageName = mContext.getResources().getString( 126 R.string.config_emergency_package_name); 127 try { 128 final PackageManager pm = mContext.getPackageManager(); 129 final ApplicationInfo appInfo = pm.getApplicationInfo( 130 packageName, MATCH_DISABLED_COMPONENTS 131 | MATCH_DISABLED_UNTIL_USED_COMPONENTS); 132 return getScaledDrawable(mContext, Utils.getBadgedIcon(mContext, appInfo), 24, 24); 133 } catch (Exception e) { 134 Log.d(TAG, "Failed to get open app button icon", e); 135 return null; 136 } 137 } 138 getButtonText()139 private CharSequence getButtonText() { 140 final String packageName = mContext.getResources().getString( 141 R.string.config_emergency_package_name); 142 try { 143 final PackageManager pm = mContext.getPackageManager(); 144 final ApplicationInfo appInfo = pm.getApplicationInfo( 145 packageName, MATCH_DISABLED_COMPONENTS 146 | MATCH_DISABLED_UNTIL_USED_COMPONENTS); 147 return mContext.getString(R.string.open_app_button, appInfo.loadLabel(pm)); 148 } catch (Exception e) { 149 Log.d(TAG, "Failed to get open app button text, falling back."); 150 return ""; 151 } 152 } 153 getScaledDrawable(Context context, Drawable icon, int width, int height)154 private static Drawable getScaledDrawable(Context context, Drawable icon, int width, 155 int height) { 156 DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 157 int widthInDp = 158 (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, displayMetrics); 159 int heightInDp = 160 (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, 161 displayMetrics); 162 163 return new BitmapDrawable(context.getResources(), 164 convertToBitmap(icon, widthInDp, heightInDp)); 165 } 166 convertToBitmap(Drawable icon, int width, int height)167 private static Bitmap convertToBitmap(Drawable icon, int width, int height) { 168 if (icon == null) { 169 return null; 170 } 171 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 172 Canvas canvas = new Canvas(bitmap); 173 icon.setBounds(0, 0, width, height); 174 icon.draw(canvas); 175 return bitmap; 176 } 177 } 178