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