blob: aafff62d26ed6062a21893864133ebc90bdc341c [file]
/*
* Copyright (C) 2026 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.security;
import android.content.Context;
import android.os.Bundle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceCategory;
import com.android.settings.R;
import com.android.settings.network.telephony.ConvertToEsimPreferenceController;
import com.android.settingslib.widget.IntroPreference;
import java.util.List;
/**
* Fragment for showing the PrimarySwitchPreference toggle for toggling SIM protection
* (in general) on/off.
*/
public class ProtectSimPrimaryScreenFragment extends BaseSimPinFragment {
// Key of the IntroPreference preference for the first active slot.
private static final String FIRST_SLOT_HEADER = "first_active_slot_intro";
// Key of the IntroPreference preference for the second active slot.
private static final String SECOND_SLOT_HEADER = "second_active_slot_intro";
private static final String FIRST_SLOT_CATEGORY = "category_first_sim_card_slot";
private static final String SECOND_SLOT_CATEGORY = "category_second_sim_card_slot";
// There are multiple controllers for changing the SIM PIN preferences - one for each slot.
private List<ChangeSimPinPreferenceController> mChangePinControllers;
// There are multiple SIM PIN toggle controllers - one for each slot and potentially multiple
// for a given slot, to handle manual and automatic PIN management modes.
private List<SimPinProtectionToggleController> mControllers;
private AutoManagedSimPinHelper mAutoManagedSimPinHelper;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mAutoManagedSimPinHelper = new AutoManagedSimPinHelper(context);
mControllers = useAll(SimPinProtectionToggleController.class);
for (SimPinProtectionToggleController controller : mControllers) {
controller.setFragment(this);
// If the controller's preference key indicates it's for the first slot, set slot
// index as 0. Otherwise, check if it's for the second slot, and set slot index as 1.
if (controller.getPreferenceKey().endsWith("_0")) {
controller.setSlotIndex(0);
} else if (controller.getPreferenceKey().endsWith("_1")) {
controller.setSlotIndex(1);
}
}
mChangePinControllers = useAll(ChangeSimPinPreferenceController.class);
for (ChangeSimPinPreferenceController controller : mChangePinControllers) {
controller.setFragment(this);
// If the controller's preference key indicates it's for the first slot, set slot
// index as 0. Otherwise, check if it's for the second slot, and set slot index as 1.
if (controller.getPreferenceKey().endsWith("_0")) {
controller.setSlotIndex(0);
} else if (controller.getPreferenceKey().endsWith("_1")) {
controller.setSlotIndex(1);
}
}
int subId = getSubId(context);
ConvertToEsimPreferenceController convertToEsimController =
use(ConvertToEsimPreferenceController.class);
if (convertToEsimController != null) {
convertToEsimController.init(subId, this);
}
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.automatic_sim_lock_protection_settings;
}
private static int getSubId(Context context) {
SubscriptionManager subscriptionManager =
context.getSystemService(SubscriptionManager.class);
final List<SubscriptionInfo> subInfoList = subscriptionManager
== null ? null : subscriptionManager.getActiveSubscriptionInfoList();
if (subInfoList == null) {
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
for (SubscriptionInfo subInfo : subInfoList) {
if (subInfo.isActive() && !subInfo.isEmbedded()) {
return subInfo.getSubscriptionId();
}
}
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
for (SimPinProtectionToggleController controller : mControllers) {
if (controller.isAvailable()) {
controller.storeEnrollmentState(outState);
}
}
}
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
for (SimPinProtectionToggleController controller : mControllers) {
if (controller.isAvailable()) {
controller.loadEnrollmentState(bundle);
}
}
}
@Override
public void onResume() {
super.onResume();
initFirstActiveSlotHeader();
initSecondActiveSlotHeader();
}
@VisibleForTesting
public void setAutoManagedSimPinHelperForTesting(AutoManagedSimPinHelper helper) {
mAutoManagedSimPinHelper = helper;
}
private void initSlotHeader(String categoryKey, String slotHeaderKey, int slotIndex) {
IntroPreference introPreference = findPreference(slotHeaderKey);
PreferenceCategory category = findPreference(categoryKey);
if (introPreference == null || category == null) {
Log.d(TAG, "Missing preference for category " + categoryKey + " or " + slotHeaderKey);
return;
}
int[] activeSlots = mAutoManagedSimPinHelper.getActiveSlots();
if (activeSlots == null || activeSlots.length < (slotIndex + 1)) {
introPreference.setVisible(false);
category.setVisible(false);
return;
}
int activeSlot = activeSlots[slotIndex];
SubscriptionManager subscriptionManager =
getContext().getSystemService(SubscriptionManager.class);
SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(
activeSlot);
if (info != null) {
introPreference.setTitle(info.getCarrierName());
} else {
introPreference.setTitle(
getContext().getResources().getString(R.string.sim_editor_title,
slotIndex + 1));
}
introPreference.setVisible(true);
category.setVisible(true);
}
private void initFirstActiveSlotHeader() {
initSlotHeader(FIRST_SLOT_CATEGORY, FIRST_SLOT_HEADER, 0);
}
private void initSecondActiveSlotHeader() {
initSlotHeader(SECOND_SLOT_CATEGORY, SECOND_SLOT_HEADER, 1);
}
}