Add new Cellular Network Security page

Test: m & atest CellularSecurityNotificationsDividerControllerTest CellularSecurityNotificationsPreferenceControllerTest CellularSecurityEncryptionDividerControllerTest CellularSecurityPreferenceControllerTest
Bug: b/318428717
Change-Id: I4a6ec5f47beb36bd455e04c2e6c4cea0ba65110f
This commit is contained in:
yomna
2024-01-23 22:49:11 +00:00
committed by Zhechen Yan
parent 6a33366270
commit 5599de4fb5
16 changed files with 1368 additions and 0 deletions

View File

@@ -628,6 +628,17 @@
android:value="true" />
</activity>
<activity android:name="Settings$CellularSecuritySettingsActivity"
android:label="@string/cellular_security_settings_title"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.CELLULAR_NETWORK_SECURITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.network.telephony.CellularSecuritySettingsFragment"/>
</activity>
<activity android:name="Settings$SatelliteSettingActivity"
android:label="@string/satellite_setting"
android:exported="true"

View File

@@ -6183,6 +6183,29 @@
<!-- Title for adaptive connectivity main switch preferences. [CHAR LIMIT=50] -->
<string name="adaptive_connectivity_main_switch_title">Use adaptive connectivity</string>
<!-- Cellular security related strings -->
<!-- Title of Cellular security tile in Network & Internet settings page. [CHAR LIMIT=60]-->
<string name="cellular_security_title">Cellular network security</string>
<!-- Summary of Cellular security tile in Network & Internet settings page. [CHAR LIMIT=NONE]-->
<string name="cellular_security_summary">Network type, encryption, notification controls</string>
<!-- Title of cellular security settings page [CHAR LIMIT=60]-->
<string name="cellular_security_settings_title">Cellular network security</string>
<!-- Title of Cellular security notifications section [CHAR LIMIT=60]-->
<string name="cellular_security_notifications">Notifications</string>
<!-- Title of Cellular security notifications toggle [CHAR LIMIT=60]-->
<string name="cellular_security_notifications_controller_title">Security notifications</string>
<!-- Summary of Cellular security notifications toggle [CHAR LIMIT=NONE]-->
<string name="cellular_security_notifications_controller_summary">Receive notifications in case the cellular network you are connected to is insecure due to lack of encryption, or if the cellular network records your unique decive or SIM identifiers (IMEI &amp; IMSI)</string>
<!--Cellular encryption -->
<!--Cellular encryption title [CHAR LIMIT=60] -->
<string name="cellular_security_settings_encryption_title">Encryption</string>
<!-- Title of Cellular security Network generations divider [CHAR LIMIT=30]-->
<string name="cellular_security_network_generations_title">Network generations</string>
<!-- Summary of Cellular security Network generations divider [CHAR LIMIT=NONE]-->
<string name="cellular_security_network_generations_summary">You can configure each installed SIM card to only connect to networks that support 3G, 4G, and 5G. The SIM will not connect to older, insecure 2G networks. This setting may limit your connectivity in case the only available network is 2G. In case of an emergency, 2G may be used.</string>
<!-- Title of preference group for credential storage settings [CHAR LIMIT=30] -->
<string name="credentials_title">Credential storage</string>
<!-- Title of preference to install certificates [CHAR LIMIT=30] -->

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="cellular_security_settings_screen"
android:title="@string/cellular_security_settings_title">
<PreferenceCategory
android:key="cellular_security_notifications_category"
android:title="@string/cellular_security_notifications"
settings:controller="com.android.settings.network.CellularSecurityNotificationsDividerController">
<SwitchPreferenceCompat
android:key="cellular_security_notifications"
android:title="@string/cellular_security_notifications_controller_title"
android:summary="@string/cellular_security_notifications_controller_summary"
settings:controller=
"com.android.settings.network.CellularSecurityNotificationsPreferenceController"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/cellular_security_settings_encryption_title"
settings:controller="com.android.settings.network.CellularSecurityEncryptionDividerController">
<SwitchPreferenceCompat
android:key="require_cellular_encryption"
android:title="@string/require_cellular_encryption_title"
android:summary="@string/require_cellular_encryption_summary"
settings:controller=
"com.android.settings.network.telephony.NullAlgorithmsPreferenceController"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -118,6 +118,12 @@
android:summary="@string/content_capture_summary"
settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController"/>
<Preference
android:key="cellular_security_settings_privacy"
android:title="@string/cellular_security_title"
android:summary="@string/cellular_security_summary"
android:fragment="com.android.settings.network.telephony.CellularSecuritySettingsFragment"
settings:searchable="false"/>
</PreferenceCategory>
<!-- Security section. -->

View File

@@ -109,4 +109,11 @@
android:summary="@string/summary_placeholder"
android:order="25"
settings:controller="com.android.settings.network.AdaptiveConnectivityPreferenceController"/>
<Preference
android:key="cellular_security_network_internet"
android:title="@string/cellular_security_title"
android:summary="@string/cellular_security_summary"
android:order="30"
settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/>
</PreferenceScreen>

View File

@@ -348,6 +348,7 @@ public class Settings extends SettingsActivity {
/* empty */
}
public static class CellularSecuritySettingsActivity extends SettingsActivity { /* empty */ }
public static class SatelliteSettingActivity extends SettingsActivity { /* empty */ }
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }

View File

@@ -144,6 +144,7 @@ import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.network.NetworkProviderSettings;
import com.android.settings.network.apn.ApnEditor;
import com.android.settings.network.apn.ApnSettings;
import com.android.settings.network.telephony.CellularSecuritySettingsFragment;
import com.android.settings.network.telephony.MobileNetworkSettings;
import com.android.settings.network.telephony.NetworkSelectSettings;
import com.android.settings.network.telephony.SatelliteSetting;
@@ -388,6 +389,7 @@ public class SettingsGateway {
ScreenTimeoutSettings.class.getName(),
ResetNetwork.class.getName(),
VibrationIntensitySettingsFragment.class.getName(),
CellularSecuritySettingsFragment.class.getName(),
};
public static final String[] SETTINGS_FOR_RESTRICTED = {

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.flags.Flags;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.telephony.CellularSecuritySettingsFragment;
/**
* {@link BasePreferenceController} for accessing Cellular Security settings from Network &
* Internet Settings menu.
*/
public class CellularSecurityPreferenceController extends BasePreferenceController {
private static final String LOG_TAG = "CellularSecurityPreferenceController";
private @Nullable TelephonyManager mTelephonyManager;
/**
* Class constructor of "Cellular Security" preference.
*
* @param context of settings
* @param prefKey assigned within UI entry of XML file
*/
public CellularSecurityPreferenceController(@NonNull Context context, @NonNull String prefKey) {
super(context, prefKey);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
}
@Override
public int getAvailabilityStatus() {
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|| !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mTelephonyManager == null) {
Log.w(LOG_TAG, "Telephony manager not yet initialized");
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
boolean isNullCipherDisablementAvailable = false;
boolean areCellSecNotificationsAvailable = false;
try {
mTelephonyManager.isNullCipherAndIntegrityPreferenceEnabled();
isNullCipherDisablementAvailable = true; // true because it doesn't throw an exception,
// we don't want the value of
// isNullCipherAndIntegrityEnabled()
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Null cipher enablement is unsupported, hiding divider: "
+ e.getMessage());
} catch (Exception e) {
Log.e(LOG_TAG,
"Failed isNullCipherAndIntegrityEnabled. Setting availability to "
+ "CONDITIONALLY_UNAVAILABLE. Exception: "
+ e.getMessage());
}
try {
// Must call both APIs, as we can't use the combined toggle if both aren't available
areNotificationsEnabled();
areCellSecNotificationsAvailable = true; // true because it doesn't throw an exception
// and we don't want the value of
// areNotificationsEnabled()
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Cellular security notifications are unsupported, hiding divider: "
+ e.getMessage());
}
if (isNullCipherDisablementAvailable || areCellSecNotificationsAvailable) {
return AVAILABLE;
} else {
return UNSUPPORTED_ON_DEVICE;
}
}
@Override
public boolean handlePreferenceTreeClick(@NonNull Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return super.handlePreferenceTreeClick(preference);
}
boolean isSafetyCenterSupported = isSafetyCenterSupported();
if (isSafetyCenterSupported) {
Intent safetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
"AndroidCellularNetworkSecuritySources");
mContext.startActivity(safetyCenterIntent);
} else {
final Bundle bundle = new Bundle();
bundle.putString(CellularSecuritySettingsFragment.KEY_CELLULAR_SECURITY_PREFERENCE, "");
new SubSettingLauncher(mContext)
.setDestination(CellularSecuritySettingsFragment.class.getName())
.setArguments(bundle)
.setSourceMetricsCategory(SettingsEnums.CELLULAR_SECURITY_SETTINGS)
.launch();
}
return true;
}
@VisibleForTesting
protected boolean isSafetyCenterSupported() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return false;
}
SafetyCenterManager safetyCenterManager = mContext.getSystemService(
SafetyCenterManager.class);
if (safetyCenterManager == null) {
return false;
}
return safetyCenterManager.isSafetyCenterEnabled();
}
@VisibleForTesting
protected boolean areNotificationsEnabled() {
if (mTelephonyManager == null) {
Log.w(LOG_TAG, "Telephony manager not yet initialized");
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
return mTelephonyManager.isNullCipherNotificationsEnabled()
&& mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.settings.core.BasePreferenceController;
/**
* {@link BasePreferenceController} for visibility of Encryption divider on Cellular Security
* settings page.
*/
public class CellularSecurityEncryptionDividerController extends
BasePreferenceController {
private static final String LOG_TAG = "CellularSecurityEncryptionDividerController";
private TelephonyManager mTelephonyManager;
protected final FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
/**
* Class constructor of "Cellular Security" preference.
*
* @param context of settings
* @param prefKey assigned within UI entry of XML file
*/
public CellularSecurityEncryptionDividerController(
@NonNull Context context, @NonNull String prefKey) {
super(context, prefKey);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
/**
* Initialization.
*/
public CellularSecurityEncryptionDividerController init() {
return this;
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
}
@Override
public int getAvailabilityStatus() {
if (mTelephonyManager == null) {
Log.w(LOG_TAG,
"Telephony manager not yet initialized. Marking availability as "
+ "CONDITIONALLY_UNAVAILABLE");
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
return CONDITIONALLY_UNAVAILABLE;
}
try {
mTelephonyManager.isNullCipherAndIntegrityPreferenceEnabled();
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Null cipher enablement is unsupported, hiding divider: "
+ e.getMessage());
return UNSUPPORTED_ON_DEVICE;
} catch (Exception e) {
Log.e(LOG_TAG,
"Failed isNullCipherAndIntegrityEnabled. Setting availability to "
+ "CONDITIONALLY_UNAVAILABLE. Exception: "
+ e.getMessage());
return CONDITIONALLY_UNAVAILABLE;
}
return AVAILABLE;
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import android.content.Context;
import android.os.Build;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.flags.Flags;
import com.android.settings.core.BasePreferenceController;
/**
* {@link BasePreferenceController} for visibility of Notifications divider on Cellular Security
* settings page.
*/
public class CellularSecurityNotificationsDividerController extends
BasePreferenceController {
private static final String LOG_TAG = "CellularSecurityNotificationsDividerController";
private TelephonyManager mTelephonyManager;
@VisibleForTesting
protected SafetyCenterManager mSafetyCenterManager;
/**
* Class constructor of "Cellular Security" preference.
*
* @param context of settings
* @param prefKey assigned within UI entry of XML file
*/
public CellularSecurityNotificationsDividerController(
@NonNull Context context, @NonNull String prefKey) {
super(context, prefKey);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
mSafetyCenterManager = mContext.getSystemService(SafetyCenterManager.class);
}
/**
* Initialization.
*/
public CellularSecurityNotificationsDividerController init() {
return this;
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
}
@Override
public int getAvailabilityStatus() {
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|| !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return UNSUPPORTED_ON_DEVICE;
}
if (!isSafetyCenterSupported()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mTelephonyManager == null) {
Log.w(LOG_TAG, "Telephony manager not yet initialized");
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
// Checking for hardware support, i.e. IRadio AIDL version must be >= 2.2
try {
// Must call both APIs, as we can't use the combined toggle if both aren't available
areNotificationsEnabled();
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Cellular security notifications are unsupported, hiding divider: "
+ e.getMessage());
return UNSUPPORTED_ON_DEVICE;
}
return AVAILABLE;
}
@VisibleForTesting
protected boolean areNotificationsEnabled() {
return mTelephonyManager.isNullCipherNotificationsEnabled()
&& mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
}
protected boolean isSafetyCenterSupported() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return false;
}
mSafetyCenterManager = mContext.getSystemService(
SafetyCenterManager.class);
if (mSafetyCenterManager == null) {
return false;
}
return mSafetyCenterManager.isSafetyCenterEnabled();
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import android.content.Context;
import android.os.Build;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.flags.Flags;
/**
* {@link TelephonyTogglePreferenceController} for accessing Cellular Security settings through
* Safety Center.
*/
public class CellularSecurityNotificationsPreferenceController extends
TelephonyTogglePreferenceController {
private static final String LOG_TAG = "CellularSecurityNotificationsPreferenceController";
private TelephonyManager mTelephonyManager;
@VisibleForTesting
protected SafetyCenterManager mSafetyCenterManager;
/**
* Class constructor of "Cellular Security" preference.
*
* @param context of settings
* @param prefKey assigned within UI entry of XML file
*/
public CellularSecurityNotificationsPreferenceController(
@NonNull Context context, @NonNull String prefKey) {
super(context, prefKey);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
mSafetyCenterManager = mContext.getSystemService(SafetyCenterManager.class);
}
/**
* Initialization based on a given subscription id.
*
* @param subId is the subscription id
* @return this instance after initialization
*/
public CellularSecurityNotificationsPreferenceController init(@NonNull int subId) {
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
.createForSubscriptionId(subId);
return this;
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
}
@Override
public int getAvailabilityStatus(int subId) {
if (!isSafetyCenterSupported()) {
return UNSUPPORTED_ON_DEVICE;
}
if (!areFlagsEnabled()) {
return UNSUPPORTED_ON_DEVICE;
}
if (mTelephonyManager == null) {
Log.w(LOG_TAG, "Telephony manager not yet initialized");
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
// Checking for hardware support, i.e. IRadio AIDL version must be >= 2.2
try {
areNotificationsEnabled();
} catch (UnsupportedOperationException e) {
Log.i(LOG_TAG, "Cellular security notifications are unsupported: " + e.getMessage());
return UNSUPPORTED_ON_DEVICE;
}
return AVAILABLE;
}
/**
* Return {@code true} if cellular security notifications are on
*
* <p><b>NOTE:</b> This method returns the active state of the preference controller and is not
* the parameter passed into {@link #setChecked(boolean)}, which is instead the requested future
* state.
*/
@Override
public boolean isChecked() {
if (!areFlagsEnabled()) {
return false;
}
try {
// Note: the default behavior for this toggle is disabled (as the underlying
// TelephonyManager APIs are disabled by default)
return areNotificationsEnabled();
} catch (Exception e) {
Log.e(LOG_TAG,
"Failed isNullCipherNotificationsEnabled and "
+ "isCellularIdentifierDisclosureNotificationsEnabled."
+ "Defaulting toggle to checked = true. Exception: "
+ e.getMessage());
return false;
}
}
/**
* Called when a user preference changes on the toggle. We pass this info on to the Telephony
* Framework so that the modem can be updated with the user's preference.
*
* <p>See {@link com.android.settings.core.TogglePreferenceController#setChecked(boolean)} for
* details.
*
* @param isChecked The toggle value that we're being requested to enforce. A value of {@code
* true} denotes that both (1) null cipher/integrity notifications, and
* (2) IMSI disclosure notifications will be enabled by the modem after this
* function completes, if they are not already.
*/
@Override
public boolean setChecked(boolean isChecked) {
if (isChecked) {
Log.i(LOG_TAG, "Enabling cellular security notifications.");
} else {
Log.i(LOG_TAG, "Disabling cellular security notifications.");
}
// Check flag status
if (!areFlagsEnabled()) {
return false;
}
try {
setNotifications(isChecked);
} catch (Exception e) {
Log.e(LOG_TAG,
"Failed setCellularIdentifierDisclosureNotificationEnabled or "
+ " setNullCipherNotificationsEnabled. Setting not updated. Exception: "
+ e.getMessage());
// Reset to defaults so we don't end up in an inconsistent state
setNotifications(!isChecked);
return false;
}
return true;
}
private void setNotifications(boolean isChecked) {
mTelephonyManager.setEnableCellularIdentifierDisclosureNotifications(isChecked);
mTelephonyManager.setNullCipherNotificationsEnabled(isChecked);
}
private boolean areNotificationsEnabled() {
return mTelephonyManager.isNullCipherNotificationsEnabled()
&& mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled();
}
private boolean areFlagsEnabled() {
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|| !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return false;
}
return true;
}
protected boolean isSafetyCenterSupported() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return false;
}
mSafetyCenterManager = mContext.getSystemService(
SafetyCenterManager.class);
if (mSafetyCenterManager == null) {
return false;
}
return mSafetyCenterManager.isSafetyCenterEnabled();
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
/**
* Cellular Security features (insecure network notifications, network security controls, etc)
*/
@SearchIndexable
public class CellularSecuritySettingsFragment extends DashboardFragment {
private static final String TAG = "CellularSecuritySettingsFragment";
public static final String KEY_CELLULAR_SECURITY_PREFERENCE = "cellular_security";
@Override
public int getMetricsCategory() {
return SettingsEnums.CELLULAR_SECURITY_SETTINGS;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.cellular_security;
}
@Override
public void onCreatePreferences(Bundle bundle, String rootKey) {
super.onCreatePreferences(bundle, rootKey);
setPreferencesFromResource(R.xml.cellular_security, rootKey);
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.cellular_security);
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.platform.test.flag.junit.SetFlagsRule;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.telephony.flags.Flags;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public final class CellularSecurityPreferenceControllerTest {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private TelephonyManager mTelephonyManager;
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private static final String PREF_KEY = "cellular_security_pref_controller_test";
private Context mContext;
private CellularSecurityPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// Tests must be skipped if these conditions aren't met as they cannot be mocked
Assume.assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU);
SafetyCenterManager mSafetyCenterManager = InstrumentationRegistry.getInstrumentation()
.getContext().getSystemService(SafetyCenterManager.class);
Assume.assumeTrue(mSafetyCenterManager != null);
Assume.assumeTrue(mSafetyCenterManager.isSafetyCenterEnabled());
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
doNothing().when(mContext).startActivity(any(Intent.class));
mController = new CellularSecurityPreferenceController(mContext, PREF_KEY);
mPreference = spy(new Preference(mContext));
mPreference.setKey(PREF_KEY);
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
mPreferenceScreen.addPreference(mPreference);
}
@Test
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
// Enable telephony API flags for testing
enableFlags(true);
// Hardware support is enabled
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(true).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
// Disable null cipher toggle API, should still be available
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherAndIntegrityPreferenceEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
// Enable null cipher toggle API, disable notifications API, should still be available
doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
// Enable telephony API flags for testing
enableFlags(true);
// Hardware support is disabled
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherAndIntegrityPreferenceEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_flagsDisabled_shouldReturnFalse() {
// Both flags disabled
enableFlags(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
// One flag is disabled
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void handlePreferenceTreeClick_safetyCenterSupported_shouldRedirectToSafetyCenter() {
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
boolean prefHandled = mController.handlePreferenceTreeClick(mPreference);
assertThat(prefHandled).isTrue();
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
}
private void enableFlags(boolean enabled) {
if (enabled) {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.telephony.TelephonyManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class CellularSecurityEncryptionDividerControllerTest {
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private static final String PREF_KEY = "cellular_security_encryption_divider_test";
private Context mContext;
private CellularSecurityEncryptionDividerController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
mController = new CellularSecurityEncryptionDividerController(mContext, PREF_KEY);
mPreference = spy(new Preference(mContext));
mPreference.setKey(PREF_KEY);
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
mPreferenceScreen.addPreference(mPreference);
}
@Test
public void getAvailabilityStatus_hardwareSupported_shouldReturnAvailable() {
doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_noHardwareSupport_shouldReturnUnsupported() {
// Hardware support is disabled
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherAndIntegrityPreferenceEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Build;
import android.platform.test.flag.junit.SetFlagsRule;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.telephony.flags.Flags;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class CellularSecurityNotificationsDividerControllerTest {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private TelephonyManager mTelephonyManager;
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private static final String PREF_KEY = "cellular_security_notifications_divider_test";
private Context mContext;
private CellularSecurityNotificationsDividerController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// Tests must be skipped if these conditions aren't met as they cannot be mocked
Assume.assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU);
SafetyCenterManager mSafetyCenterManager = InstrumentationRegistry.getInstrumentation()
.getContext().getSystemService(SafetyCenterManager.class);
Assume.assumeTrue(mSafetyCenterManager != null);
Assume.assumeTrue(mSafetyCenterManager.isSafetyCenterEnabled());
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
mController = new CellularSecurityNotificationsDividerController(mContext, PREF_KEY);
mPreference = spy(new Preference(mContext));
mPreference.setKey(PREF_KEY);
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
mPreferenceScreen.addPreference(mPreference);
}
@Test
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
// Enable telephony API flags for testing
enableFlags(true);
// Hardware support is enabled
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(true).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
// Enable telephony API flags for testing
enableFlags(true);
// Hardware support is disabled
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_flagsDisabled_shouldReturnFalse() {
// Both flags disabled
enableFlags(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
// One flag is disabled
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
private void enableFlags(boolean enabled) {
if (enabled) {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}

View File

@@ -0,0 +1,247 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network.telephony;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Build;
import android.platform.test.flag.junit.SetFlagsRule;
import android.safetycenter.SafetyCenterManager;
import android.telephony.TelephonyManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.telephony.flags.Flags;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class CellularSecurityNotificationsPreferenceControllerTest {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private TelephonyManager mTelephonyManager;
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private static final String PREF_KEY = "cellular_security_notifications_pref_controller_test";
private Context mContext;
private CellularSecurityNotificationsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// Tests must be skipped if these conditions aren't met as they cannot be mocked
Assume.assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU);
SafetyCenterManager mSafetyCenterManager = InstrumentationRegistry.getInstrumentation()
.getContext().getSystemService(SafetyCenterManager.class);
Assume.assumeTrue(mSafetyCenterManager != null);
Assume.assumeTrue(mSafetyCenterManager.isSafetyCenterEnabled());
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
mController = new CellularSecurityNotificationsPreferenceController(mContext, PREF_KEY);
mPreference = spy(new Preference(mContext));
mPreference.setKey(PREF_KEY);
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
mPreferenceScreen.addPreference(mPreference);
}
@Test
public void getAvailabilityStatus_hardwareSupported_shouldReturnTrue() {
// All flags enabled
enableFlags(true);
// Hardware support is enabled
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(true).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_noHardwareSupport_shouldReturnFalse() {
// All flags enabled
enableFlags(true);
// Hardware support is disabled
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_flagsDisabled_shouldReturnFalse() {
// All flags disabled
enableFlags(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
// One flag is disabled
enableFlags(true);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void setChecked_flagsDisabled_shouldReturnFalse() {
// Flags disabled
enableFlags(false);
// Hardware support is enabled
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(true);
doNothing().when(mTelephonyManager)
.setEnableCellularIdentifierDisclosureNotifications(true);
assertThat(mController.setChecked(false)).isFalse();
assertThat(mController.setChecked(true)).isFalse();
// Enable 1 flag, make sure it still fails
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
assertThat(mController.setChecked(false)).isFalse();
assertThat(mController.setChecked(true)).isFalse();
}
@Test
public void setChecked_hardwareDisabled_shouldReturnFalse() {
// Flags disabled
enableFlags(false);
// Hardware support is enabled
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(true);
doNothing().when(mTelephonyManager)
.setEnableCellularIdentifierDisclosureNotifications(true);
assertThat(mController.setChecked(true)).isFalse();
// Hardware support is enabled, called with false
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(false);
doNothing().when(mTelephonyManager)
.setEnableCellularIdentifierDisclosureNotifications(false);
assertThat(mController.setChecked(false)).isFalse();
}
@Test
public void setChecked_shouldReturnTrue() {
enableFlags(true);
// Hardware support is enabled, enabling the feature
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(true);
doNothing().when(mTelephonyManager)
.setEnableCellularIdentifierDisclosureNotifications(true);
assertThat(mController.setChecked(true)).isTrue();
// Hardware support is enabled, disabling the feature
doNothing().when(mTelephonyManager).setNullCipherNotificationsEnabled(false);
doNothing().when(mTelephonyManager)
.setEnableCellularIdentifierDisclosureNotifications(false);
assertThat(mController.setChecked(false)).isTrue();
}
@Test
public void isChecked_shouldReturnTrue() {
// Hardware support is enabled
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(true).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_flagsDisabled_shouldReturnFalse() {
enableFlags(false);
// Hardware support is enabled
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(true).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_hardwareUnsupported_shouldReturnFalse() {
enableFlags(true);
// Hardware support is disabled
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isNullCipherNotificationsEnabled();
doThrow(new UnsupportedOperationException("test")).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_notificationsDisabled_shouldReturnFalse() {
enableFlags(true);
// Hardware support is enabled, but APIs are disabled
doReturn(false).when(mTelephonyManager).isNullCipherNotificationsEnabled();
doReturn(false).when(mTelephonyManager)
.isCellularIdentifierDisclosureNotificationsEnabled();
assertThat(mController.isChecked()).isFalse();
// Enable 1 API, should still return false
doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
assertThat(mController.isChecked()).isFalse();
}
private void enableFlags(boolean enabled) {
if (enabled) {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}