/* * Copyright (c) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.cdma; import java.util.concurrent.atomic.AtomicInteger; import com.android.internal.telephony.CommandsInterface; import android.content.Context; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; import android.provider.Settings; import android.telephony.Rlog; /** * Class that handles the CDMA subscription source changed events from RIL */ public class CdmaSubscriptionSourceManager extends Handler { static final String LOG_TAG = "CdmaSSM"; private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1; private static final int EVENT_GET_CDMA_SUBSCRIPTION_SOURCE = 2; private static final int EVENT_RADIO_ON = 3; private static final int EVENT_SUBSCRIPTION_STATUS_CHANGED = 4; // To know subscription is activated private static final int SUBSCRIPTION_ACTIVATED = 1; public static final int SUBSCRIPTION_SOURCE_UNKNOWN = -1; public static final int SUBSCRIPTION_FROM_RUIM = 0; /* CDMA subscription from RUIM */ public static final int SUBSCRIPTION_FROM_NV = 1; /* CDMA subscription from NV */ public static final int PREFERRED_CDMA_SUBSCRIPTION = SUBSCRIPTION_FROM_NV; private static CdmaSubscriptionSourceManager sInstance; private static final Object sReferenceCountMonitor = new Object(); private static int sReferenceCount = 0; // ***** Instance Variables private CommandsInterface mCi; private Context mContext; private RegistrantList mCdmaSubscriptionSourceChangedRegistrants = new RegistrantList(); // Type of CDMA subscription source private AtomicInteger mCdmaSubscriptionSource = new AtomicInteger(SUBSCRIPTION_FROM_NV); // Constructor private CdmaSubscriptionSourceManager(Context context, CommandsInterface ci) { mContext = context; mCi = ci; mCi.registerForCdmaSubscriptionChanged(this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); mCi.registerForOn(this, EVENT_RADIO_ON, null); int subscriptionSource = getDefault(context); log("cdmaSSM constructor: " + subscriptionSource); mCdmaSubscriptionSource.set(subscriptionSource); mCi.registerForSubscriptionStatusChanged(this, EVENT_SUBSCRIPTION_STATUS_CHANGED, null); } /** * This function creates a single instance of this class * * @return object of type CdmaSubscriptionSourceManager */ public static CdmaSubscriptionSourceManager getInstance(Context context, CommandsInterface ci, Handler h, int what, Object obj) { synchronized (sReferenceCountMonitor) { if (null == sInstance) { sInstance = new CdmaSubscriptionSourceManager(context, ci); } CdmaSubscriptionSourceManager.sReferenceCount++; } sInstance.registerForCdmaSubscriptionSourceChanged(h, what, obj); return sInstance; } /** * Unregisters for the registered event with RIL */ public void dispose(Handler h) { mCdmaSubscriptionSourceChangedRegistrants.remove(h); synchronized (sReferenceCountMonitor) { sReferenceCount--; if (sReferenceCount <= 0) { mCi.unregisterForCdmaSubscriptionChanged(this); mCi.unregisterForOn(this); mCi.unregisterForSubscriptionStatusChanged(this); sInstance = null; } } } /* * (non-Javadoc) * @see android.os.Handler#handleMessage(android.os.Message) */ @Override public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: case EVENT_GET_CDMA_SUBSCRIPTION_SOURCE: { log("CDMA_SUBSCRIPTION_SOURCE event = " + msg.what); ar = (AsyncResult) msg.obj; handleGetCdmaSubscriptionSource(ar); } break; case EVENT_RADIO_ON: { mCi.getCdmaSubscriptionSource(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_SOURCE)); } break; case EVENT_SUBSCRIPTION_STATUS_CHANGED: { log("EVENT_SUBSCRIPTION_STATUS_CHANGED"); ar = (AsyncResult)msg.obj; if (ar.exception == null) { int actStatus = ((int[])ar.result)[0]; log("actStatus = " + actStatus); if (actStatus == SUBSCRIPTION_ACTIVATED) { // Subscription Activated // In case of multi-SIM, framework should wait for the subscription ready // to send any request to RIL. Otherwise it will return failure. Rlog.v(LOG_TAG,"get Cdma Subscription Source"); mCi.getCdmaSubscriptionSource( obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_SOURCE)); } } else { logw("EVENT_SUBSCRIPTION_STATUS_CHANGED, Exception:" + ar.exception); } } break; default: super.handleMessage(msg); } } /** * Returns the current CDMA subscription source value * @return CDMA subscription source value */ public int getCdmaSubscriptionSource() { log("getcdmasubscriptionSource: " + mCdmaSubscriptionSource.get()); return mCdmaSubscriptionSource.get(); } /** * Gets the default CDMA subscription source * * @return Default CDMA subscription source from Settings DB if present. */ public static int getDefault(Context context) { // Get the default value from the Settings int subscriptionSource = Settings.Global.getInt(context.getContentResolver(), Settings.Global.CDMA_SUBSCRIPTION_MODE, PREFERRED_CDMA_SUBSCRIPTION); Rlog.d(LOG_TAG, "subscriptionSource from settings: " + subscriptionSource); return subscriptionSource; } /** * Clients automatically register for CDMA subscription source changed event * when they get an instance of this object. */ private void registerForCdmaSubscriptionSourceChanged(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); mCdmaSubscriptionSourceChangedRegistrants.add(r); } /** * Handles the call to get the subscription source * * @param ar AsyncResult object that contains the result of get CDMA * subscription source call */ private void handleGetCdmaSubscriptionSource(AsyncResult ar) { if ((ar.exception == null) && (ar.result != null)) { int newSubscriptionSource = ((int[]) ar.result)[0]; if (newSubscriptionSource != mCdmaSubscriptionSource.get()) { log("Subscription Source Changed : " + mCdmaSubscriptionSource + " >> " + newSubscriptionSource); mCdmaSubscriptionSource.set(newSubscriptionSource); // Notify registrants of the new CDMA subscription source mCdmaSubscriptionSourceChangedRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); } } else { // GET_CDMA_SUBSCRIPTION is returning Failure. Probably // because modem created GSM Phone. If modem created // GSMPhone, then PhoneProxy will trigger a change in // Phone objects and this object will be destroyed. logw("Unable to get CDMA Subscription Source, Exception: " + ar.exception + ", result: " + ar.result); } } private void log(String s) { Rlog.d(LOG_TAG, s); } private void logw(String s) { Rlog.w(LOG_TAG, s); } }