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