• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.car.settings.qc;
18 
19 import static com.android.car.datasubscription.DataSubscription.DATA_SUBSCRIPTION_ACTION;
20 import static com.android.car.qc.QCItem.QC_ACTION_TOGGLE_STATE;
21 import static com.android.car.qc.QCItem.QC_TYPE_ACTION_SWITCH;
22 import static com.android.car.settings.qc.QCUtils.getActionDisabledDialogIntent;
23 import static com.android.car.settings.qc.QCUtils.getAvailabilityStatusForZoneFromXml;
24 import static com.android.car.settings.qc.SettingsQCRegistry.MOBILE_DATA_ROW_URI;
25 
26 import android.app.PendingIntent;
27 import android.car.drivingstate.CarUxRestrictions;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.graphics.drawable.Icon;
32 import android.net.Uri;
33 import android.os.UserManager;
34 import android.text.TextUtils;
35 
36 import androidx.annotation.VisibleForTesting;
37 
38 import com.android.car.datasubscription.DataSubscription;
39 import com.android.car.qc.QCActionItem;
40 import com.android.car.qc.QCCategory;
41 import com.android.car.qc.QCItem;
42 import com.android.car.qc.QCList;
43 import com.android.car.qc.QCRow;
44 import com.android.car.settings.R;
45 import com.android.car.settings.common.Logger;
46 import com.android.car.settings.enterprise.EnterpriseUtils;
47 import com.android.settingslib.net.DataUsageController;
48 
49 /**
50  * QCItem for showing a mobile data row element.
51  * The row contains a data icon, the current default network name, and a switch
52  * to enable/disable mobile data.
53  */
54 public class MobileDataRow extends SettingsQCItem {
55     private static final String TAG = MobileDataRow.class.getSimpleName();
56     private static final Logger LOG = new Logger(MobileDataRow.class);
57     private final DataUsageController mDataUsageController;
58     private boolean mIsDistractionOptimizationRequired;
59     private DataSubscription mSubscription;
60 
MobileDataRow(Context context)61     public MobileDataRow(Context context) {
62         super(context);
63         setAvailabilityStatusForZone(getAvailabilityStatusForZoneFromXml(context,
64                 R.xml.network_and_internet_fragment, R.string.pk_mobile_network_settings_entry));
65         mDataUsageController = getDataUsageController(context);
66         mSubscription = new DataSubscription(context);
67     }
68     @Override
getQCItem()69     QCItem getQCItem() {
70         if (!mDataUsageController.isMobileDataSupported() || isHiddenForZone()) {
71             return null;
72         }
73 
74         boolean dataEnabled = mDataUsageController.isMobileDataEnabled();
75         Icon icon = MobileNetworkQCUtils.getMobileNetworkSignalIcon(getContext());
76 
77         String userRestriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
78         boolean hasDpmRestrictions = EnterpriseUtils.hasUserRestrictionByDpm(getContext(),
79                 userRestriction);
80         boolean hasUmRestrictions = EnterpriseUtils.hasUserRestrictionByUm(getContext(),
81                 userRestriction);
82 
83         boolean isReadOnlyForZone = isReadOnlyForZone();
84         PendingIntent disabledPendingIntent = isReadOnlyForZone
85                 ? QCUtils.getDisabledToastBroadcastIntent(getContext())
86                 : getActionDisabledDialogIntent(getContext(), userRestriction);
87 
88         QCActionItem dataToggle = new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH)
89                 .setChecked(dataEnabled)
90                 .setAction(getBroadcastIntent())
91                 .setEnabled(!hasUmRestrictions && !hasDpmRestrictions && isWritableForZone())
92                 .setClickableWhileDisabled(hasDpmRestrictions || isReadOnlyForZone)
93                 .setDisabledClickAction(disabledPendingIntent)
94                 .setContentDescription(getContext(), R.string.mobile_network_toggle_title)
95                 .build();
96 
97         QCRow dataRow = new QCRow.Builder()
98                 .setTitle(getContext().getString(R.string.mobile_network_settings))
99                 .setSubtitle(getSubtitle(dataEnabled))
100                 .setCategory(getCategory())
101                 .setActionText(getActionText(dataEnabled))
102                 .setIcon(icon)
103                 .setPrimaryAction(getPrimaryAction())
104                 .addEndItem(dataToggle)
105                 .build();
106 
107         try {
108             dataRow.setPackageUid(getContext()
109                     .getPackageManager()
110                     .getApplicationInfo(getContext().getPackageName(), 0).uid);
111             dataRow.setTag(TAG);
112         } catch (PackageManager.NameNotFoundException e) {
113             LOG.w("Can't find application info for package " + e);
114         }
115         return new QCList.Builder()
116                 .addRow(dataRow)
117                 .build();
118     }
119 
120     @Override
getUri()121     Uri getUri() {
122         return MOBILE_DATA_ROW_URI;
123     }
124 
125     @Override
onNotifyChange(Intent intent)126     void onNotifyChange(Intent intent) {
127         boolean newState = intent.getBooleanExtra(QC_ACTION_TOGGLE_STATE,
128                 !mDataUsageController.isMobileDataEnabled());
129         mDataUsageController.setMobileDataEnabled(newState);
130     }
131 
132     @Override
getBackgroundWorkerClass()133     Class getBackgroundWorkerClass() {
134         return MobileDataRowWorker.class;
135     }
136 
137     @VisibleForTesting
getDataUsageController(Context context)138     DataUsageController getDataUsageController(Context context) {
139         return new DataUsageController(context);
140     }
141 
getSubtitle(boolean dataEnabled)142     String getSubtitle(boolean dataEnabled) {
143         String subtitle = MobileNetworkQCUtils.getMobileNetworkSummary(
144                 getContext(), dataEnabled);
145         if (TextUtils.isEmpty(subtitle)
146                 && isDataSubscriptionFlagEnable()
147                 && dataEnabled
148                 && mSubscription.isDataSubscriptionInactive()) {
149             return getContext().getString(
150                     R.string.connectivity_inactive_prompt);
151         }
152         return subtitle;
153     }
154 
getActionText(boolean dataEnabled)155     String getActionText(boolean dataEnabled) {
156         if (isDataSubscriptionFlagEnable()
157                 && dataEnabled
158                 && mSubscription.isDataSubscriptionInactive()
159                 && !mIsDistractionOptimizationRequired) {
160             return getContext().getString(
161                     R.string.connectivity_inactive_action_text);
162         }
163         return null;
164     }
165 
getCategory()166     int getCategory() {
167         if (isDataSubscriptionFlagEnable()
168                 && mSubscription.isDataSubscriptionInactive()) {
169             return QCCategory.WARNING;
170         }
171         return QCCategory.NORMAL;
172     }
173 
setIsDistractionOptimizationRequired(CarUxRestrictions carUxRestrictions)174     void setIsDistractionOptimizationRequired(CarUxRestrictions carUxRestrictions) {
175         if (carUxRestrictions == null) {
176             mIsDistractionOptimizationRequired = false;
177         } else {
178             mIsDistractionOptimizationRequired = carUxRestrictions
179                     .isRequiresDistractionOptimization();
180         }
181     }
182 
setCarUxRestrictions(CarUxRestrictions carUxRestrictions)183     void setCarUxRestrictions(CarUxRestrictions carUxRestrictions) {
184         setIsDistractionOptimizationRequired(carUxRestrictions);
185     }
186 
getPrimaryAction()187     PendingIntent getPrimaryAction() {
188         if (!isDataSubscriptionFlagEnable()) {
189             return null;
190         }
191         if (!mSubscription.isDataSubscriptionInactive()
192                 || mIsDistractionOptimizationRequired) {
193             return null;
194         }
195         Intent dataSubscriptionIntent = new Intent(DATA_SUBSCRIPTION_ACTION);
196         dataSubscriptionIntent.setPackage(getContext().getString(
197                         R.string.connectivity_flow_app));
198         dataSubscriptionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
199         PendingIntent intent = PendingIntent.getActivity(getContext(), /* requestCode= */ 0,
200                 dataSubscriptionIntent, PendingIntent.FLAG_IMMUTABLE, null);
201         return intent;
202     }
203 
isDataSubscriptionFlagEnable()204     private boolean isDataSubscriptionFlagEnable() {
205         return com.android.car.datasubscription.Flags.dataSubscriptionPopUp();
206     }
207 
208     @VisibleForTesting
setSubscription(DataSubscription dataSubscription)209     public void setSubscription(DataSubscription dataSubscription) {
210         mSubscription = dataSubscription;
211     }
212 }
213