1 /*
2  * Copyright (C) 2022 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.sim;
18 
19 import android.app.Dialog;
20 import android.app.settings.SettingsEnums;
21 import android.content.DialogInterface;
22 import android.os.Bundle;
23 import android.os.UserHandle;
24 import android.os.UserManager;
25 import android.telephony.SubscriptionInfo;
26 import android.telephony.SubscriptionManager;
27 import android.telephony.TelephonyManager;
28 import android.text.TextUtils;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.widget.TextView;
33 
34 import androidx.annotation.NonNull;
35 import androidx.annotation.Nullable;
36 import androidx.annotation.VisibleForTesting;
37 import androidx.appcompat.app.AlertDialog;
38 
39 import com.android.settings.R;
40 import com.android.settings.network.SubscriptionUtil;
41 
42 import java.util.List;
43 
44 /**
45  * Show a dialog prompting the user to enable auto data switch following the dialog where user chose
46  * default data SIM.
47  */
48 public class EnableAutoDataSwitchDialogFragment extends SimDialogFragment implements
49         DialogInterface.OnClickListener {
50     private static final String TAG = "EnableAutoDataSwitchDialogFragment";
51     /** Sub Id of the non-default data SIM */
52     private int mBackupDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
53 
54     /** @return a new instance of this fragment */
newInstance()55     public static EnableAutoDataSwitchDialogFragment newInstance() {
56         final EnableAutoDataSwitchDialogFragment fragment =
57                 new EnableAutoDataSwitchDialogFragment();
58         final Bundle args = initArguments(SimDialogActivity.ENABLE_AUTO_DATA_SWITCH,
59                 R.string.enable_auto_data_switch_dialog_title);
60         fragment.setArguments(args);
61         return fragment;
62     }
63 
64     @NonNull
65     @Override
onCreateDialog(@ullable Bundle savedInstanceState)66     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
67         final AlertDialog dialog = new AlertDialog.Builder(getContext())
68                 .setPositiveButton(R.string.yes, this)
69                 .setNegativeButton(R.string.sim_action_no_thanks, null)
70                 .create();
71         updateDialog(dialog);
72         return dialog;
73     }
74 
75     @Override
getMetricsCategory()76     public int getMetricsCategory() {
77         return SettingsEnums.DIALOG_AUTO_DATA_SWITCH;
78     }
79 
80     /** update dialog */
updateDialog(AlertDialog dialog)81     public void updateDialog(AlertDialog dialog) {
82         Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed);
83 
84         if (mWasDismissed) {
85             return;
86         }
87 
88         if (dialog == null) {
89             Log.d(TAG, "Dialog is null.");
90             dismiss();
91             return;
92         }
93 
94         // Set message
95         View content = LayoutInflater.from(getContext()).inflate(
96                 R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
97         TextView dialogMessage = content != null ? content.findViewById(R.id.msg) : null;
98         final String message = getMessage();
99         if (TextUtils.isEmpty(message) || dialogMessage == null) {
100             onDismiss(dialog);
101             return;
102         }
103         dialogMessage.setText(message);
104         dialogMessage.setVisibility(View.VISIBLE);
105         dialog.setView(content);
106 
107         // Set title
108         View titleView = LayoutInflater.from(getContext()).inflate(
109                 R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported, null);
110         TextView titleTextView = titleView.findViewById(R.id.title);
111         titleTextView.setText(getContext().getString(getTitleResId()));
112         dialog.setCustomTitle(titleTextView);
113     }
114 
115     /**
116      * @return The message of the dialog. {@code null} if the dialog shouldn't be displayed.
117      */
118     @VisibleForTesting
getMessage()119     protected String getMessage() {
120         int ddsSubId = getDefaultDataSubId();
121         if (ddsSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return null;
122         Log.d(TAG, "DDS SubId: " + ddsSubId);
123 
124         SubscriptionManager subscriptionManager = getSubscriptionManager();
125         List<SubscriptionInfo> activeSubscriptions  = subscriptionManager
126                 .getActiveSubscriptionInfoList();
127         if (activeSubscriptions == null) return null;
128 
129         // Find if a backup data sub exists.
130         SubscriptionInfo backupSubInfo = activeSubscriptions.stream()
131                 .filter(subInfo -> subInfo.getSubscriptionId() != ddsSubId)
132                 .findFirst()
133                 .orElse(null);
134         if (backupSubInfo == null) return null;
135         mBackupDataSubId = backupSubInfo.getSubscriptionId();
136 
137         // Check if auto data switch is already enabled
138         final TelephonyManager telephonyManager = getTelephonyManagerForSub(mBackupDataSubId);
139         if (telephonyManager == null) {
140             Log.d(TAG, "telephonyManager for " + mBackupDataSubId + " is null");
141             return null;
142         }
143         if (telephonyManager.isMobileDataPolicyEnabled(
144                 TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)) {
145             Log.d(TAG, "AUTO_DATA_SWITCH already enabled");
146             return null;
147         }
148 
149         Log.d(TAG, "Backup data sub Id: " + mBackupDataSubId);
150         // The description of the feature
151         String message =
152                 getContext().getString(
153                         R.string.enable_auto_data_switch_dialog_message,
154                         SubscriptionUtil.getUniqueSubscriptionDisplayName(
155                                 backupSubInfo, getContext()));
156         UserManager userManager = getUserManager();
157         if (userManager == null) return message;
158 
159         // If one of the sub is dedicated to work profile(enterprise-managed), which means we might
160         // switching between personal & work profile, append a warning to the message.
161         UserHandle ddsUserHandle = subscriptionManager.getSubscriptionUserHandle(ddsSubId);
162         UserHandle nDdsUserHandle = subscriptionManager.getSubscriptionUserHandle(mBackupDataSubId);
163         boolean isDdsManaged = ddsUserHandle != null && userManager.isManagedProfile(
164                 ddsUserHandle.getIdentifier());
165         boolean isNDdsManaged = nDdsUserHandle != null && userManager.isManagedProfile(
166                 nDdsUserHandle.getIdentifier());
167         Log.d(TAG, "isDdsManaged= " + isDdsManaged + " isNDdsManaged=" + isNDdsManaged);
168         if (isDdsManaged ^ isNDdsManaged) {
169             message += getContext().getString(
170                     R.string.auto_data_switch_dialog_managed_profile_warning);
171         }
172 
173         return message;
174     }
175 
176     @Override
updateDialog()177     public void updateDialog() {
178         updateDialog((AlertDialog) getDialog());
179     }
180 
181     @Override
onClick(DialogInterface dialog, int buttonClicked)182     public void onClick(DialogInterface dialog, int buttonClicked) {
183         if (buttonClicked != DialogInterface.BUTTON_POSITIVE) {
184             return;
185         }
186         final SimDialogActivity activity = (SimDialogActivity) getActivity();
187         if (mBackupDataSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
188             activity.onSubscriptionSelected(getDialogType(), mBackupDataSubId);
189         }
190     }
191 
getTelephonyManagerForSub(int subId)192     private TelephonyManager getTelephonyManagerForSub(int subId) {
193         return getContext().getSystemService(TelephonyManager.class)
194                 .createForSubscriptionId(subId);
195     }
196 
getSubscriptionManager()197     private SubscriptionManager getSubscriptionManager() {
198         return getContext().getSystemService(SubscriptionManager.class).createForAllUserProfiles();
199     }
200 
201     @VisibleForTesting
getDefaultDataSubId()202     protected int getDefaultDataSubId() {
203         return SubscriptionManager.getDefaultDataSubscriptionId();
204     }
205 
getUserManager()206     private UserManager getUserManager() {
207         return getContext().getSystemService(UserManager.class);
208     }
209 }
210