• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.car.settings.network;
18 
19 import static com.android.car.datasubscription.DataSubscription.DATA_SUBSCRIPTION_ACTION;
20 
21 import android.annotation.SuppressLint;
22 import android.car.drivingstate.CarUxRestrictions;
23 import android.content.ActivityNotFoundException;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.database.ContentObserver;
27 import android.net.ConnectivityManager;
28 import android.net.Uri;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.UserManager;
32 import android.provider.Settings;
33 import android.telephony.SubscriptionInfo;
34 import android.telephony.SubscriptionManager;
35 import android.telephony.TelephonyManager;
36 
37 import androidx.annotation.CallSuper;
38 import androidx.annotation.VisibleForTesting;
39 
40 import com.android.car.datasubscription.DataSubscription;
41 import com.android.car.settings.R;
42 import com.android.car.settings.common.ColoredTwoActionSwitchPreference;
43 import com.android.car.settings.common.DataSubscriptionStatsLogHelper;
44 import com.android.car.settings.common.FragmentController;
45 import com.android.car.settings.common.Logger;
46 import com.android.car.settings.common.PreferenceController;
47 import com.android.settingslib.utils.StringUtil;
48 
49 import java.util.List;
50 
51 /** Controls the preference for accessing mobile network settings. */
52 public class MobileNetworkEntryPreferenceController extends
53         PreferenceController<ColoredTwoActionSwitchPreference> implements
54         SubscriptionsChangeListener.SubscriptionsChangeAction,
55         DataSubscription.DataSubscriptionChangeListener {
56     private static final Logger LOG = new Logger(MobileNetworkEntryPreferenceController.class);
57     private final UserManager mUserManager;
58     private final SubscriptionsChangeListener mChangeListener;
59     private final SubscriptionManager mSubscriptionManager;
60     private final ConnectivityManager mConnectivityManager;
61     private final TelephonyManager mTelephonyManager;
62     private final int mSubscriptionId;
63     private final ContentObserver mMobileDataChangeObserver = new ContentObserver(
64             new Handler(Looper.getMainLooper())) {
65         @Override
66         public void onChange(boolean selfChange) {
67             super.onChange(selfChange);
68             refreshUi();
69         }
70     };
71     private DataSubscription mSubscription;
72 
73     @SuppressLint("MissingPermission")
MobileNetworkEntryPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)74     public MobileNetworkEntryPreferenceController(Context context, String preferenceKey,
75             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
76         super(context, preferenceKey, fragmentController, uxRestrictions);
77         mUserManager = UserManager.get(context);
78         mChangeListener = new SubscriptionsChangeListener(context, /* action= */ this);
79         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
80         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
81         mTelephonyManager = context.getSystemService(TelephonyManager.class);
82         mSubscriptionId = SubscriptionManager.getDefaultDataSubscriptionId();
83         if (isDataSubscriptionFlagEnable()) {
84             mSubscription = new DataSubscription(context);
85         }
86     }
87 
88     @Override
getPreferenceType()89     protected Class<ColoredTwoActionSwitchPreference> getPreferenceType() {
90         return ColoredTwoActionSwitchPreference.class;
91     }
92 
93     @Override
onCreateInternal()94     protected void onCreateInternal() {
95         super.onCreateInternal();
96         getPreference().setOnSecondaryActionClickListener(this::onSecondaryActionClick);
97     }
98 
99     @Override
updateState(ColoredTwoActionSwitchPreference preference)100     protected void updateState(ColoredTwoActionSwitchPreference preference) {
101         List<SubscriptionInfo> subs = SubscriptionUtils.getAvailableSubscriptions(
102                 mSubscriptionManager, mTelephonyManager);
103         preference.setEnabled(getAvailabilityStatus() == AVAILABLE);
104         preference.setSummary(getSummary(subs));
105         preference.setActionText(getActionText());
106         getPreference().setSecondaryActionChecked(mTelephonyManager.isDataEnabled());
107     }
108 
109     @Override
onStartInternal()110     protected void onStartInternal() {
111         mChangeListener.start();
112         if (mSubscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
113             getContext().getContentResolver().registerContentObserver(getObservableUri(
114                     mSubscriptionId), /* notifyForDescendants= */ false, mMobileDataChangeObserver);
115         }
116         if (mSubscription != null) {
117             mSubscription.addDataSubscriptionListener(this);
118         }
119     }
120 
121     @Override
onStopInternal()122     protected void onStopInternal() {
123         mChangeListener.stop();
124         if (mSubscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
125             getContext().getContentResolver().unregisterContentObserver(mMobileDataChangeObserver);
126         }
127         if (mSubscription != null) {
128             mSubscription.removeDataSubscriptionListener();
129         }
130     }
131 
132     @Override
getDefaultAvailabilityStatus()133     protected int getDefaultAvailabilityStatus() {
134         if (!NetworkUtils.hasMobileNetwork(mConnectivityManager)
135                 && !NetworkUtils.hasSim(mTelephonyManager)) {
136             return UNSUPPORTED_ON_DEVICE;
137         }
138         boolean isNotAdmin = !mUserManager.isAdminUser();
139         boolean hasRestriction =
140                 mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
141         if (isNotAdmin || hasRestriction) {
142             return DISABLED_FOR_PROFILE;
143         }
144         return AVAILABLE;
145     }
146 
147     @Override
handlePreferenceClicked(ColoredTwoActionSwitchPreference preference)148     protected boolean handlePreferenceClicked(ColoredTwoActionSwitchPreference preference) {
149         List<SubscriptionInfo> subs = SubscriptionUtils.getAvailableSubscriptions(
150                 mSubscriptionManager, mTelephonyManager);
151         if (subs.isEmpty()) {
152             if (isDataSubscriptionFlagEnable()
153                     && mSubscription.isDataSubscriptionInactive()) {
154                 Intent dataSubscriptionIntent = new Intent(DATA_SUBSCRIPTION_ACTION);
155                 dataSubscriptionIntent.setPackage(getContext().getString(
156                         R.string.connectivity_flow_app));
157                 dataSubscriptionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
158                 try {
159                     getContext().startActivity(dataSubscriptionIntent);
160                 } catch (ActivityNotFoundException e) {
161                     LOG.w("Can't start activity from package " + DATA_SUBSCRIPTION_ACTION);
162                 }
163                 finally {
164                     DataSubscriptionStatsLogHelper.getInstance()
165                             .writeDataSubscriptionEventReported();
166                 }
167             }
168         } else if (subs.size() == 1) {
169             getFragmentController().launchFragment(
170                     MobileNetworkFragment.newInstance(subs.get(0).getSubscriptionId()));
171         } else {
172             getFragmentController().launchFragment(new MobileNetworkListFragment());
173         }
174         return true;
175     }
176 
177     @Override
handlePreferenceChanged(ColoredTwoActionSwitchPreference preference, Object newValue)178     protected boolean handlePreferenceChanged(ColoredTwoActionSwitchPreference preference,
179             Object newValue) {
180         List<SubscriptionInfo> subs = SubscriptionUtils.getAvailableSubscriptions(
181                 mSubscriptionManager, mTelephonyManager);
182         preference.setSummary(getSummary(subs));
183         preference.setActionText(getActionText());
184         return true;
185     }
186 
187     @Override
188     @CallSuper
onSubscriptionsChanged()189     public void onSubscriptionsChanged() {
190         refreshUi();
191     }
192 
getSummary(List<SubscriptionInfo> subs)193     private CharSequence getSummary(List<SubscriptionInfo> subs) {
194         if (!mTelephonyManager.isDataEnabled()) {
195             return getContext().getString(R.string.mobile_network_state_off);
196         }
197         int count = subs.size();
198         if (subs.isEmpty()) {
199             if (isDataSubscriptionFlagEnable()
200                     && mSubscription.isDataSubscriptionInactive()) {
201                 return getContext().getString(R.string.connectivity_inactive_prompt);
202             } else {
203                 return null;
204             }
205         } else if (count == 1) {
206             return subs.get(0).getDisplayName();
207         } else {
208             return StringUtil.getIcuPluralsString(getContext(), count,
209                     R.string.mobile_network_summary_count);
210         }
211     }
212 
getActionText()213     private CharSequence getActionText() {
214         if (!mTelephonyManager.isDataEnabled()) {
215             return null;
216         }
217         if (isDataSubscriptionFlagEnable()
218                 && mSubscription.isDataSubscriptionInactive()
219                 && !getUxRestrictions().isRequiresDistractionOptimization()) {
220             getPreference().setIsWarning(true);
221             return getContext().getString(R.string.connectivity_inactive_action_text);
222         }
223         return null;
224     }
225 
getObservableUri(int subId)226     private Uri getObservableUri(int subId) {
227         Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
228         if (mTelephonyManager.getSimCount() != 1) {
229             uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
230         }
231         return uri;
232     }
233 
234     @VisibleForTesting
onSecondaryActionClick(boolean isChecked)235     void onSecondaryActionClick(boolean isChecked) {
236         mTelephonyManager.setDataEnabled(isChecked);
237         handlePreferenceChanged(getPreference(), isChecked);
238     }
239 
240     @VisibleForTesting
setSubscription(DataSubscription subscription)241     void setSubscription(DataSubscription subscription) {
242         mSubscription = subscription;
243     }
244 
isDataSubscriptionFlagEnable()245     private boolean isDataSubscriptionFlagEnable() {
246         return com.android.car.datasubscription.Flags.dataSubscriptionPopUp();
247     }
248 
249     @Override
onChange(int value)250     public void onChange(int value) {
251         refreshUi();
252     }
253 }
254