1 /*
2  * Copyright (C) 2019 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.ON_PAUSE;
20 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
21 
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.UserManager;
25 import android.provider.Settings;
26 import android.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 import android.telephony.euicc.EuiccManager;
29 
30 import androidx.lifecycle.Lifecycle;
31 import androidx.lifecycle.LifecycleObserver;
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.settings.core.PreferenceControllerMixin;
38 import com.android.settings.dashboard.DashboardFragment;
39 import com.android.settings.network.telephony.MobileNetworkActivity;
40 import com.android.settings.network.telephony.MobileNetworkUtils;
41 import com.android.settings.overlay.FeatureFactory;
42 import com.android.settings.widget.AddPreference;
43 import com.android.settingslib.Utils;
44 import com.android.settingslib.core.AbstractPreferenceController;
45 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
46 
47 import java.util.List;
48 
49 public class MobileNetworkSummaryController extends AbstractPreferenceController implements
50         SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver,
51         PreferenceControllerMixin {
52     private static final String TAG = "MobileNetSummaryCtlr";
53 
54     private static final String KEY = "mobile_network_list";
55 
56     private final MetricsFeatureProvider mMetricsFeatureProvider;
57 
58     private SubscriptionManager mSubscriptionManager;
59     private UserManager mUserManager;
60     private SubscriptionsChangeListener mChangeListener;
61     private AddPreference mPreference;
62 
63     /**
64      * This controls the summary text and click behavior of the "Mobile network" item on the
65      * Network & internet page. There are 3 separate cases depending on the number of mobile network
66      * subscriptions:
67      * <ul>
68      * <li>No subscription: click action begins a UI flow to add a network subscription, and
69      * the summary text indicates this</li>
70      *
71      * <li>One subscription: click action takes you to details for that one network, and
72      * the summary text is the network name</li>
73      *
74      * <li>More than one subscription: click action takes you to a page listing the subscriptions,
75      * and the summary text gives the count of SIMs</li>
76      * </ul>
77      */
MobileNetworkSummaryController(Context context, Lifecycle lifecycle)78     public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
79         super(context);
80         mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
81         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
82         mUserManager = context.getSystemService(UserManager.class);
83         if (lifecycle != null) {
84           mChangeListener = new SubscriptionsChangeListener(context, this);
85           lifecycle.addObserver(this);
86         }
87     }
88 
89     @OnLifecycleEvent(ON_RESUME)
onResume()90     public void onResume() {
91         mChangeListener.start();
92         update();
93     }
94 
95     @OnLifecycleEvent(ON_PAUSE)
onPause()96     public void onPause() {
97         mChangeListener.stop();
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         final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
109                 mContext);
110         if (subs.isEmpty()) {
111             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
112                 return mContext.getResources().getString(
113                         R.string.mobile_network_summary_add_a_network);
114             }
115             return null;
116         } else if (subs.size() == 1) {
117             final SubscriptionInfo info = subs.get(0);
118             final int subId = info.getSubscriptionId();
119             if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)
120                     && !SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)) {
121                 return mContext.getString(R.string.mobile_network_tap_to_activate,
122                         SubscriptionUtil.getDisplayName(info));
123             } else {
124                 return subs.get(0).getDisplayName();
125             }
126         } else {
127             final int count = subs.size();
128             return mContext.getResources().getQuantityString(R.plurals.mobile_network_summary_count,
129                     count, count);
130         }
131     }
132 
startAddSimFlow()133     private void startAddSimFlow() {
134         final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
135         intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true);
136         mContext.startActivity(intent);
137     }
138 
update()139     private void update() {
140         if (mPreference == null || mPreference.isDisabledByAdmin()) {
141             return;
142         }
143         refreshSummary(mPreference);
144         mPreference.setOnPreferenceClickListener(null);
145         mPreference.setOnAddClickListener(null);
146         mPreference.setFragment(null);
147         mPreference.setEnabled(!mChangeListener.isAirplaneModeOn());
148 
149         final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
150                 mContext);
151 
152         if (subs.isEmpty()) {
153             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
154                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
155                     mMetricsFeatureProvider.logClickedPreference(pref,
156                             pref.getExtras().getInt(DashboardFragment.CATEGORY));
157                     startAddSimFlow();
158                     return true;
159                 });
160             } else {
161                 mPreference.setEnabled(false);
162             }
163         } else {
164             // We have one or more existing subscriptions, so we want the plus button if eSIM is
165             // supported.
166             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
167                 mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
168                 mPreference.setOnAddClickListener(p -> {
169                     mMetricsFeatureProvider.logClickedPreference(p,
170                             p.getExtras().getInt(DashboardFragment.CATEGORY));
171                     startAddSimFlow();
172                 });
173             }
174 
175             if (subs.size() == 1) {
176                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
177                     mMetricsFeatureProvider.logClickedPreference(pref,
178                             pref.getExtras().getInt(DashboardFragment.CATEGORY));
179                     final SubscriptionInfo info = subs.get(0);
180                     final int subId = info.getSubscriptionId();
181                     if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)
182                             && !SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)) {
183                         mSubscriptionManager.setSubscriptionEnabled(subId, true);
184                     } else {
185                         final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
186                         intent.putExtra(Settings.EXTRA_SUB_ID, subs.get(0).getSubscriptionId());
187                         mContext.startActivity(intent);
188                     }
189                     return true;
190                 });
191             } else {
192                 mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
193             }
194         }
195     }
196 
197     @Override
isAvailable()198     public boolean isAvailable() {
199         return !Utils.isWifiOnly(mContext) && mUserManager.isAdminUser();
200     }
201 
202     @Override
getPreferenceKey()203     public String getPreferenceKey() {
204         return KEY;
205     }
206 
207     @Override
onAirplaneModeChanged(boolean airplaneModeEnabled)208     public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
209         update();
210     }
211 
212     @Override
onSubscriptionsChanged()213     public void onSubscriptionsChanged() {
214         refreshSummary(mPreference);
215         update();
216     }
217 }
218