| /* |
| * Copyright (C) 2020 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.FragmentManager; |
| import android.os.Bundle; |
| import android.telephony.SubscriptionInfo; |
| import android.telephony.SubscriptionManager; |
| import android.util.Log; |
| |
| import com.android.settings.SidecarFragment; |
| import com.android.settings.network.telephony.EuiccOperationSidecar; |
| |
| /** |
| * This sidecar is responsible for switching to the removable slot. It disables the active eSIM |
| * profile before switching if there is one. |
| */ |
| public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar |
| implements SidecarFragment.Listener { |
| |
| private static final String TAG = "DisableSubscriptionAndSwitchSlotSidecar"; |
| private static final String ACTION_DISABLE_SUBSCRIPTION_AND_SWITCH_SLOT = |
| "disable_subscription_and_switch_slot_sidecar"; |
| |
| // Stateless members. |
| private SwitchToEuiccSubscriptionSidecar mSwitchToSubscriptionSidecar; |
| private SwitchSlotSidecar mSwitchSlotSidecar; |
| private int mPhysicalSlotId; |
| |
| /** Returns a SwitchToRemovableSlotSidecar sidecar instance. */ |
| public static SwitchToRemovableSlotSidecar get(FragmentManager fm) { |
| return SidecarFragment.get(fm, TAG, SwitchToRemovableSlotSidecar.class, null /* args */); |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| mSwitchToSubscriptionSidecar = |
| SwitchToEuiccSubscriptionSidecar.get(getChildFragmentManager()); |
| mSwitchSlotSidecar = SwitchSlotSidecar.get(getChildFragmentManager()); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| mSwitchToSubscriptionSidecar.addListener(this); |
| mSwitchSlotSidecar.addListener(this); |
| } |
| |
| @Override |
| public void onPause() { |
| mSwitchToSubscriptionSidecar.removeListener(this); |
| mSwitchSlotSidecar.removeListener(this); |
| super.onPause(); |
| } |
| |
| @Override |
| protected String getReceiverAction() { |
| return ACTION_DISABLE_SUBSCRIPTION_AND_SWITCH_SLOT; |
| } |
| |
| @Override |
| public void onStateChange(SidecarFragment fragment) { |
| if (fragment == mSwitchToSubscriptionSidecar) { |
| onSwitchToSubscriptionSidecarStateChange(); |
| } else if (fragment == mSwitchSlotSidecar) { |
| onSwitchSlotSidecarStateChange(); |
| } else { |
| Log.wtf(TAG, "Received state change from a sidecar not expected."); |
| } |
| } |
| |
| /** |
| * Starts switching to the removable slot. It disables the active eSIM profile before switching |
| * if there is one. |
| * |
| * @param physicalSlotId removable physical SIM slot ID. |
| */ |
| public void run(int physicalSlotId) { |
| mPhysicalSlotId = physicalSlotId; |
| SubscriptionManager subscriptionManager = |
| getContext().getSystemService(SubscriptionManager.class); |
| if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream() |
| .anyMatch(SubscriptionInfo::isEmbedded)) { |
| Log.i(TAG, "There is an active eSIM profile. Disable the profile first."); |
| // Use INVALID_SUBSCRIPTION_ID to disable the only active profile. |
| mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| } else { |
| Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot."); |
| mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId); |
| } |
| } |
| |
| private void onSwitchToSubscriptionSidecarStateChange() { |
| switch (mSwitchToSubscriptionSidecar.getState()) { |
| case State.SUCCESS: |
| mSwitchToSubscriptionSidecar.reset(); |
| Log.i( |
| TAG, |
| "Successfully disabled eSIM profile. Start to switch to Removable slot."); |
| mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId); |
| break; |
| case State.ERROR: |
| mSwitchToSubscriptionSidecar.reset(); |
| Log.i(TAG, "Failed to disable the active eSIM profile."); |
| setState(State.ERROR, Substate.UNUSED); |
| break; |
| } |
| } |
| |
| private void onSwitchSlotSidecarStateChange() { |
| switch (mSwitchSlotSidecar.getState()) { |
| case State.SUCCESS: |
| mSwitchSlotSidecar.reset(); |
| Log.i(TAG, "Successfully switched to removable slot."); |
| setState(State.SUCCESS, Substate.UNUSED); |
| break; |
| case State.ERROR: |
| mSwitchSlotSidecar.reset(); |
| Log.i(TAG, "Failed to switch to removable slot."); |
| setState(State.ERROR, Substate.UNUSED); |
| break; |
| } |
| } |
| } |