• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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;
18 
19 import android.os.AsyncResult;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.os.Registrant;
23 import android.os.RegistrantList;
24 import android.telephony.ServiceState;
25 import android.telephony.SignalStrength;
26 
27 /**
28  * {@hide}
29  */
30 public abstract class ServiceStateTracker extends Handler {
31 
32     protected CommandsInterface cm;
33 
34     public ServiceState ss;
35     protected ServiceState newSS;
36 
37     public SignalStrength mSignalStrength;
38 
39     // TODO - this should not be public
40     public RestrictedState mRestrictedState = new RestrictedState();
41 
42     /* The otaspMode passed to PhoneStateListener#onOtaspChanged */
43     static public final int OTASP_UNINITIALIZED = 0;
44     static public final int OTASP_UNKNOWN = 1;
45     static public final int OTASP_NEEDED = 2;
46     static public final int OTASP_NOT_NEEDED = 3;
47 
48     /**
49      * A unique identifier to track requests associated with a poll
50      * and ignore stale responses.  The value is a count-down of
51      * expected responses in this pollingContext.
52      */
53     protected int[] pollingContext;
54     protected boolean mDesiredPowerState;
55 
56     /**
57      *  Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
58      */
59     protected int mRadioTechnology = 0;
60     protected int mNewRadioTechnology = 0;
61 
62     /**
63      * By default, strength polling is enabled.  However, if we're
64      * getting unsolicited signal strength updates from the radio, set
65      * value to true and don't bother polling any more.
66      */
67     protected boolean dontPollSignalStrength = false;
68 
69     protected RegistrantList mRoamingOnRegistrants = new RegistrantList();
70     protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
71     protected RegistrantList mAttachedRegistrants = new RegistrantList();
72     protected RegistrantList mDetachedRegistrants = new RegistrantList();
73     protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
74     protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
75     protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
76 
77     /* Radio power off pending flag and tag counter */
78     private boolean mPendingRadioPowerOffAfterDataOff = false;
79     private int mPendingRadioPowerOffAfterDataOffTag = 0;
80 
81     protected  static final boolean DBG = true;
82 
83     /** Signal strength poll rate. */
84     protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
85 
86     /** Waiting period before recheck gprs and voice registration. */
87     public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
88 
89     /** GSM events */
90     protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
91     protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
92     protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
93     protected static final int EVENT_POLL_STATE_REGISTRATION           = 4;
94     protected static final int EVENT_POLL_STATE_GPRS                   = 5;
95     protected static final int EVENT_POLL_STATE_OPERATOR               = 6;
96     protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
97     protected static final int EVENT_NITZ_TIME                         = 11;
98     protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
99     protected static final int EVENT_RADIO_AVAILABLE                   = 13;
100     protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
101     protected static final int EVENT_GET_LOC_DONE                      = 15;
102     protected static final int EVENT_SIM_RECORDS_LOADED                = 16;
103     protected static final int EVENT_SIM_READY                         = 17;
104     protected static final int EVENT_LOCATION_UPDATES_ENABLED          = 18;
105     protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE        = 19;
106     protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE        = 20;
107     protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE      = 21;
108     protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
109     protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
110 
111     /** CDMA events */
112     protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA      = 24;
113     protected static final int EVENT_POLL_STATE_OPERATOR_CDMA          = 25;
114     protected static final int EVENT_RUIM_READY                        = 26;
115     protected static final int EVENT_RUIM_RECORDS_LOADED               = 27;
116     protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA         = 28;
117     protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA          = 29;
118     protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA        = 30;
119     protected static final int EVENT_GET_LOC_DONE_CDMA                 = 31;
120     protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA       = 32;
121     protected static final int EVENT_NV_LOADED                         = 33;
122     protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION      = 34;
123     protected static final int EVENT_NV_READY                          = 35;
124     protected static final int EVENT_ERI_FILE_LOADED                   = 36;
125     protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE       = 37;
126     protected static final int EVENT_SET_RADIO_POWER_OFF               = 38;
127 
128     protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
129 
130     /**
131      * List of ISO codes for countries that can have an offset of
132      * GMT+0 when not in daylight savings time.  This ignores some
133      * small places such as the Canary Islands (Spain) and
134      * Danmarkshavn (Denmark).  The list must be sorted by code.
135     */
136     protected static final String[] GMT_COUNTRY_CODES = {
137         "bf", // Burkina Faso
138         "ci", // Cote d'Ivoire
139         "eh", // Western Sahara
140         "fo", // Faroe Islands, Denmark
141         "gh", // Ghana
142         "gm", // Gambia
143         "gn", // Guinea
144         "gw", // Guinea Bissau
145         "ie", // Ireland
146         "lr", // Liberia
147         "is", // Iceland
148         "ma", // Morocco
149         "ml", // Mali
150         "mr", // Mauritania
151         "pt", // Portugal
152         "sl", // Sierra Leone
153         "sn", // Senegal
154         "st", // Sao Tome and Principe
155         "tg", // Togo
156         "uk", // U.K
157     };
158 
159     /** Reason for registration denial. */
160     protected static final String REGISTRATION_DENIED_GEN  = "General";
161     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
162 
ServiceStateTracker()163     public ServiceStateTracker() {
164     }
165 
getDesiredPowerState()166     public boolean getDesiredPowerState() {
167         return mDesiredPowerState;
168     }
169 
170     /**
171      * Registration point for combined roaming on
172      * combined roaming is true when roaming is true and ONS differs SPN
173      *
174      * @param h handler to notify
175      * @param what what code of message when delivered
176      * @param obj placed in Message.obj
177      */
registerForRoamingOn(Handler h, int what, Object obj)178     public  void registerForRoamingOn(Handler h, int what, Object obj) {
179         Registrant r = new Registrant(h, what, obj);
180         mRoamingOnRegistrants.add(r);
181 
182         if (ss.getRoaming()) {
183             r.notifyRegistrant();
184         }
185     }
186 
unregisterForRoamingOn(Handler h)187     public  void unregisterForRoamingOn(Handler h) {
188         mRoamingOnRegistrants.remove(h);
189     }
190 
191     /**
192      * Registration point for combined roaming off
193      * combined roaming is true when roaming is true and ONS differs SPN
194      *
195      * @param h handler to notify
196      * @param what what code of message when delivered
197      * @param obj placed in Message.obj
198      */
registerForRoamingOff(Handler h, int what, Object obj)199     public  void registerForRoamingOff(Handler h, int what, Object obj) {
200         Registrant r = new Registrant(h, what, obj);
201         mRoamingOffRegistrants.add(r);
202 
203         if (!ss.getRoaming()) {
204             r.notifyRegistrant();
205         }
206     }
207 
unregisterForRoamingOff(Handler h)208     public  void unregisterForRoamingOff(Handler h) {
209         mRoamingOffRegistrants.remove(h);
210     }
211 
212     /**
213      * Re-register network by toggling preferred network type.
214      * This is a work-around to deregister and register network since there is
215      * no ril api to set COPS=2 (deregister) only.
216      *
217      * @param onComplete is dispatched when this is complete.  it will be
218      * an AsyncResult, and onComplete.obj.exception will be non-null
219      * on failure.
220      */
reRegisterNetwork(Message onComplete)221     public void reRegisterNetwork(Message onComplete) {
222         cm.getPreferredNetworkType(
223                 obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
224     }
225 
226     public void
setRadioPower(boolean power)227     setRadioPower(boolean power) {
228         mDesiredPowerState = power;
229 
230         setPowerStateToDesired();
231     }
232 
233     /**
234      * These two flags manage the behavior of the cell lock -- the
235      * lock should be held if either flag is true.  The intention is
236      * to allow temporary acquisition of the lock to get a single
237      * update.  Such a lock grab and release can thus be made to not
238      * interfere with more permanent lock holds -- in other words, the
239      * lock will only be released if both flags are false, and so
240      * releases by temporary users will only affect the lock state if
241      * there is no continuous user.
242      */
243     private boolean mWantContinuousLocationUpdates;
244     private boolean mWantSingleLocationUpdate;
245 
enableSingleLocationUpdate()246     public void enableSingleLocationUpdate() {
247         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
248         mWantSingleLocationUpdate = true;
249         cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
250     }
251 
enableLocationUpdates()252     public void enableLocationUpdates() {
253         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
254         mWantContinuousLocationUpdates = true;
255         cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
256     }
257 
disableSingleLocationUpdate()258     protected void disableSingleLocationUpdate() {
259         mWantSingleLocationUpdate = false;
260         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
261             cm.setLocationUpdates(false, null);
262         }
263     }
264 
disableLocationUpdates()265     public void disableLocationUpdates() {
266         mWantContinuousLocationUpdates = false;
267         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
268             cm.setLocationUpdates(false, null);
269         }
270     }
271 
272     @Override
handleMessage(Message msg)273     public void handleMessage(Message msg) {
274         switch (msg.what) {
275             case EVENT_SET_RADIO_POWER_OFF:
276                 synchronized(this) {
277                     if (mPendingRadioPowerOffAfterDataOff &&
278                             (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
279                         if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
280                         hangupAndPowerOff();
281                         mPendingRadioPowerOffAfterDataOffTag += 1;
282                         mPendingRadioPowerOffAfterDataOff = false;
283                     } else {
284                         log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
285                                 "!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
286                     }
287                 }
288                 break;
289 
290             default:
291                 log("Unhandled message with number: " + msg.what);
292                 break;
293         }
294     }
295 
getPhone()296     protected abstract Phone getPhone();
handlePollStateResult(int what, AsyncResult ar)297     protected abstract void handlePollStateResult(int what, AsyncResult ar);
updateSpnDisplay()298     protected abstract void updateSpnDisplay();
setPowerStateToDesired()299     protected abstract void setPowerStateToDesired();
log(String s)300     protected abstract void log(String s);
loge(String s)301     protected abstract void loge(String s);
302 
getCurrentDataConnectionState()303     public abstract int getCurrentDataConnectionState();
isConcurrentVoiceAndDataAllowed()304     public abstract boolean isConcurrentVoiceAndDataAllowed();
305 
306     /**
307      * Registration point for transition into DataConnection attached.
308      * @param h handler to notify
309      * @param what what code of message when delivered
310      * @param obj placed in Message.obj
311      */
registerForDataConnectionAttached(Handler h, int what, Object obj)312     public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
313         Registrant r = new Registrant(h, what, obj);
314         mAttachedRegistrants.add(r);
315 
316         if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
317             r.notifyRegistrant();
318         }
319     }
unregisterForDataConnectionAttached(Handler h)320     public void unregisterForDataConnectionAttached(Handler h) {
321         mAttachedRegistrants.remove(h);
322     }
323 
324     /**
325      * Registration point for transition into DataConnection detached.
326      * @param h handler to notify
327      * @param what what code of message when delivered
328      * @param obj placed in Message.obj
329      */
registerForDataConnectionDetached(Handler h, int what, Object obj)330     public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
331         Registrant r = new Registrant(h, what, obj);
332         mDetachedRegistrants.add(r);
333 
334         if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
335             r.notifyRegistrant();
336         }
337     }
unregisterForDataConnectionDetached(Handler h)338     public void unregisterForDataConnectionDetached(Handler h) {
339         mDetachedRegistrants.remove(h);
340     }
341 
342     /**
343      * Registration point for transition into network attached.
344      * @param h handler to notify
345      * @param what what code of message when delivered
346      * @param obj in Message.obj
347      */
registerForNetworkAttached(Handler h, int what, Object obj)348     public void registerForNetworkAttached(Handler h, int what, Object obj) {
349         Registrant r = new Registrant(h, what, obj);
350 
351         mNetworkAttachedRegistrants.add(r);
352         if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
353             r.notifyRegistrant();
354         }
355     }
unregisterForNetworkAttached(Handler h)356     public void unregisterForNetworkAttached(Handler h) {
357         mNetworkAttachedRegistrants.remove(h);
358     }
359 
360     /**
361      * Registration point for transition into packet service restricted zone.
362      * @param h handler to notify
363      * @param what what code of message when delivered
364      * @param obj placed in Message.obj
365      */
registerForPsRestrictedEnabled(Handler h, int what, Object obj)366     public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
367         Registrant r = new Registrant(h, what, obj);
368         mPsRestrictEnabledRegistrants.add(r);
369 
370         if (mRestrictedState.isPsRestricted()) {
371             r.notifyRegistrant();
372         }
373     }
374 
unregisterForPsRestrictedEnabled(Handler h)375     public void unregisterForPsRestrictedEnabled(Handler h) {
376         mPsRestrictEnabledRegistrants.remove(h);
377     }
378 
379     /**
380      * Registration point for transition out of packet service restricted zone.
381      * @param h handler to notify
382      * @param what what code of message when delivered
383      * @param obj placed in Message.obj
384      */
registerForPsRestrictedDisabled(Handler h, int what, Object obj)385     public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
386         Registrant r = new Registrant(h, what, obj);
387         mPsRestrictDisabledRegistrants.add(r);
388 
389         if (mRestrictedState.isPsRestricted()) {
390             r.notifyRegistrant();
391         }
392     }
393 
unregisterForPsRestrictedDisabled(Handler h)394     public void unregisterForPsRestrictedDisabled(Handler h) {
395         mPsRestrictDisabledRegistrants.remove(h);
396     }
397 
398     /**
399      * Clean up existing voice and data connection then turn off radio power.
400      *
401      * Hang up the existing voice calls to decrease call drop rate.
402      */
powerOffRadioSafely(DataConnectionTracker dcTracker)403     public void powerOffRadioSafely(DataConnectionTracker dcTracker) {
404         synchronized (this) {
405             if (!mPendingRadioPowerOffAfterDataOff) {
406                 // To minimize race conditions we call cleanUpAllConnections on
407                 // both if else paths instead of before this isDisconnected test.
408                 if (dcTracker.isDisconnected()) {
409                     // To minimize race conditions we do this after isDisconnected
410                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
411                     if (DBG) log("Data disconnected, turn off radio right away.");
412                     hangupAndPowerOff();
413                 } else {
414                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
415                     Message msg = Message.obtain(this);
416                     msg.what = EVENT_SET_RADIO_POWER_OFF;
417                     msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
418                     if (sendMessageDelayed(msg, 30000)) {
419                         if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
420                         mPendingRadioPowerOffAfterDataOff = true;
421                     } else {
422                         log("Cannot send delayed Msg, turn off radio right away.");
423                         hangupAndPowerOff();
424                     }
425                 }
426             }
427         }
428     }
429 
430     /**
431      * process the pending request to turn radio off after data is disconnected
432      *
433      * return true if there is pending request to process; false otherwise.
434      */
processPendingRadioPowerOffAfterDataOff()435     public boolean processPendingRadioPowerOffAfterDataOff() {
436         synchronized(this) {
437             if (mPendingRadioPowerOffAfterDataOff) {
438                 if (DBG) log("Process pending request to turn radio off.");
439                 mPendingRadioPowerOffAfterDataOffTag += 1;
440                 hangupAndPowerOff();
441                 mPendingRadioPowerOffAfterDataOff = false;
442                 return true;
443             }
444             return false;
445         }
446     }
447 
448     /**
449      * Hang up all voice call and turn off radio. Implemented by derived class.
450      */
hangupAndPowerOff()451     protected abstract void hangupAndPowerOff();
452 
453     /** Cancel a pending (if any) pollState() operation */
cancelPollState()454     protected void cancelPollState() {
455         // This will effectively cancel the rest of the poll requests.
456         pollingContext = new int[1];
457     }
458 }
459