• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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