| /* |
| * 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.hardware.biometrics.BiometricPrompt; |
| import android.os.OutcomeReceiver; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.TelephonyManager; |
| import android.util.Log; |
| |
| import androidx.annotation.NonNull; |
| import androidx.annotation.Nullable; |
| import androidx.fragment.app.Fragment; |
| import androidx.preference.Preference; |
| import androidx.preference.PreferenceScreen; |
| |
| import com.android.settings.core.BasePreferenceController; |
| |
| /** |
| * Controller for showing the automatically-generated SIM PIN. Ensures that the user is |
| * authenticated before calling into the TelephonyManager for retrieving the SIM PIN. |
| */ |
| public class ShowAutoManagedSimPinController extends BasePreferenceController implements |
| Preference.OnPreferenceClickListener { |
| private static final String TAG = "AutoManagedSimPin"; |
| // The tag used for the DialogFragment's showNow method. |
| private static final String FRAGMENT_TAG = "PinShow"; |
| |
| private final SubscriptionManager mSubscriptionManager; |
| private TelephonyManager mTelephonyManager; |
| |
| private int mSubId; |
| |
| @Nullable |
| private Fragment mFragment; |
| |
| private Preference mPreference; |
| |
| private AutoManagedSimPinHelper mAutoManagedSimPinHelper; |
| |
| public ShowAutoManagedSimPinController(@NonNull Context context, |
| @NonNull String preferenceKey) { |
| super(context, preferenceKey); |
| mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); |
| mTelephonyManager = context.getSystemService(TelephonyManager.class); |
| mSubId = mSubscriptionManager.getEnabledSubscriptionId(0); |
| |
| mAutoManagedSimPinHelper = new AutoManagedSimPinHelper(mContext); |
| } |
| |
| @Override |
| public int getAvailabilityStatus() { |
| if (!android.security.Flags.autoSimPinManagement()) { |
| return CONDITIONALLY_UNAVAILABLE; |
| } |
| |
| if (!mAutoManagedSimPinHelper.isPinAutoManagedForSubscription(mSubId)) { |
| return DISABLED_DEPENDENT_SETTING; |
| } |
| |
| return AVAILABLE; |
| } |
| |
| @Override |
| public void displayPreference(PreferenceScreen screen) { |
| super.displayPreference(screen); |
| |
| mPreference = screen.findPreference(getPreferenceKey()); |
| mPreference.setOnPreferenceClickListener(this); |
| } |
| |
| @Override |
| public void updateState(Preference preference) { |
| super.updateState(preference); |
| |
| preference.setEnabled(mAutoManagedSimPinHelper.isPinAutoManagedForSubscription(mSubId)); |
| } |
| |
| @Override |
| public boolean onPreferenceClick(@NonNull Preference preference) { |
| showAuthenticationDialog(); |
| return true; |
| } |
| |
| public void setFragment(Fragment fragment) { |
| mFragment = fragment; |
| } |
| |
| private void showAuthenticationDialog() { |
| final BiometricPrompt.AuthenticationCallback authenticationCallback = |
| new BiometricPrompt.AuthenticationCallback() { |
| @Override |
| public void onAuthenticationSucceeded( |
| BiometricPrompt.AuthenticationResult result) { |
| Log.d(TAG, "Authentication succeeded, asking for PIN."); |
| getPlatformManagedPin(); |
| } |
| |
| @Override |
| public void onAuthenticationError(int errorCode, CharSequence errString) { |
| Log.w(TAG, "Authentication error for showing PIN, error code " |
| + errorCode + " message: " + errString); |
| } |
| }; |
| |
| mAutoManagedSimPinHelper.showAuthenticationPromptForCallback(authenticationCallback); |
| } |
| |
| private class GetAutoManagedPinReceiver implements |
| OutcomeReceiver<String, TelephonyManager.SimAutoPinManagementException> { |
| private GetAutoManagedPinReceiver() { |
| } |
| |
| @Override |
| public void onResult(String result) { |
| DisplaySimPinDialogFragment df = DisplaySimPinDialogFragment.newInstance(true, result); |
| |
| if (mFragment != null) { |
| df.showNow(mFragment.getChildFragmentManager(), FRAGMENT_TAG); |
| } |
| } |
| |
| @Override |
| public void onError(@NonNull TelephonyManager.SimAutoPinManagementException error) { |
| Log.w(TAG, "Failure getting PIN: " + error); |
| DisplaySimPinDialogFragment df = DisplaySimPinDialogFragment.newInstance(false, ""); |
| if (mFragment != null) { |
| df.showNow(mFragment.getChildFragmentManager(), FRAGMENT_TAG); |
| } |
| |
| OutcomeReceiver.super.onError(error); |
| } |
| } |
| |
| private void getPlatformManagedPin() { |
| mTelephonyManager.createForSubscriptionId(mSubId).getAutoManagedPinForSim( |
| mContext.getMainExecutor(), |
| new GetAutoManagedPinReceiver()); |
| } |
| } |