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