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.settings.network;
18 
19 import android.content.Context;
20 import android.telephony.SubscriptionManager;
21 import android.util.Log;
22 
23 import com.android.settings.network.SubscriptionUtil;
24 import com.android.settings.network.helper.SelectableSubscriptions;
25 import com.android.settings.network.helper.SubscriptionAnnotation;
26 import com.android.settings.network.helper.SubscriptionGrouping;
27 import com.android.settings.network.telephony.MobileNetworkUtils;
28 import com.android.settingslib.utils.ThreadUtils;
29 
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.Future;
33 import java.util.function.Consumer;
34 import java.util.stream.Collectors;
35 
36 /**
37  * This one keeps the information required by MobileNetworkSummaryController.
38  */
39 public class MobileNetworkSummaryStatus {
40     private static final String LOG_TAG = "MobileNetworkSummaryStatus";
41 
42     private Future<Map<Integer, CharSequence>> mUniqueNameMapping;
43     private Map<Integer, CharSequence> mUniqueNameMappingCache;
44 
45     private Future<Boolean> mIsEuiccConfiguable;
46     private Boolean mIsEuiccConfiguableCache;
47 
48     private Future<Boolean> mIsPsimDisableSupported;
49     private Boolean mIsPsimDisableSupportedCache;
50 
51     private List<SubscriptionAnnotation> mSubscriptionList;
52 
53     private boolean mDisableReEntranceUpdate;
54 
55     // Constructor
MobileNetworkSummaryStatus()56     public MobileNetworkSummaryStatus() {}
57 
58     /**
59      * Update the status
60      * @param context
61      * @param andThen Consumer which always performed by the end of #update()
62      *                and avoid from repeated queries.
63      */
update(Context context, Consumer<MobileNetworkSummaryStatus> andThen)64     public void update(Context context, Consumer<MobileNetworkSummaryStatus> andThen) {
65         if (mDisableReEntranceUpdate) {
66             Log.d(LOG_TAG, "network summary query ignored");
67             if (andThen != null) {
68                 andThen.accept(this);
69             }
70             return;
71         }
72         mDisableReEntranceUpdate = true;
73         Log.d(LOG_TAG, "network summary query");
74 
75         // Query Euicc in background
76         mIsEuiccConfiguable = (Future<Boolean>)
77                 ThreadUtils.postOnBackgroundThread(() -> isEuiccConfiguable(context));
78 
79         // Query display name in background
80         mUniqueNameMapping = (Future<Map<Integer, CharSequence>>)
81                 ThreadUtils.postOnBackgroundThread(() -> getUniqueNameForDisplay(context));
82 
83         // Query support status of pSIM disable feature
84         mIsPsimDisableSupported = (Future<Boolean>) ThreadUtils.postOnBackgroundThread(()
85                 -> isPhysicalSimDisableSupported(context));
86 
87         // Query subscription
88         mSubscriptionList = getSubscriptions(context);
89 
90         if (andThen != null) {
91             andThen.accept(this);
92         }
93         mDisableReEntranceUpdate = false;
94     }
95 
96     /**
97      * Get the subscription information
98      * @return a list of SubscriptionAnnotation
99      */
getSubscriptionList()100     public List<SubscriptionAnnotation> getSubscriptionList() {
101         return mSubscriptionList;
102     }
103 
104     /**
105      * Get unique display name for a specific subscription
106      * @param subscriptionId subscription ID
107      * @return display name for that subscription
108      */
getDisplayName(int subscriptionId)109     public CharSequence getDisplayName(int subscriptionId) {
110         if (mUniqueNameMapping != null) {
111             try {
112                 mUniqueNameMappingCache = mUniqueNameMapping.get();
113             } catch (Exception exception) {
114                 Log.w(LOG_TAG, "Fail to get display names", exception);
115             }
116             mUniqueNameMapping = null;
117         }
118         if (mUniqueNameMappingCache == null) {
119             return null;
120         }
121         return mUniqueNameMappingCache.get(subscriptionId);
122     }
123 
124     // Check if Euicc is currently available
isEuiccConfigSupport()125     public boolean isEuiccConfigSupport() {
126         if (mIsEuiccConfiguable != null) {
127             try {
128                 mIsEuiccConfiguableCache = mIsEuiccConfiguable.get();
129             } catch (Exception exception) {
130                 Log.w(LOG_TAG, "Fail to get euicc config status", exception);
131             }
132             mIsEuiccConfiguable = null;
133         }
134         return (mIsEuiccConfiguableCache == null) ?
135                 false : mIsEuiccConfiguableCache.booleanValue();
136     }
137 
138     // Check if disable physical SIM is supported
isPhysicalSimDisableSupport()139     public boolean isPhysicalSimDisableSupport() {
140         if (mIsPsimDisableSupported != null) {
141             try {
142                 mIsPsimDisableSupportedCache = mIsPsimDisableSupported.get();
143             } catch (Exception exception) {
144                 Log.w(LOG_TAG, "Fail to get pSIM disable support", exception);
145             }
146             mIsPsimDisableSupported = null;
147         }
148         return (mIsPsimDisableSupportedCache == null) ?
149                 false : mIsPsimDisableSupportedCache.booleanValue();
150     }
151 
getSubscriptions(Context context)152     private List<SubscriptionAnnotation> getSubscriptions(Context context) {
153         return (new SelectableSubscriptions(context, true))
154 
155                 // To maintain the consistency with SubscriptionUtil#getAvailableSubscriptions().
156                 .addFinisher(new SubscriptionGrouping())
157 
158                 .call()
159                 .stream()
160                 .filter(SubscriptionAnnotation::isDisplayAllowed)
161                 .collect(Collectors.toList());
162     }
163 
getUniqueNameForDisplay(Context context)164     private Map<Integer, CharSequence> getUniqueNameForDisplay(Context context) {
165         return SubscriptionUtil.getUniqueSubscriptionDisplayNames(context);
166     }
167 
isPhysicalSimDisableSupported(Context context)168     private boolean isPhysicalSimDisableSupported(Context context) {
169         SubscriptionManager subMgr = context.getSystemService(SubscriptionManager.class);
170         return SubscriptionUtil.showToggleForPhysicalSim(subMgr);
171     }
172 
isEuiccConfiguable(Context context)173     private boolean isEuiccConfiguable(Context context) {
174         return MobileNetworkUtils.showEuiccSettingsDetecting(context);
175     }
176 }
177