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