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;
18 
19 import android.app.settings.SettingsEnums;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.os.Build;
24 import android.os.Bundle;
25 import android.safetycenter.SafetyCenterManager;
26 import android.telephony.TelephonyManager;
27 import android.text.TextUtils;
28 import android.util.Log;
29 
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 import androidx.annotation.VisibleForTesting;
33 import androidx.preference.Preference;
34 import androidx.preference.PreferenceScreen;
35 
36 import com.android.internal.telephony.flags.Flags;
37 import com.android.settings.core.BasePreferenceController;
38 import com.android.settings.core.SubSettingLauncher;
39 import com.android.settings.network.telephony.CellularSecuritySettingsFragment;
40 
41 /**
42  * {@link BasePreferenceController} for accessing Cellular Security settings from Network &
43  * Internet Settings menu.
44  */
45 public class CellularSecurityPreferenceController extends BasePreferenceController {
46 
47     private static final String LOG_TAG = "CellularSecurityPreferenceController";
48 
49     private @Nullable TelephonyManager mTelephonyManager;
50 
51     /**
52      * Class constructor of "Cellular Security" preference.
53      *
54      * @param context of settings
55      * @param prefKey     assigned within UI entry of XML file
56      */
CellularSecurityPreferenceController(@onNull Context context, @NonNull String prefKey)57     public CellularSecurityPreferenceController(@NonNull Context context, @NonNull String prefKey) {
58         super(context, prefKey);
59         mTelephonyManager = context.getSystemService(TelephonyManager.class);
60     }
61 
62     @Override
displayPreference(@onNull PreferenceScreen screen)63     public void displayPreference(@NonNull PreferenceScreen screen) {
64         super.displayPreference(screen);
65     }
66 
67     @Override
getAvailabilityStatus()68     public int getAvailabilityStatus() {
69         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
70                 || !Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
71                 || !Flags.enableModemCipherTransparencyUnsolEvents()
72                 || !Flags.enableIdentifierDisclosureTransparency()
73                 || !Flags.enableModemCipherTransparency()) {
74             return UNSUPPORTED_ON_DEVICE;
75         }
76         if (mTelephonyManager == null) {
77             Log.w(LOG_TAG, "Telephony manager not yet initialized");
78             mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
79         }
80 
81         boolean isNullCipherDisablementAvailable = false;
82         boolean areCellSecNotificationsAvailable = false;
83         try {
84             mTelephonyManager.isNullCipherAndIntegrityPreferenceEnabled();
85             isNullCipherDisablementAvailable = true; // true because it doesn't throw an exception,
86                                                      // we don't want the value of
87                                                      // isNullCipherAndIntegrityEnabled()
88         } catch (UnsupportedOperationException e) {
89             Log.i(LOG_TAG, "Null cipher enablement is unsupported, hiding divider: "
90                     + e.getMessage());
91         } catch (Exception e) {
92             Log.e(LOG_TAG,
93                     "Failed isNullCipherAndIntegrityEnabled. Setting availability to "
94                             + "CONDITIONALLY_UNAVAILABLE. Exception: "
95                             + e.getMessage());
96         }
97 
98         try {
99             // Must call both APIs, as we can't use the combined toggle if both aren't available
100             areNotificationsEnabled();
101             areCellSecNotificationsAvailable = true; // true because it doesn't throw an exception
102                                                      // and we don't want the value of
103                                                      // areNotificationsEnabled()
104         } catch (UnsupportedOperationException e) {
105             Log.i(LOG_TAG, "Cellular security notifications are unsupported, hiding divider: "
106                     + e.getMessage());
107         }
108 
109         if (isNullCipherDisablementAvailable || areCellSecNotificationsAvailable) {
110             return AVAILABLE;
111         } else {
112             return UNSUPPORTED_ON_DEVICE;
113         }
114     }
115 
116     @Override
handlePreferenceTreeClick(@onNull Preference preference)117     public boolean handlePreferenceTreeClick(@NonNull Preference preference) {
118         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
119             return super.handlePreferenceTreeClick(preference);
120         }
121         boolean isSafetyCenterSupported = isSafetyCenterSupported();
122         if (isSafetyCenterSupported) {
123             Intent safetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
124             safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
125                     "AndroidCellularNetworkSecuritySources");
126             mContext.startActivity(safetyCenterIntent);
127         } else {
128             final Bundle bundle = new Bundle();
129             bundle.putString(CellularSecuritySettingsFragment.KEY_CELLULAR_SECURITY_PREFERENCE, "");
130 
131             new SubSettingLauncher(mContext)
132                      .setDestination(CellularSecuritySettingsFragment.class.getName())
133                      .setArguments(bundle)
134                      .setSourceMetricsCategory(SettingsEnums.CELLULAR_SECURITY_SETTINGS)
135                      .launch();
136         }
137         return true;
138     }
139 
140     @VisibleForTesting
isSafetyCenterSupported()141     protected boolean isSafetyCenterSupported() {
142         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
143             return false;
144         }
145         SafetyCenterManager safetyCenterManager = mContext.getSystemService(
146                 SafetyCenterManager.class);
147         if (safetyCenterManager == null) {
148             return false;
149         }
150         return safetyCenterManager.isSafetyCenterEnabled();
151     }
152 
153     @VisibleForTesting
areNotificationsEnabled()154     protected boolean areNotificationsEnabled() {
155         if (mTelephonyManager == null) {
156             Log.w(LOG_TAG, "Telephony manager not yet initialized");
157             mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
158         }
159 
160         return mTelephonyManager.isNullCipherNotificationsEnabled()
161             && mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
162     }
163 }
164