1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.network; 18 19 import android.app.FragmentManager; 20 import android.os.Bundle; 21 import android.telephony.SubscriptionInfo; 22 import android.telephony.SubscriptionManager; 23 import android.util.Log; 24 25 import com.android.settings.SidecarFragment; 26 import com.android.settings.network.telephony.EuiccOperationSidecar; 27 28 /** 29 * This sidecar is responsible for switching to the removable slot. It disables the active eSIM 30 * profile before switching if there is one. 31 */ 32 public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar 33 implements SidecarFragment.Listener { 34 35 private static final String TAG = "DisableSubscriptionAndSwitchSlotSidecar"; 36 private static final String ACTION_DISABLE_SUBSCRIPTION_AND_SWITCH_SLOT = 37 "disable_subscription_and_switch_slot_sidecar"; 38 39 // Stateless members. 40 private SwitchToEuiccSubscriptionSidecar mSwitchToSubscriptionSidecar; 41 private SwitchSlotSidecar mSwitchSlotSidecar; 42 private int mPhysicalSlotId; 43 44 /** Returns a SwitchToRemovableSlotSidecar sidecar instance. */ get(FragmentManager fm)45 public static SwitchToRemovableSlotSidecar get(FragmentManager fm) { 46 return SidecarFragment.get(fm, TAG, SwitchToRemovableSlotSidecar.class, null /* args */); 47 } 48 49 @Override onCreate(Bundle savedInstanceState)50 public void onCreate(Bundle savedInstanceState) { 51 super.onCreate(savedInstanceState); 52 mSwitchToSubscriptionSidecar = 53 SwitchToEuiccSubscriptionSidecar.get(getChildFragmentManager()); 54 mSwitchSlotSidecar = SwitchSlotSidecar.get(getChildFragmentManager()); 55 } 56 57 @Override onResume()58 public void onResume() { 59 super.onResume(); 60 mSwitchToSubscriptionSidecar.addListener(this); 61 mSwitchSlotSidecar.addListener(this); 62 } 63 64 @Override onPause()65 public void onPause() { 66 mSwitchToSubscriptionSidecar.removeListener(this); 67 mSwitchSlotSidecar.removeListener(this); 68 super.onPause(); 69 } 70 71 @Override getReceiverAction()72 protected String getReceiverAction() { 73 return ACTION_DISABLE_SUBSCRIPTION_AND_SWITCH_SLOT; 74 } 75 76 @Override onStateChange(SidecarFragment fragment)77 public void onStateChange(SidecarFragment fragment) { 78 if (fragment == mSwitchToSubscriptionSidecar) { 79 onSwitchToSubscriptionSidecarStateChange(); 80 } else if (fragment == mSwitchSlotSidecar) { 81 onSwitchSlotSidecarStateChange(); 82 } else { 83 Log.wtf(TAG, "Received state change from a sidecar not expected."); 84 } 85 } 86 87 /** 88 * Starts switching to the removable slot. It disables the active eSIM profile before switching 89 * if there is one. 90 * 91 * @param physicalSlotId removable physical SIM slot ID. 92 */ run(int physicalSlotId)93 public void run(int physicalSlotId) { 94 mPhysicalSlotId = physicalSlotId; 95 SubscriptionManager subscriptionManager = 96 getContext().getSystemService(SubscriptionManager.class); 97 if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream() 98 .anyMatch(SubscriptionInfo::isEmbedded)) { 99 Log.i(TAG, "There is an active eSIM profile. Disable the profile first."); 100 // Use INVALID_SUBSCRIPTION_ID to disable the only active profile. 101 mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 102 } else { 103 Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot."); 104 mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId); 105 } 106 } 107 onSwitchToSubscriptionSidecarStateChange()108 private void onSwitchToSubscriptionSidecarStateChange() { 109 switch (mSwitchToSubscriptionSidecar.getState()) { 110 case State.SUCCESS: 111 mSwitchToSubscriptionSidecar.reset(); 112 Log.i( 113 TAG, 114 "Successfully disabled eSIM profile. Start to switch to Removable slot."); 115 mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId); 116 break; 117 case State.ERROR: 118 mSwitchToSubscriptionSidecar.reset(); 119 Log.i(TAG, "Failed to disable the active eSIM profile."); 120 setState(State.ERROR, Substate.UNUSED); 121 break; 122 } 123 } 124 onSwitchSlotSidecarStateChange()125 private void onSwitchSlotSidecarStateChange() { 126 switch (mSwitchSlotSidecar.getState()) { 127 case State.SUCCESS: 128 mSwitchSlotSidecar.reset(); 129 Log.i(TAG, "Successfully switched to removable slot."); 130 setState(State.SUCCESS, Substate.UNUSED); 131 break; 132 case State.ERROR: 133 mSwitchSlotSidecar.reset(); 134 Log.i(TAG, "Failed to switch to removable slot."); 135 setState(State.ERROR, Substate.UNUSED); 136 break; 137 } 138 } 139 } 140