• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 static androidx.lifecycle.Lifecycle.Event;
20 
21 import android.content.Context;
22 import android.os.UserManager;
23 import android.telephony.ServiceState;
24 import android.telephony.SubscriptionManager;
25 import android.telephony.TelephonyManager;
26 import android.util.Log;
27 import android.view.View;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.lifecycle.LifecycleObserver;
31 import androidx.lifecycle.LifecycleOwner;
32 import androidx.lifecycle.OnLifecycleEvent;
33 import androidx.preference.Preference;
34 import androidx.preference.PreferenceScreen;
35 
36 import com.android.settings.R;
37 import com.android.settingslib.RestrictedPreference;
38 import com.android.settingslib.Utils;
39 import com.android.settingslib.core.AbstractPreferenceController;
40 import com.android.settingslib.core.lifecycle.Lifecycle;
41 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
42 
43 import java.util.List;
44 
45 public class NetworkProviderCallsSmsController extends AbstractPreferenceController implements
46         LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback,
47         DefaultSubscriptionReceiver.DefaultSubscriptionListener {
48 
49     private static final String TAG = "NetworkProviderCallsSmsController";
50     private static final String KEY = "calls_and_sms";
51     private static final String RTL_MARK = "\u200F";
52 
53     private UserManager mUserManager;
54     private TelephonyManager mTelephonyManager;
55     private RestrictedPreference mPreference;
56     private boolean mIsRtlMode;
57     private LifecycleOwner mLifecycleOwner;
58     private MobileNetworkRepository mMobileNetworkRepository;
59     private List<SubscriptionInfoEntity> mSubInfoEntityList;
60     private int mDefaultVoiceSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
61     private int mDefaultSmsSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
62     private DefaultSubscriptionReceiver mDataSubscriptionChangedReceiver;
63 
64     /**
65      * The summary text and click behavior of the "Calls & SMS" item on the
66      * Network & internet page.
67      */
NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle, LifecycleOwner lifecycleOwner)68     public NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle,
69             LifecycleOwner lifecycleOwner) {
70         super(context);
71 
72         mUserManager = context.getSystemService(UserManager.class);
73         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
74         mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
75                 == View.LAYOUT_DIRECTION_RTL;
76         mLifecycleOwner = lifecycleOwner;
77         mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
78         mDataSubscriptionChangedReceiver = new DefaultSubscriptionReceiver(context, this);
79         if (lifecycle != null) {
80             lifecycle.addObserver(this);
81         }
82     }
83 
84     @OnLifecycleEvent(Event.ON_RESUME)
onResume()85     public void onResume() {
86         mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
87                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
88         mMobileNetworkRepository.updateEntity();
89         mDataSubscriptionChangedReceiver.registerReceiver();
90         mDefaultVoiceSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
91         mDefaultSmsSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
92     }
93 
94     @OnLifecycleEvent(Event.ON_PAUSE)
onPause()95     public void onPause() {
96         mMobileNetworkRepository.removeRegister(this);
97         mDataSubscriptionChangedReceiver.unRegisterReceiver();
98     }
99 
100     @Override
displayPreference(PreferenceScreen screen)101     public void displayPreference(PreferenceScreen screen) {
102         super.displayPreference(screen);
103         mPreference = screen.findPreference(getPreferenceKey());
104     }
105 
106     @Override
getSummary()107     public CharSequence getSummary() {
108         List<SubscriptionInfoEntity> list = getSubscriptionInfoList();
109         if (list == null || list.isEmpty()) {
110             return setSummaryResId(R.string.calls_sms_no_sim);
111         } else {
112             final StringBuilder summary = new StringBuilder();
113             SubscriptionInfoEntity[] entityArray = list.toArray(
114                     new SubscriptionInfoEntity[0]);
115             for (SubscriptionInfoEntity subInfo : entityArray) {
116                 int subsSize = list.size();
117                 int subId = Integer.parseInt(subInfo.subId);
118                 final CharSequence displayName = subInfo.uniqueName;
119 
120                 // Set displayName as summary if there is only one valid SIM.
121                 if (subsSize == 1
122                         && list.get(0).isValidSubscription
123                         && isInService(subId)) {
124                     return displayName;
125                 }
126 
127                 CharSequence status = getPreferredStatus(subInfo, subsSize, subId);
128                 if (status.toString().isEmpty()) {
129                     // If there are 2 or more SIMs and one of these has no preferred status,
130                     // set only its displayName as summary.
131                     summary.append(displayName);
132                 } else {
133                     summary.append(displayName)
134                             .append(" (")
135                             .append(status)
136                             .append(")");
137                 }
138                 // Do not add ", " for the last subscription.
139                 if (list.size() > 0 && !subInfo.equals(list.get(list.size() - 1))) {
140                     summary.append(", ");
141                 }
142 
143                 if (mIsRtlMode) {
144                     summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
145                 }
146             }
147             return summary;
148         }
149     }
150 
151     @VisibleForTesting
getPreferredStatus(SubscriptionInfoEntity subInfo, int subsSize, int subId)152     protected CharSequence getPreferredStatus(SubscriptionInfoEntity subInfo, int subsSize,
153             int subId) {
154         String status = "";
155         boolean isCallPreferred = subInfo.getSubId() == getDefaultVoiceSubscriptionId();
156         boolean isSmsPreferred = subInfo.getSubId() == getDefaultSmsSubscriptionId();
157 
158         if (!subInfo.isValidSubscription || !isInService(subId)) {
159             status = setSummaryResId(subsSize > 1 ? R.string.calls_sms_unavailable :
160                     R.string.calls_sms_temp_unavailable);
161         } else {
162             if (isCallPreferred && isSmsPreferred) {
163                 status = setSummaryResId(R.string.calls_sms_preferred);
164             } else if (isCallPreferred) {
165                 status = setSummaryResId(R.string.calls_sms_calls_preferred);
166             } else if (isSmsPreferred) {
167                 status = setSummaryResId(R.string.calls_sms_sms_preferred);
168             }
169         }
170         return status;
171     }
172 
setSummaryResId(int resId)173     private String setSummaryResId(int resId) {
174         return mContext.getResources().getString(resId);
175     }
176 
177     @VisibleForTesting
getSubscriptionInfoList()178     protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
179         return mSubInfoEntityList;
180     }
181 
update()182     private void update() {
183         if (mPreference == null || mPreference.isDisabledByAdmin()) {
184             return;
185         }
186         refreshSummary(mPreference);
187         mPreference.setOnPreferenceClickListener(null);
188         mPreference.setFragment(null);
189 
190         if (mSubInfoEntityList == null || mSubInfoEntityList.isEmpty()) {
191             mPreference.setEnabled(false);
192         } else {
193             mPreference.setEnabled(true);
194             mPreference.setFragment(NetworkProviderCallsSmsFragment.class.getCanonicalName());
195         }
196     }
197 
198     @Override
isAvailable()199     public boolean isAvailable() {
200         return SubscriptionUtil.isSimHardwareVisible(mContext) &&
201                 mUserManager.isAdminUser();
202     }
203 
204     @Override
getPreferenceKey()205     public String getPreferenceKey() {
206         return KEY;
207     }
208 
209     @Override
onAirplaneModeChanged(boolean airplaneModeEnabled)210     public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
211         update();
212     }
213 
214     @Override
updateState(Preference preference)215     public void updateState(Preference preference) {
216         super.updateState(preference);
217         if (preference == null) {
218             return;
219         }
220         refreshSummary(mPreference);
221         update();
222     }
223 
224     @VisibleForTesting
isInService(int subId)225     protected boolean isInService(int subId) {
226         ServiceState serviceState =
227                 mTelephonyManager.createForSubscriptionId(subId).getServiceState();
228         return Utils.isInService(serviceState);
229     }
230 
231     @Override
onActiveSubInfoChanged(List<SubscriptionInfoEntity> activeSubInfoList)232     public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> activeSubInfoList) {
233         mSubInfoEntityList = activeSubInfoList;
234         update();
235     }
236 
237     @VisibleForTesting
getDefaultVoiceSubscriptionId()238     protected int getDefaultVoiceSubscriptionId() {
239         return mDefaultVoiceSubId;
240     }
241 
242     @VisibleForTesting
getDefaultSmsSubscriptionId()243     protected int getDefaultSmsSubscriptionId() {
244         return mDefaultSmsSubId;
245     }
246 
247     @Override
onDefaultVoiceChanged(int defaultVoiceSubId)248     public void onDefaultVoiceChanged(int defaultVoiceSubId) {
249         mDefaultVoiceSubId = defaultVoiceSubId;
250         update();
251     }
252 
253     @Override
onDefaultSmsChanged(int defaultSmsSubId)254     public void onDefaultSmsChanged(int defaultSmsSubId) {
255         mDefaultSmsSubId = defaultSmsSubId;
256         update();
257     }
258 }
259