1 /* 2 * Copyright (c) 2011 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.internal.telephony.cdma; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.content.Context; 21 import android.os.AsyncResult; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.os.Registrant; 25 import android.os.RegistrantList; 26 import android.provider.Settings; 27 28 import com.android.internal.telephony.CommandsInterface; 29 import com.android.internal.telephony.Phone; 30 import com.android.telephony.Rlog; 31 32 import java.util.concurrent.atomic.AtomicInteger; 33 34 /** 35 * Class that handles the CDMA subscription source changed events from RIL 36 */ 37 public class CdmaSubscriptionSourceManager extends Handler { 38 static final String LOG_TAG = "CdmaSSM"; 39 private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1; 40 private static final int EVENT_GET_CDMA_SUBSCRIPTION_SOURCE = 2; 41 private static final int EVENT_RADIO_ON = 3; 42 private static final int EVENT_SUBSCRIPTION_STATUS_CHANGED = 4; 43 44 // To know subscription is activated 45 private static final int SUBSCRIPTION_ACTIVATED = 1; 46 47 public static final int SUBSCRIPTION_SOURCE_UNKNOWN = -1; 48 public static final int SUBSCRIPTION_FROM_RUIM = 0; /* CDMA subscription from RUIM */ 49 public static final int SUBSCRIPTION_FROM_NV = 1; /* CDMA subscription from NV */ 50 51 private static CdmaSubscriptionSourceManager sInstance; 52 private static final Object sReferenceCountMonitor = new Object(); 53 private static int sReferenceCount = 0; 54 55 // ***** Instance Variables 56 private CommandsInterface mCi; 57 private RegistrantList mCdmaSubscriptionSourceChangedRegistrants = new RegistrantList(); 58 59 // Type of CDMA subscription source 60 private AtomicInteger mCdmaSubscriptionSource = 61 new AtomicInteger(Phone.PREFERRED_CDMA_SUBSCRIPTION); 62 63 // Constructor CdmaSubscriptionSourceManager(Context context, CommandsInterface ci)64 private CdmaSubscriptionSourceManager(Context context, CommandsInterface ci) { 65 mCi = ci; 66 mCi.registerForCdmaSubscriptionChanged(this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 67 mCi.registerForOn(this, EVENT_RADIO_ON, null); 68 int subscriptionSource = getDefault(context); 69 log("cdmaSSM constructor: " + subscriptionSource); 70 mCdmaSubscriptionSource.set(subscriptionSource); 71 mCi.registerForSubscriptionStatusChanged(this, EVENT_SUBSCRIPTION_STATUS_CHANGED, null); 72 } 73 74 /** 75 * This function creates a single instance of this class 76 * 77 * @return object of type CdmaSubscriptionSourceManager 78 */ 79 @UnsupportedAppUsage getInstance(Context context, CommandsInterface ci, Handler h, int what, Object obj)80 public static CdmaSubscriptionSourceManager getInstance(Context context, 81 CommandsInterface ci, Handler h, int what, Object obj) { 82 synchronized (sReferenceCountMonitor) { 83 if (null == sInstance) { 84 sInstance = new CdmaSubscriptionSourceManager(context, ci); 85 } 86 CdmaSubscriptionSourceManager.sReferenceCount++; 87 } 88 sInstance.registerForCdmaSubscriptionSourceChanged(h, what, obj); 89 return sInstance; 90 } 91 92 /** 93 * Unregisters for the registered event with RIL 94 */ dispose(Handler h)95 public void dispose(Handler h) { 96 mCdmaSubscriptionSourceChangedRegistrants.remove(h); 97 synchronized (sReferenceCountMonitor) { 98 sReferenceCount--; 99 if (sReferenceCount <= 0) { 100 mCi.unregisterForCdmaSubscriptionChanged(this); 101 mCi.unregisterForOn(this); 102 mCi.unregisterForSubscriptionStatusChanged(this); 103 sInstance = null; 104 } 105 } 106 } 107 108 /* 109 * (non-Javadoc) 110 * @see android.os.Handler#handleMessage(android.os.Message) 111 */ 112 @Override handleMessage(Message msg)113 public void handleMessage(Message msg) { 114 AsyncResult ar; 115 switch (msg.what) { 116 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: 117 case EVENT_GET_CDMA_SUBSCRIPTION_SOURCE: 118 { 119 log("CDMA_SUBSCRIPTION_SOURCE event = " + msg.what); 120 ar = (AsyncResult) msg.obj; 121 handleGetCdmaSubscriptionSource(ar); 122 } 123 break; 124 case EVENT_RADIO_ON: { 125 mCi.getCdmaSubscriptionSource(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_SOURCE)); 126 } 127 break; 128 case EVENT_SUBSCRIPTION_STATUS_CHANGED: { 129 log("EVENT_SUBSCRIPTION_STATUS_CHANGED"); 130 ar = (AsyncResult)msg.obj; 131 if (ar.exception == null) { 132 int actStatus = ((int[])ar.result)[0]; 133 log("actStatus = " + actStatus); 134 if (actStatus == SUBSCRIPTION_ACTIVATED) { // Subscription Activated 135 // In case of multi-SIM, framework should wait for the subscription ready 136 // to send any request to RIL. Otherwise it will return failure. 137 Rlog.v(LOG_TAG,"get Cdma Subscription Source"); 138 mCi.getCdmaSubscriptionSource( 139 obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_SOURCE)); 140 } 141 } else { 142 logw("EVENT_SUBSCRIPTION_STATUS_CHANGED, Exception:" + ar.exception); 143 } 144 } 145 break; 146 default: 147 super.handleMessage(msg); 148 } 149 } 150 151 /** 152 * Returns the current CDMA subscription source value 153 * @return CDMA subscription source value 154 */ 155 @UnsupportedAppUsage getCdmaSubscriptionSource()156 public int getCdmaSubscriptionSource() { 157 log("getcdmasubscriptionSource: " + mCdmaSubscriptionSource.get()); 158 return mCdmaSubscriptionSource.get(); 159 } 160 161 /** 162 * Gets the default CDMA subscription source 163 * 164 * @return Default CDMA subscription source from Settings DB if present. 165 */ getDefault(Context context)166 public static int getDefault(Context context) { 167 // Get the default value from the Settings 168 int subscriptionSource = Settings.Global.getInt(context.getContentResolver(), 169 Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION); 170 Rlog.d(LOG_TAG, "subscriptionSource from settings: " + subscriptionSource); 171 return subscriptionSource; 172 } 173 174 /** 175 * Clients automatically register for CDMA subscription source changed event 176 * when they get an instance of this object. 177 */ registerForCdmaSubscriptionSourceChanged(Handler h, int what, Object obj)178 private void registerForCdmaSubscriptionSourceChanged(Handler h, int what, Object obj) { 179 Registrant r = new Registrant (h, what, obj); 180 mCdmaSubscriptionSourceChangedRegistrants.add(r); 181 } 182 183 /** 184 * Handles the call to get the subscription source 185 * 186 * @param ar AsyncResult object that contains the result of get CDMA 187 * subscription source call 188 */ handleGetCdmaSubscriptionSource(AsyncResult ar)189 private void handleGetCdmaSubscriptionSource(AsyncResult ar) { 190 if ((ar.exception == null) && (ar.result != null)) { 191 int newSubscriptionSource = ((int[]) ar.result)[0]; 192 193 if (newSubscriptionSource != mCdmaSubscriptionSource.get()) { 194 log("Subscription Source Changed : " + mCdmaSubscriptionSource + " >> " 195 + newSubscriptionSource); 196 mCdmaSubscriptionSource.set(newSubscriptionSource); 197 198 // Notify registrants of the new CDMA subscription source 199 mCdmaSubscriptionSourceChangedRegistrants.notifyRegistrants(new AsyncResult(null, 200 null, null)); 201 } 202 } else { 203 // GET_CDMA_SUBSCRIPTION is returning Failure. Probably because modem created GSM Phone. 204 logw("Unable to get CDMA Subscription Source, Exception: " + ar.exception 205 + ", result: " + ar.result); 206 } 207 } 208 log(String s)209 private void log(String s) { 210 Rlog.d(LOG_TAG, s); 211 } 212 logw(String s)213 private void logw(String s) { 214 Rlog.w(LOG_TAG, s); 215 } 216 217 } 218