• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.telephony;
18 
19 import android.content.Context;
20 import android.os.Build;
21 import android.safetycenter.SafetyCenterManager;
22 import android.telephony.SubscriptionInfo;
23 import android.telephony.TelephonyManager;
24 import android.util.Log;
25 
26 import androidx.annotation.NonNull;
27 import androidx.annotation.VisibleForTesting;
28 
29 import com.android.settings.network.SubscriptionUtil;
30 
31 import java.util.List;
32 
33 /**
34  * {@link TelephonyTogglePreferenceController} for accessing Cellular Security settings through
35  * Safety Center.
36  */
37 public class CellularSecurityNotificationsPreferenceController extends
38                 TelephonyTogglePreferenceController {
39 
40     private static final String LOG_TAG = "CellularSecurityNotificationsPreferenceController";
41 
42     private TelephonyManager mTelephonyManager;
43     @VisibleForTesting
44     protected SafetyCenterManager mSafetyCenterManager;
45 
46     /**
47      * Class constructor of "Cellular Security" preference.
48      *
49      * @param context of settings
50      * @param prefKey assigned within UI entry of XML file
51      */
CellularSecurityNotificationsPreferenceController( @onNull Context context, @NonNull String prefKey)52     public CellularSecurityNotificationsPreferenceController(
53             @NonNull Context context, @NonNull String prefKey) {
54         super(context, prefKey);
55         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
56         mSafetyCenterManager = mContext.getSystemService(SafetyCenterManager.class);
57     }
58 
59     /**
60      * Initialization based on a given subscription id.
61      *
62      * @param subId is the subscription id
63      * @return this instance after initialization
64      */
init(@onNull int subId)65     @NonNull public CellularSecurityNotificationsPreferenceController init(@NonNull int subId) {
66         mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
67                 .createForSubscriptionId(subId);
68         return this;
69     }
70 
71     @Override
getAvailabilityStatus(int subId)72     public int getAvailabilityStatus(int subId) {
73         if (!isSafetyCenterSupported()) {
74             return UNSUPPORTED_ON_DEVICE;
75         }
76 
77         // Check there are valid SIM cards which can be displayed to the user, otherwise this
78         // setting should not be shown.
79         List<SubscriptionInfo> availableSubs = SubscriptionUtil.getAvailableSubscriptions(mContext);
80         if (availableSubs.isEmpty()) {
81             return CONDITIONALLY_UNAVAILABLE;
82         }
83 
84         // Checking for hardware support, i.e. IRadio AIDL version must be >= 2.2
85         try {
86             areNotificationsEnabled();
87         } catch (UnsupportedOperationException e) {
88             Log.i(LOG_TAG, "Cellular security notifications are unsupported: " + e.getMessage());
89             return UNSUPPORTED_ON_DEVICE;
90         }
91 
92         return AVAILABLE;
93     }
94 
95     /**
96      * Return {@code true} if cellular security notifications are on
97      *
98      * <p><b>NOTE:</b> This method returns the active state of the preference controller and is not
99      * the parameter passed into {@link #setChecked(boolean)}, which is instead the requested future
100      * state.
101      */
102     @Override
isChecked()103     public boolean isChecked() {
104         try {
105             // Note: the default behavior for this toggle is disabled (as the underlying
106             // TelephonyManager APIs are disabled by default)
107             return areNotificationsEnabled();
108         } catch (Exception e) {
109             Log.e(LOG_TAG,
110                     "Failed isNullCipherNotificationsEnabled and "
111                             + "isCellularIdentifierDisclosureNotificationsEnabled."
112                             + "Defaulting toggle to checked = true. Exception: "
113                             + e.getMessage());
114             return false;
115         }
116     }
117 
118     /**
119      * Called when a user preference changes on the toggle. We pass this info on to the Telephony
120      * Framework so that the modem can be updated with the user's preference.
121      *
122      * <p>See {@link com.android.settings.core.TogglePreferenceController#setChecked(boolean)} for
123      * details.
124      *
125      * @param isChecked The toggle value that we're being requested to enforce. A value of {@code
126      *                  true} denotes that both (1) null cipher/integrity notifications, and
127      *                  (2) IMSI disclosure notifications will be enabled by the modem after this
128      *                  function completes, if they are not already.
129      */
130     @Override
setChecked(boolean isChecked)131     public boolean setChecked(boolean isChecked) {
132         if (isChecked) {
133             Log.i(LOG_TAG, "Enabling cellular security notifications.");
134         } else {
135             Log.i(LOG_TAG, "Disabling cellular security notifications.");
136         }
137 
138         try {
139             setNotifications(isChecked);
140         } catch (Exception e) {
141             Log.e(LOG_TAG,
142                     "Failed setCellularIdentifierDisclosureNotificationEnabled or "
143                             + " setNullCipherNotificationsEnabled. Setting not updated. Exception: "
144                             + e.getMessage());
145             // Reset to defaults so we don't end up in an inconsistent state
146             setNotifications(!isChecked);
147             return false;
148         }
149         return true;
150     }
151 
setNotifications(boolean isChecked)152     private void setNotifications(boolean isChecked) {
153         mTelephonyManager.setEnableCellularIdentifierDisclosureNotifications(isChecked);
154         mTelephonyManager.setNullCipherNotificationsEnabled(isChecked);
155     }
156 
areNotificationsEnabled()157     private boolean areNotificationsEnabled() {
158         if (mTelephonyManager == null) {
159             Log.w(LOG_TAG, "Telephony manager not yet initialized");
160             mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
161         }
162         return mTelephonyManager.isNullCipherNotificationsEnabled()
163             && mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
164     }
165 
isSafetyCenterSupported()166     protected boolean isSafetyCenterSupported() {
167         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
168             return false;
169         }
170         mSafetyCenterManager = mContext.getSystemService(
171                 SafetyCenterManager.class);
172         if (mSafetyCenterManager == null) {
173             return false;
174         }
175         return mSafetyCenterManager.isSafetyCenterEnabled();
176     }
177 }
178