• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.car.settings.qc;
18 
19 import android.content.Context;
20 import android.graphics.Color;
21 import android.graphics.drawable.ColorDrawable;
22 import android.graphics.drawable.Drawable;
23 import android.graphics.drawable.Icon;
24 import android.graphics.drawable.LayerDrawable;
25 import android.telephony.SignalStrength;
26 import android.telephony.SubscriptionManager;
27 import android.telephony.TelephonyManager;
28 import android.text.TextUtils;
29 import android.util.Log;
30 import android.view.Gravity;
31 
32 import androidx.annotation.Nullable;
33 
34 import com.android.car.settings.R;
35 import com.android.car.settings.common.DrawableUtil;
36 import com.android.settingslib.Utils;
37 import com.android.settingslib.graph.SignalDrawable;
38 import com.android.settingslib.net.SignalStrengthUtil;
39 import com.android.settingslib.utils.ThreadUtils;
40 
41 import java.util.concurrent.Semaphore;
42 import java.util.concurrent.TimeUnit;
43 import java.util.concurrent.atomic.AtomicReference;
44 
45 /**
46  * Helper methods for Mobile network quick controls.
47  */
48 public class MobileNetworkQCUtils {
49     private static final String TAG = "MobileNetworkQCUtils";
50     // Timeout for acquiring a signal drawable (in ms)
51     private static final long SIGNAL_DRAWABLE_TIMEOUT = 1000L;
52     private static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
53 
MobileNetworkQCUtils()54     private MobileNetworkQCUtils() {
55     }
56 
57     /**
58      * Retrieve the network subtitle for the current quick control network state.
59      */
60     @Nullable
getMobileNetworkSummary(Context context, boolean dataEnabled)61     public static String getMobileNetworkSummary(Context context, boolean dataEnabled) {
62         if (!dataEnabled) {
63             return context.getString(R.string.mobile_network_state_off);
64         }
65         TelephonyManager manager = context.getSystemService(TelephonyManager.class);
66         if (manager == null) {
67             return null;
68         }
69         String subtitle = manager.getNetworkOperatorName();
70         if (TextUtils.isEmpty(subtitle)) {
71             return null;
72         }
73         return subtitle;
74     }
75 
76     /**
77      * Retrieve an icon representing the current network symbol.
78      */
getMobileNetworkSignalIcon(Context context)79     public static Icon getMobileNetworkSignalIcon(Context context) {
80         // Set default drawable in case the SignalDrawable cannot be loaded
81         Drawable drawable = context.getDrawable(R.drawable.ic_qc_mobile_data);
82         try {
83             Semaphore lock = new Semaphore(/* permits= */0);
84             AtomicReference<Drawable> shared = new AtomicReference<>();
85             ThreadUtils.postOnMainThread(() -> {
86                 shared.set(getSignalStrengthDrawable(context));
87                 lock.release();
88             });
89             boolean success = lock.tryAcquire(SIGNAL_DRAWABLE_TIMEOUT, TimeUnit.MILLISECONDS);
90             if (success) {
91                 drawable = shared.get();
92             } else {
93                 Log.d(TAG, "Timed out getting signal drawable");
94             }
95         } catch (InterruptedException e) {
96             Log.e(TAG, "Interrupted while obtaining signal drawable", e);
97         }
98 
99         return DrawableUtil.createIconFromDrawable(drawable);
100     }
101 
getSignalStrengthDrawable(Context context)102     private static Drawable getSignalStrengthDrawable(Context context) {
103         TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
104         SignalStrength strength = telephonyManager.getSignalStrength();
105         int level = (strength == null) ? 0 : strength.getLevel();
106         int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
107         if (SignalStrengthUtil.shouldInflateSignalStrength(context,
108                 SubscriptionManager.getDefaultDataSubscriptionId())) {
109             level += 1;
110             numLevels += 1;
111         }
112         return createSignalDrawable(context, level, numLevels);
113     }
114 
createSignalDrawable(Context context, int level, int numLevels)115     private static Drawable createSignalDrawable(Context context, int level, int numLevels) {
116         SignalDrawable signalDrawable = new SignalDrawable(context);
117         signalDrawable.setLevel(
118                 SignalDrawable.getState(level, numLevels, /* cutOut= */ false));
119 
120         Drawable[] layers = {EMPTY_DRAWABLE, signalDrawable};
121         int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
122 
123         LayerDrawable icons = new LayerDrawable(layers);
124         // Set the network type icon at the top left
125         icons.setLayerGravity(/* index= */ 0, Gravity.TOP | Gravity.LEFT);
126         // Set the signal strength icon at the bottom right
127         icons.setLayerGravity(/* index= */ 1, Gravity.BOTTOM | Gravity.RIGHT);
128         icons.setLayerSize(/* index= */ 1, iconSize, iconSize);
129         icons.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
130         return icons;
131     }
132 }
133