• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Configuration;
23 import android.content.res.Resources;
24 import android.graphics.Paint;
25 import android.graphics.drawable.ShapeDrawable;
26 import android.graphics.drawable.shapes.OvalShape;
27 import android.os.Bundle;
28 import android.telephony.SubscriptionInfo;
29 import android.telephony.SubscriptionManager;
30 import android.telephony.TelephonyManager;
31 import android.text.TextUtils;
32 import android.util.Log;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.view.ViewGroup;
36 import android.widget.ArrayAdapter;
37 import android.widget.EditText;
38 import android.widget.ImageView;
39 import android.widget.Spinner;
40 import android.widget.TextView;
41 
42 import androidx.annotation.NonNull;
43 import androidx.annotation.Nullable;
44 import androidx.annotation.VisibleForTesting;
45 import androidx.appcompat.app.AlertDialog;
46 
47 import com.android.settings.R;
48 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
49 import com.android.settings.network.SubscriptionUtil;
50 import com.android.settingslib.DeviceInfoUtils;
51 
52 import com.google.common.collect.ImmutableMap;
53 
54 import java.util.List;
55 import java.util.Map;
56 
57 /**
58  * A dialog allowing the display name of a mobile network subscription to be changed
59  */
60 public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragment {
61 
62     public static final String TAG = "RenameMobileNetwork";
63 
64     private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
65 
66     private TelephonyManager mTelephonyManager;
67     private SubscriptionManager mSubscriptionManager;
68     private int mSubId;
69     private EditText mNameView;
70     private Spinner mColorSpinner;
71     private Color[] mColors;
72     private Map<Integer, Integer> mLightDarkMap;
73 
newInstance(int subscriptionId)74     public static RenameMobileNetworkDialogFragment newInstance(int subscriptionId) {
75         final Bundle args = new Bundle(1);
76         args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
77         final RenameMobileNetworkDialogFragment fragment = new RenameMobileNetworkDialogFragment();
78         fragment.setArguments(args);
79         return fragment;
80     }
81 
82     @VisibleForTesting
getTelephonyManager(Context context)83     protected TelephonyManager getTelephonyManager(Context context) {
84         return context.getSystemService(TelephonyManager.class);
85     }
86 
87     @VisibleForTesting
getSubscriptionManager(Context context)88     protected SubscriptionManager getSubscriptionManager(Context context) {
89         return context.getSystemService(SubscriptionManager.class);
90     }
91 
92     @VisibleForTesting
getNameView()93     protected EditText getNameView() {
94         return mNameView;
95     }
96 
97     @VisibleForTesting
getColorSpinnerView()98     protected Spinner getColorSpinnerView() {
99         return mColorSpinner;
100     }
101 
102     @Override
onAttach(Context context)103     public void onAttach(Context context) {
104         super.onAttach(context);
105         mTelephonyManager = getTelephonyManager(context);
106         mSubscriptionManager = getSubscriptionManager(context);
107         mSubId = getArguments().getInt(KEY_SUBSCRIPTION_ID);
108         Resources res = context.getResources();
109         mLightDarkMap = ImmutableMap.<Integer, Integer>builder()
110                 .put(res.getInteger(R.color.SIM_color_cyan),
111                         res.getInteger(R.color.SIM_dark_mode_color_cyan))
112                 .put(res.getInteger(R.color.SIM_color_blue800),
113                         res.getInteger(R.color.SIM_dark_mode_color_blue))
114                 .put(res.getInteger(R.color.SIM_color_green800),
115                         res.getInteger(R.color.SIM_dark_mode_color_green))
116                 .put(res.getInteger(R.color.SIM_color_purple800),
117                         res.getInteger(R.color.SIM_dark_mode_color_purple))
118                 .put(res.getInteger(R.color.SIM_color_pink800),
119                         res.getInteger(R.color.SIM_dark_mode_color_pink))
120                 .put(res.getInteger(R.color.SIM_color_orange),
121                         res.getInteger(R.color.SIM_dark_mode_color_orange))
122                 .build();
123     }
124 
125     @NonNull
126     @Override
onCreateDialog(@ullable Bundle savedInstanceState)127     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
128         mColors = getColors();
129 
130         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
131         final LayoutInflater layoutInflater = builder.getContext().getSystemService(
132                 LayoutInflater.class);
133         final View view = layoutInflater.inflate(R.layout.dialog_mobile_network_rename, null);
134         populateView(view);
135         builder.setTitle(R.string.mobile_network_sim_name)
136                 .setView(view)
137                 .setPositiveButton(R.string.mobile_network_sim_name_rename, (dialog, which) -> {
138                     mSubscriptionManager.setDisplayName(mNameView.getText().toString(), mSubId,
139                             SubscriptionManager.NAME_SOURCE_USER_INPUT);
140                     final Color color = (mColorSpinner == null) ? mColors[0]
141                             : mColors[mColorSpinner.getSelectedItemPosition()];
142                     mSubscriptionManager.setIconTint(color.getColor(), mSubId);
143                 })
144                 .setNegativeButton(android.R.string.cancel, null);
145         return builder.create();
146     }
147 
148     @VisibleForTesting
populateView(View view)149     protected void populateView(View view) {
150         mNameView = view.findViewById(R.id.name_edittext);
151         SubscriptionInfo info = null;
152         final List<SubscriptionInfo> infoList = mSubscriptionManager
153                 .getAvailableSubscriptionInfoList();
154         if (infoList != null) {
155             for (SubscriptionInfo subInfo : infoList) {
156                 if (subInfo.getSubscriptionId() == mSubId) {
157                     info = subInfo;
158                     break;
159                 }
160             }
161         }
162         if (info == null) {
163             Log.w(TAG, "got null SubscriptionInfo for mSubId:" + mSubId);
164             return;
165         }
166         final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
167                 info, getContext());
168         mNameView.setText(displayName);
169         if (!TextUtils.isEmpty(displayName)) {
170             mNameView.setSelection(displayName.length());
171         }
172 
173         mColorSpinner = view.findViewById(R.id.color_spinner);
174         final ColorAdapter adapter = new ColorAdapter(getContext(),
175                 R.layout.dialog_mobile_network_color_picker_item, mColors);
176         mColorSpinner.setAdapter(adapter);
177         mColorSpinner.setSelection(getSimColorIndex(info.getIconTint()));
178 
179         final TextView operatorName = view.findViewById(R.id.operator_name_value);
180         mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
181         operatorName.setText(info.getCarrierName());
182 
183         final TextView phoneTitle = view.findViewById(R.id.number_label);
184         phoneTitle.setVisibility(info.isOpportunistic() ? View.GONE : View.VISIBLE);
185 
186         final TextView phoneNumber = view.findViewById(R.id.number_value);
187         final String pn = DeviceInfoUtils.getBidiFormattedPhoneNumber(getContext(), info);
188         if (!TextUtils.isEmpty(pn)) {
189             phoneNumber.setText(pn);
190         }
191     }
192 
193     @Override
getMetricsCategory()194     public int getMetricsCategory() {
195         return SettingsEnums.MOBILE_NETWORK_RENAME_DIALOG;
196     }
197 
198     private class ColorAdapter extends ArrayAdapter<Color> {
199 
200         private Context mContext;
201         private int mItemResId;
202 
ColorAdapter(Context context, int resource, Color[] colors)203         public ColorAdapter(Context context, int resource, Color[] colors) {
204             super(context, resource, colors);
205             mContext = context;
206             mItemResId = resource;
207         }
208 
209         @Override
getView(int position, View convertView, ViewGroup parent)210         public View getView(int position, View convertView, ViewGroup parent) {
211             final LayoutInflater inflater = (LayoutInflater)
212                     mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
213 
214             if (convertView == null) {
215                 convertView = inflater.inflate(mItemResId, null);
216             }
217             boolean isDarkMode = false;
218             if ((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
219                     == Configuration.UI_MODE_NIGHT_YES) {
220                 isDarkMode = true;
221             }
222             ((ImageView) convertView.findViewById(R.id.color_icon))
223                     .setImageDrawable(getItem(position).getDrawable(isDarkMode));
224             ((TextView) convertView.findViewById(R.id.color_label))
225                     .setText(getItem(position).getLabel());
226 
227             return convertView;
228         }
229 
230         @Override
getDropDownView(int position, View convertView, ViewGroup parent)231         public View getDropDownView(int position, View convertView, ViewGroup parent) {
232             return getView(position, convertView, parent);
233         }
234     }
235 
getColors()236     private Color[] getColors() {
237         final Resources res = getContext().getResources();
238         final int[] colorInts = res.getIntArray(R.array.sim_color_light);
239         final String[] colorStrings = res.getStringArray(R.array.color_picker);
240         final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size);
241         final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width);
242         final Color[] colors = new Color[colorInts.length];
243         for (int i = 0; i < colors.length; i++) {
244             colors[i] = new Color(colorStrings[i], colorInts[i], iconSize, strokeWidth);
245         }
246         return colors;
247     }
248 
249     private class Color {
250 
251         private String mLabel;
252         private int mColor;
253         private ShapeDrawable mDrawable;
254 
Color(String label, int color, int iconSize, int strokeWidth)255         private Color(String label, int color, int iconSize, int strokeWidth) {
256             mLabel = label;
257             mColor = color;
258             mDrawable = new ShapeDrawable(new OvalShape());
259             mDrawable.setIntrinsicHeight(iconSize);
260             mDrawable.setIntrinsicWidth(iconSize);
261             mDrawable.getPaint().setStrokeWidth(strokeWidth);
262             mDrawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
263             mDrawable.getPaint().setColor(color);
264         }
265 
getLabel()266         private String getLabel() {
267             return mLabel;
268         }
269 
getColor()270         private int getColor() {
271             return mColor;
272         }
273 
getDrawable(boolean isDarkMode)274         private ShapeDrawable getDrawable(boolean isDarkMode) {
275             if (isDarkMode) {
276                 mDrawable.getPaint().setColor(getDarkColor(mColor));
277             }
278             return mDrawable;
279         }
280     }
281 
getDarkColor(int lightColor)282     private int getDarkColor(int lightColor) {
283         return mLightDarkMap.getOrDefault(lightColor, lightColor);
284     }
285 
286     /*
287     * Get the color index from previous color that defined in Android OS
288     * (frameworks/base/core/res/res/values/arrays.xml). If can't find the color, continue to look
289     * for it in the new color plattee. If not, give it the first index.
290     */
291 
getSimColorIndex(int color)292     private int getSimColorIndex(int color) {
293         int index = -1;
294         final int[] previousSimColorInts =
295                 getContext().getResources().getIntArray(com.android.internal.R.array.sim_colors);
296         for (int i = 0; i < previousSimColorInts.length; i++) {
297             if (previousSimColorInts[i] == color) {
298                 index = i;
299             }
300         }
301 
302         if (index == -1) {
303             for (int i = 0; i < mColors.length; i++) {
304                 if (mColors[i].getColor() == color) {
305                     index = i;
306                 }
307             }
308         }
309 
310         return index == -1 ? 0 : index;
311     }
312 }
313