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.SubscriptionInfo;
25 import android.telephony.SubscriptionManager;
26 import android.telephony.TelephonyManager;
27 import android.view.View;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.lifecycle.LifecycleObserver;
31 import androidx.lifecycle.OnLifecycleEvent;
32 import androidx.preference.Preference;
33 import androidx.preference.PreferenceScreen;
34 
35 import com.android.settings.R;
36 import com.android.settingslib.RestrictedPreference;
37 import com.android.settingslib.Utils;
38 import com.android.settingslib.core.AbstractPreferenceController;
39 import com.android.settingslib.core.lifecycle.Lifecycle;
40 
41 import java.util.List;
42 
43 public class NetworkProviderCallsSmsController extends AbstractPreferenceController implements
44         SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
45 
46     private static final String TAG = "NetworkProviderCallsSmsController";
47     private static final String KEY = "calls_and_sms";
48     private static final String RTL_MARK = "\u200F";
49 
50     private UserManager mUserManager;
51     private SubscriptionManager mSubscriptionManager;
52     private SubscriptionsChangeListener mSubscriptionsChangeListener;
53     private TelephonyManager mTelephonyManager;
54     private RestrictedPreference mPreference;
55     private boolean mIsRtlMode;
56 
57     /**
58      * The summary text and click behavior of the "Calls & SMS" item on the
59      * Network & internet page.
60      */
NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle)61     public NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle) {
62         super(context);
63 
64         mUserManager = context.getSystemService(UserManager.class);
65         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
66         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
67         mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
68                 == View.LAYOUT_DIRECTION_RTL;
69         if (lifecycle != null) {
70             mSubscriptionsChangeListener = new SubscriptionsChangeListener(context, this);
71             lifecycle.addObserver(this);
72         }
73     }
74 
75     @OnLifecycleEvent(Event.ON_RESUME)
onResume()76     public void onResume() {
77         mSubscriptionsChangeListener.start();
78         update();
79     }
80 
81     @OnLifecycleEvent(Event.ON_PAUSE)
onPause()82     public void onPause() {
83         mSubscriptionsChangeListener.stop();
84     }
85 
86     @Override
displayPreference(PreferenceScreen screen)87     public void displayPreference(PreferenceScreen screen) {
88         super.displayPreference(screen);
89         mPreference = screen.findPreference(getPreferenceKey());
90     }
91 
92     @Override
getSummary()93     public CharSequence getSummary() {
94         final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(
95                 mSubscriptionManager);
96 
97         if (subs.isEmpty()) {
98             return setSummaryResId(R.string.calls_sms_no_sim);
99         } else {
100             final StringBuilder summary = new StringBuilder();
101             for (SubscriptionInfo subInfo : subs) {
102                 int subsSize = subs.size();
103                 int subId = subInfo.getSubscriptionId();
104                 final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
105                         subInfo, mContext);
106 
107                 // Set displayName as summary if there is only one valid SIM.
108                 if (subsSize == 1
109                         && SubscriptionManager.isValidSubscriptionId(subId)
110                         && isInService(subId)) {
111                     return displayName;
112                 }
113 
114                 CharSequence status = getPreferredStatus(subsSize, subId);
115                 if (status.toString().isEmpty()) {
116                     // If there are 2 or more SIMs and one of these has no preferred status,
117                     // set only its displayName as summary.
118                     summary.append(displayName);
119                 } else {
120                     summary.append(displayName)
121                             .append(" (")
122                             .append(status)
123                             .append(")");
124                 }
125                 // Do not add ", " for the last subscription.
126                 if (subInfo != subs.get(subs.size() - 1)) {
127                     summary.append(", ");
128                 }
129 
130                 if (mIsRtlMode) {
131                     summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
132                 }
133             }
134             return summary;
135         }
136     }
137 
138     @VisibleForTesting
getPreferredStatus(int subsSize, int subId)139     protected CharSequence getPreferredStatus(int subsSize, int subId) {
140         String status = "";
141         boolean isDataPreferred = subId == getDefaultVoiceSubscriptionId();
142         boolean isSmsPreferred = subId == getDefaultSmsSubscriptionId();
143 
144         if (!SubscriptionManager.isValidSubscriptionId(subId) || !isInService(subId)) {
145             status = setSummaryResId(subsSize > 1 ? R.string.calls_sms_unavailable :
146                     R.string.calls_sms_temp_unavailable);
147         } else {
148             if (isDataPreferred && isSmsPreferred) {
149                 status = setSummaryResId(R.string.calls_sms_preferred);
150             } else if (isDataPreferred) {
151                 status = setSummaryResId(R.string.calls_sms_calls_preferred);
152             } else if (isSmsPreferred) {
153                 status = setSummaryResId(R.string.calls_sms_sms_preferred);
154             }
155         }
156         return status;
157     }
158 
setSummaryResId(int resId)159     private String setSummaryResId(int resId) {
160         return mContext.getResources().getString(resId);
161     }
162 
163     @VisibleForTesting
getDefaultVoiceSubscriptionId()164     protected int getDefaultVoiceSubscriptionId() {
165         return SubscriptionManager.getDefaultVoiceSubscriptionId();
166     }
167 
168     @VisibleForTesting
getDefaultSmsSubscriptionId()169     protected int getDefaultSmsSubscriptionId() {
170         return SubscriptionManager.getDefaultSmsSubscriptionId();
171     }
172 
update()173     private void update() {
174         if (mPreference == null || mPreference.isDisabledByAdmin()) {
175             return;
176         }
177         refreshSummary(mPreference);
178         mPreference.setOnPreferenceClickListener(null);
179         mPreference.setFragment(null);
180 
181         final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(
182                 mSubscriptionManager);
183         if (subs.isEmpty()) {
184             mPreference.setEnabled(false);
185         } else {
186             mPreference.setEnabled(true);
187             mPreference.setFragment(NetworkProviderCallsSmsFragment.class.getCanonicalName());
188         }
189     }
190 
191     @Override
isAvailable()192     public boolean isAvailable() {
193         return mUserManager.isAdminUser();
194     }
195 
196     @Override
getPreferenceKey()197     public String getPreferenceKey() {
198         return KEY;
199     }
200 
201     @Override
onAirplaneModeChanged(boolean airplaneModeEnabled)202     public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
203         update();
204     }
205 
206     @Override
updateState(Preference preference)207     public void updateState(Preference preference) {
208         super.updateState(preference);
209         if (preference == null) {
210             return;
211         }
212         refreshSummary(mPreference);
213         update();
214     }
215 
216     @Override
onSubscriptionsChanged()217     public void onSubscriptionsChanged() {
218         refreshSummary(mPreference);
219         update();
220     }
221 
222     @VisibleForTesting
isInService(int subId)223     protected boolean isInService(int subId) {
224         ServiceState serviceState =
225                 mTelephonyManager.createForSubscriptionId(subId).getServiceState();
226         return Utils.isInService(serviceState);
227     }
228 }
229