1 /* 2 * Copyright (C) 2019 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.network.telephony; 18 19 import android.app.Dialog; 20 import android.app.settings.SettingsEnums; 21 import android.content.Context; 22 import android.content.res.Resources; 23 import android.graphics.Paint; 24 import android.graphics.drawable.ShapeDrawable; 25 import android.graphics.drawable.shapes.OvalShape; 26 import android.os.Bundle; 27 import android.telephony.ServiceState; 28 import android.telephony.SubscriptionInfo; 29 import android.telephony.SubscriptionManager; 30 import android.telephony.TelephonyManager; 31 import android.text.BidiFormatter; 32 import android.text.TextDirectionHeuristics; 33 import android.text.TextUtils; 34 import android.util.Log; 35 import android.view.LayoutInflater; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.AdapterView; 39 import android.widget.ArrayAdapter; 40 import android.widget.EditText; 41 import android.widget.ImageView; 42 import android.widget.Spinner; 43 import android.widget.TextView; 44 45 import com.android.settings.R; 46 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 47 import com.android.settingslib.DeviceInfoUtils; 48 49 import androidx.annotation.NonNull; 50 import androidx.annotation.Nullable; 51 import androidx.annotation.VisibleForTesting; 52 import androidx.appcompat.app.AlertDialog; 53 54 /** 55 * A dialog allowing the display name of a mobile network subscription to be changed 56 */ 57 public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragment { 58 59 public static final String TAG = "RenameMobileNetwork"; 60 61 private static final String KEY_SUBSCRIPTION_ID = "subscription_id"; 62 63 private TelephonyManager mTelephonyManager; 64 private SubscriptionManager mSubscriptionManager; 65 private int mSubId; 66 private EditText mNameView; 67 private Spinner mColorSpinner; 68 private Color[] mColors; 69 newInstance(int subscriptionId)70 public static RenameMobileNetworkDialogFragment newInstance(int subscriptionId) { 71 final Bundle args = new Bundle(1); 72 args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId); 73 final RenameMobileNetworkDialogFragment fragment = new RenameMobileNetworkDialogFragment(); 74 fragment.setArguments(args); 75 return fragment; 76 } 77 78 @VisibleForTesting getTelephonyManager(Context context)79 protected TelephonyManager getTelephonyManager(Context context) { 80 return context.getSystemService(TelephonyManager.class); 81 } 82 83 @VisibleForTesting getSubscriptionManager(Context context)84 protected SubscriptionManager getSubscriptionManager(Context context) { 85 return context.getSystemService(SubscriptionManager.class); 86 } 87 88 @VisibleForTesting getNameView()89 protected EditText getNameView() { 90 return mNameView; 91 } 92 93 @VisibleForTesting getColorSpinnerView()94 protected Spinner getColorSpinnerView() { 95 return mColorSpinner; 96 } 97 98 @Override onAttach(Context context)99 public void onAttach(Context context) { 100 super.onAttach(context); 101 mTelephonyManager = getTelephonyManager(context); 102 mSubscriptionManager = getSubscriptionManager(context); 103 mSubId = getArguments().getInt(KEY_SUBSCRIPTION_ID); 104 } 105 106 @NonNull 107 @Override onCreateDialog(@ullable Bundle savedInstanceState)108 public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { 109 mColors = getColors(); 110 111 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 112 final LayoutInflater layoutInflater = builder.getContext().getSystemService( 113 LayoutInflater.class); 114 final View view = layoutInflater.inflate(R.layout.dialog_mobile_network_rename, null); 115 populateView(view); 116 builder.setTitle(R.string.mobile_network_sim_name) 117 .setView(view) 118 .setPositiveButton(R.string.mobile_network_sim_name_rename, (dialog, which) -> { 119 mSubscriptionManager.setDisplayName(mNameView.getText().toString(), mSubId, 120 SubscriptionManager.NAME_SOURCE_USER_INPUT); 121 mSubscriptionManager.setIconTint( 122 mColors[mColorSpinner.getSelectedItemPosition()].getColor(), 123 mSubId); 124 }) 125 .setNegativeButton(android.R.string.cancel, null); 126 return builder.create(); 127 } 128 129 @VisibleForTesting populateView(View view)130 protected void populateView(View view) { 131 mNameView = view.findViewById(R.id.name_edittext); 132 final SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId); 133 if (info == null) { 134 Log.w(TAG, "got null SubscriptionInfo for mSubId:" + mSubId); 135 return; 136 } 137 final CharSequence displayName = info.getDisplayName(); 138 mNameView.setText(displayName); 139 if (!TextUtils.isEmpty(displayName)) { 140 mNameView.setSelection(displayName.length()); 141 } 142 143 mColorSpinner = view.findViewById(R.id.color_spinner); 144 final ColorAdapter adapter = new ColorAdapter(getContext(), 145 R.layout.dialog_mobile_network_color_picker_item, mColors); 146 mColorSpinner.setAdapter(adapter); 147 for (int i = 0; i < mColors.length; i++) { 148 if (mColors[i].getColor() == info.getIconTint()) { 149 mColorSpinner.setSelection(i); 150 break; 151 } 152 } 153 154 final TextView operatorName = view.findViewById(R.id.operator_name_value); 155 final ServiceState serviceState = mTelephonyManager.getServiceStateForSubscriber(mSubId); 156 operatorName.setText(serviceState.getOperatorAlphaLong()); 157 158 final TextView phoneTitle = view.findViewById(R.id.number_label); 159 phoneTitle.setVisibility(info.isOpportunistic() ? View.GONE : View.VISIBLE); 160 161 final TextView phoneNumber = view.findViewById(R.id.number_value); 162 final String formattedNumber = DeviceInfoUtils.getFormattedPhoneNumber(getContext(), info); 163 phoneNumber.setText(BidiFormatter.getInstance().unicodeWrap(formattedNumber, 164 TextDirectionHeuristics.LTR)); 165 } 166 167 @Override getMetricsCategory()168 public int getMetricsCategory() { 169 return SettingsEnums.MOBILE_NETWORK_RENAME_DIALOG; 170 } 171 172 private class ColorAdapter extends ArrayAdapter<Color> { 173 174 private Context mContext; 175 private int mItemResId; 176 ColorAdapter(Context context, int resource, Color[] colors)177 public ColorAdapter(Context context, int resource, Color[] colors) { 178 super(context, resource, colors); 179 mContext = context; 180 mItemResId = resource; 181 } 182 183 @Override getView(int position, View convertView, ViewGroup parent)184 public View getView(int position, View convertView, ViewGroup parent) { 185 final LayoutInflater inflater = (LayoutInflater) 186 mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 187 188 if (convertView == null) { 189 convertView = inflater.inflate(mItemResId, null); 190 } 191 ((ImageView) convertView.findViewById(R.id.color_icon)) 192 .setImageDrawable(getItem(position).getDrawable()); 193 ((TextView) convertView.findViewById(R.id.color_label)) 194 .setText(getItem(position).getLabel()); 195 196 return convertView; 197 } 198 199 @Override getDropDownView(int position, View convertView, ViewGroup parent)200 public View getDropDownView(int position, View convertView, ViewGroup parent) { 201 return getView(position, convertView, parent); 202 } 203 } 204 getColors()205 private Color[] getColors() { 206 final Resources res = getContext().getResources(); 207 final int[] colorInts = res.getIntArray(com.android.internal.R.array.sim_colors); 208 final String[] colorStrings = res.getStringArray(R.array.color_picker); 209 final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size); 210 final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width); 211 final Color[] colors = new Color[colorInts.length]; 212 for (int i = 0; i < colors.length; i++) { 213 colors[i] = new Color(colorStrings[i], colorInts[i], iconSize, strokeWidth); 214 } 215 return colors; 216 } 217 218 private static class Color { 219 220 private String mLabel; 221 private int mColor; 222 private ShapeDrawable mDrawable; 223 Color(String label, int color, int iconSize, int strokeWidth)224 private Color(String label, int color, int iconSize, int strokeWidth) { 225 mLabel = label; 226 mColor = color; 227 mDrawable = new ShapeDrawable(new OvalShape()); 228 mDrawable.setIntrinsicHeight(iconSize); 229 mDrawable.setIntrinsicWidth(iconSize); 230 mDrawable.getPaint().setStrokeWidth(strokeWidth); 231 mDrawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE); 232 mDrawable.getPaint().setColor(color); 233 } 234 getLabel()235 private String getLabel() { 236 return mLabel; 237 } 238 getColor()239 private int getColor() { 240 return mColor; 241 } 242 getDrawable()243 private ShapeDrawable getDrawable() { 244 return mDrawable; 245 } 246 } 247 } 248