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