| /* | |
| * 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); | |
| } | |
| } |