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