| /* |
| * Copyright (C) 2008 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 android.telephony; |
| |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.Looper; |
| import android.os.Message; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.CellLocation; |
| import android.telephony.CellInfo; |
| import android.telephony.VoLteServiceState; |
| import android.telephony.Rlog; |
| import android.telephony.ServiceState; |
| import android.telephony.SignalStrength; |
| import android.telephony.PreciseCallState; |
| import android.telephony.PreciseDataConnectionState; |
| |
| import com.android.internal.telephony.IPhoneStateListener; |
| import java.util.List; |
| |
| /** |
| * A listener class for monitoring changes in specific telephony states |
| * on the device, including service state, signal strength, message |
| * waiting indicator (voicemail), and others. |
| * <p> |
| * Override the methods for the state that you wish to receive updates for, and |
| * pass your PhoneStateListener object, along with bitwise-or of the LISTEN_ |
| * flags to {@link TelephonyManager#listen TelephonyManager.listen()}. |
| * <p> |
| * Note that access to some telephony information is |
| * permission-protected. Your application won't receive updates for protected |
| * information unless it has the appropriate permissions declared in |
| * its manifest file. Where permissions apply, they are noted in the |
| * appropriate LISTEN_ flags. |
| */ |
| public class PhoneStateListener { |
| private static final String LOG_TAG = "PhoneStateListener"; |
| private static final boolean DBG = false; // STOPSHIP if true |
| |
| /** |
| * Stop listening for updates. |
| */ |
| public static final int LISTEN_NONE = 0; |
| |
| /** |
| * Listen for changes to the network service state (cellular). |
| * |
| * @see #onServiceStateChanged |
| * @see ServiceState |
| */ |
| public static final int LISTEN_SERVICE_STATE = 0x00000001; |
| |
| /** |
| * Listen for changes to the network signal strength (cellular). |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE |
| * READ_PHONE_STATE} |
| * <p> |
| * |
| * @see #onSignalStrengthChanged |
| * |
| * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS} |
| */ |
| @Deprecated |
| public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002; |
| |
| /** |
| * Listen for changes to the message-waiting indicator. |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE |
| * READ_PHONE_STATE} |
| * <p> |
| * Example: The status bar uses this to determine when to display the |
| * voicemail icon. |
| * |
| * @see #onMessageWaitingIndicatorChanged |
| */ |
| public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004; |
| |
| /** |
| * Listen for changes to the call-forwarding indicator. |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE |
| * READ_PHONE_STATE} |
| * @see #onCallForwardingIndicatorChanged |
| */ |
| public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; |
| |
| /** |
| * Listen for changes to the device's cell location. Note that |
| * this will result in frequent callbacks to the listener. |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION |
| * ACCESS_COARSE_LOCATION} |
| * <p> |
| * If you need regular location updates but want more control over |
| * the update interval or location precision, you can set up a listener |
| * through the {@link android.location.LocationManager location manager} |
| * instead. |
| * |
| * @see #onCellLocationChanged |
| */ |
| public static final int LISTEN_CELL_LOCATION = 0x00000010; |
| |
| /** |
| * Listen for changes to the device call state. |
| * {@more} |
| * |
| * @see #onCallStateChanged |
| */ |
| public static final int LISTEN_CALL_STATE = 0x00000020; |
| |
| /** |
| * Listen for changes to the data connection state (cellular). |
| * |
| * @see #onDataConnectionStateChanged |
| */ |
| public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040; |
| |
| /** |
| * Listen for changes to the direction of data traffic on the data |
| * connection (cellular). |
| * {@more} |
| * Example: The status bar uses this to display the appropriate |
| * data-traffic icon. |
| * |
| * @see #onDataActivity |
| */ |
| public static final int LISTEN_DATA_ACTIVITY = 0x00000080; |
| |
| /** |
| * Listen for changes to the network signal strengths (cellular). |
| * <p> |
| * Example: The status bar uses this to control the signal-strength |
| * icon. |
| * |
| * @see #onSignalStrengthsChanged |
| */ |
| public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100; |
| |
| /** |
| * Listen for changes to OTASP mode. |
| * |
| * @see #onOtaspChanged |
| * @hide |
| */ |
| public static final int LISTEN_OTASP_CHANGED = 0x00000200; |
| |
| /** |
| * Listen for changes to observed cell info. |
| * |
| * @see #onCellInfoChanged |
| */ |
| public static final int LISTEN_CELL_INFO = 0x00000400; |
| |
| /** |
| * Listen for precise changes and fails to the device calls (cellular). |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE |
| * READ_PRECISE_PHONE_STATE} |
| * |
| * @hide |
| */ |
| public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800; |
| |
| /** |
| * Listen for precise changes and fails on the data connection (cellular). |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE |
| * READ_PRECISE_PHONE_STATE} |
| * |
| * @see #onPreciseDataConnectionStateChanged |
| * @hide |
| */ |
| public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000; |
| |
| /** |
| * Listen for real time info for all data connections (cellular)). |
| * {@more} |
| * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE |
| * READ_PRECISE_PHONE_STATE} |
| * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo) |
| * |
| * @deprecated Use {@link TelephonyManager#getModemActivityInfo()} |
| * @hide |
| */ |
| @Deprecated |
| public static final int LISTEN_DATA_CONNECTION_REAL_TIME_INFO = 0x00002000; |
| |
| /** |
| * Listen for changes to LTE network state |
| * |
| * @see #onLteNetworkStateChanged |
| * @hide |
| */ |
| public static final int LISTEN_VOLTE_STATE = 0x00004000; |
| |
| /** |
| * Listen for OEM hook raw event |
| * |
| * @see #onOemHookRawEvent |
| * @hide |
| */ |
| public static final int LISTEN_OEM_HOOK_RAW_EVENT = 0x00008000; |
| |
| /** |
| * Listen for carrier network changes indicated by a carrier app. |
| * |
| * @see #onCarrierNetworkRequest |
| * @see TelephonyManager#notifyCarrierNetworkChange(boolean) |
| * @hide |
| */ |
| public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000; |
| |
| /* |
| * Subscription used to listen to the phone state changes |
| * @hide |
| */ |
| /** @hide */ |
| protected int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; |
| |
| private final Handler mHandler; |
| |
| /** |
| * Create a PhoneStateListener for the Phone with the default subscription. |
| * This class requires Looper.myLooper() not return null. |
| */ |
| public PhoneStateListener() { |
| this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, Looper.myLooper()); |
| } |
| |
| /** |
| * Create a PhoneStateListener for the Phone with the default subscription |
| * using a particular non-null Looper. |
| * @hide |
| */ |
| public PhoneStateListener(Looper looper) { |
| this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, looper); |
| } |
| |
| /** |
| * Create a PhoneStateListener for the Phone using the specified subscription. |
| * This class requires Looper.myLooper() not return null. To supply your |
| * own non-null Looper use PhoneStateListener(int subId, Looper looper) below. |
| * @hide |
| */ |
| public PhoneStateListener(int subId) { |
| this(subId, Looper.myLooper()); |
| } |
| |
| /** |
| * Create a PhoneStateListener for the Phone using the specified subscription |
| * and non-null Looper. |
| * @hide |
| */ |
| public PhoneStateListener(int subId, Looper looper) { |
| if (DBG) log("ctor: subId=" + subId + " looper=" + looper); |
| mSubId = subId; |
| mHandler = new Handler(looper) { |
| public void handleMessage(Message msg) { |
| if (DBG) { |
| log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what) |
| + " msg=" + msg); |
| } |
| switch (msg.what) { |
| case LISTEN_SERVICE_STATE: |
| PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj); |
| break; |
| case LISTEN_SIGNAL_STRENGTH: |
| PhoneStateListener.this.onSignalStrengthChanged(msg.arg1); |
| break; |
| case LISTEN_MESSAGE_WAITING_INDICATOR: |
| PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0); |
| break; |
| case LISTEN_CALL_FORWARDING_INDICATOR: |
| PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0); |
| break; |
| case LISTEN_CELL_LOCATION: |
| PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj); |
| break; |
| case LISTEN_CALL_STATE: |
| PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj); |
| break; |
| case LISTEN_DATA_CONNECTION_STATE: |
| PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2); |
| PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1); |
| break; |
| case LISTEN_DATA_ACTIVITY: |
| PhoneStateListener.this.onDataActivity(msg.arg1); |
| break; |
| case LISTEN_SIGNAL_STRENGTHS: |
| PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj); |
| break; |
| case LISTEN_OTASP_CHANGED: |
| PhoneStateListener.this.onOtaspChanged(msg.arg1); |
| break; |
| case LISTEN_CELL_INFO: |
| PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj); |
| break; |
| case LISTEN_PRECISE_CALL_STATE: |
| PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj); |
| break; |
| case LISTEN_PRECISE_DATA_CONNECTION_STATE: |
| PhoneStateListener.this.onPreciseDataConnectionStateChanged( |
| (PreciseDataConnectionState)msg.obj); |
| break; |
| case LISTEN_DATA_CONNECTION_REAL_TIME_INFO: |
| PhoneStateListener.this.onDataConnectionRealTimeInfoChanged( |
| (DataConnectionRealTimeInfo)msg.obj); |
| break; |
| case LISTEN_VOLTE_STATE: |
| PhoneStateListener.this.onVoLteServiceStateChanged((VoLteServiceState)msg.obj); |
| break; |
| case LISTEN_OEM_HOOK_RAW_EVENT: |
| PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj); |
| break; |
| case LISTEN_CARRIER_NETWORK_CHANGE: |
| PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj); |
| break; |
| |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Callback invoked when device service state changes. |
| * |
| * @see ServiceState#STATE_EMERGENCY_ONLY |
| * @see ServiceState#STATE_IN_SERVICE |
| * @see ServiceState#STATE_OUT_OF_SERVICE |
| * @see ServiceState#STATE_POWER_OFF |
| */ |
| public void onServiceStateChanged(ServiceState serviceState) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when network signal strength changes. |
| * |
| * @see ServiceState#STATE_EMERGENCY_ONLY |
| * @see ServiceState#STATE_IN_SERVICE |
| * @see ServiceState#STATE_OUT_OF_SERVICE |
| * @see ServiceState#STATE_POWER_OFF |
| * @deprecated Use {@link #onSignalStrengthsChanged(SignalStrength)} |
| */ |
| @Deprecated |
| public void onSignalStrengthChanged(int asu) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when the message-waiting indicator changes. |
| */ |
| public void onMessageWaitingIndicatorChanged(boolean mwi) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when the call-forwarding indicator changes. |
| */ |
| public void onCallForwardingIndicatorChanged(boolean cfi) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when device cell location changes. |
| */ |
| public void onCellLocationChanged(CellLocation location) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when device call state changes. |
| * @param state call state |
| * @param incomingNumber incoming call phone number. If application does not have |
| * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission, an empty |
| * string will be passed as an argument. |
| * |
| * @see TelephonyManager#CALL_STATE_IDLE |
| * @see TelephonyManager#CALL_STATE_RINGING |
| * @see TelephonyManager#CALL_STATE_OFFHOOK |
| */ |
| public void onCallStateChanged(int state, String incomingNumber) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when connection state changes. |
| * |
| * @see TelephonyManager#DATA_DISCONNECTED |
| * @see TelephonyManager#DATA_CONNECTING |
| * @see TelephonyManager#DATA_CONNECTED |
| * @see TelephonyManager#DATA_SUSPENDED |
| */ |
| public void onDataConnectionStateChanged(int state) { |
| // default implementation empty |
| } |
| |
| /** |
| * same as above, but with the network type. Both called. |
| */ |
| public void onDataConnectionStateChanged(int state, int networkType) { |
| } |
| |
| /** |
| * Callback invoked when data activity state changes. |
| * |
| * @see TelephonyManager#DATA_ACTIVITY_NONE |
| * @see TelephonyManager#DATA_ACTIVITY_IN |
| * @see TelephonyManager#DATA_ACTIVITY_OUT |
| * @see TelephonyManager#DATA_ACTIVITY_INOUT |
| * @see TelephonyManager#DATA_ACTIVITY_DORMANT |
| */ |
| public void onDataActivity(int direction) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when network signal strengths changes. |
| * |
| * @see ServiceState#STATE_EMERGENCY_ONLY |
| * @see ServiceState#STATE_IN_SERVICE |
| * @see ServiceState#STATE_OUT_OF_SERVICE |
| * @see ServiceState#STATE_POWER_OFF |
| */ |
| public void onSignalStrengthsChanged(SignalStrength signalStrength) { |
| // default implementation empty |
| } |
| |
| |
| /** |
| * The Over The Air Service Provisioning (OTASP) has changed. Requires |
| * the READ_PHONE_STATE permission. |
| * @param otaspMode is integer <code>OTASP_UNKNOWN=1<code> |
| * means the value is currently unknown and the system should wait until |
| * <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before |
| * making the decision to perform OTASP or not. |
| * |
| * @hide |
| */ |
| public void onOtaspChanged(int otaspMode) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when a observed cell info has changed, |
| * or new cells have been added or removed. |
| * @param cellInfo is the list of currently visible cells. |
| */ |
| public void onCellInfoChanged(List<CellInfo> cellInfo) { |
| } |
| |
| /** |
| * Callback invoked when precise device call state changes. |
| * |
| * @hide |
| */ |
| public void onPreciseCallStateChanged(PreciseCallState callState) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when data connection state changes with precise information. |
| * |
| * @hide |
| */ |
| public void onPreciseDataConnectionStateChanged( |
| PreciseDataConnectionState dataConnectionState) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when data connection state changes with precise information. |
| * |
| * @hide |
| */ |
| public void onDataConnectionRealTimeInfoChanged( |
| DataConnectionRealTimeInfo dcRtInfo) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when the service state of LTE network |
| * related to the VoLTE service has changed. |
| * @param stateInfo is the current LTE network information |
| * @hide |
| */ |
| public void onVoLteServiceStateChanged(VoLteServiceState stateInfo) { |
| } |
| |
| /** |
| * Callback invoked when OEM hook raw event is received. Requires |
| * the READ_PRIVILEGED_PHONE_STATE permission. |
| * @param rawData is the byte array of the OEM hook raw data. |
| * @hide |
| */ |
| public void onOemHookRawEvent(byte[] rawData) { |
| // default implementation empty |
| } |
| |
| /** |
| * Callback invoked when telephony has received notice from a carrier |
| * app that a network action that could result in connectivity loss |
| * has been requested by an app using |
| * {@link android.telephony.TelephonyManager#notifyCarrierNetworkChange(boolean)} |
| * |
| * @param active Whether the carrier network change is or shortly |
| * will be active. This value is true to indicate |
| * showing alternative UI and false to stop. |
| * |
| * @hide |
| */ |
| public void onCarrierNetworkChange(boolean active) { |
| // default implementation empty |
| } |
| |
| /** |
| * The callback methods need to be called on the handler thread where |
| * this object was created. If the binder did that for us it'd be nice. |
| */ |
| IPhoneStateListener callback = new IPhoneStateListener.Stub() { |
| public void onServiceStateChanged(ServiceState serviceState) { |
| Message.obtain(mHandler, LISTEN_SERVICE_STATE, 0, 0, serviceState).sendToTarget(); |
| } |
| |
| public void onSignalStrengthChanged(int asu) { |
| Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTH, asu, 0, null).sendToTarget(); |
| } |
| |
| public void onMessageWaitingIndicatorChanged(boolean mwi) { |
| Message.obtain(mHandler, LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null) |
| .sendToTarget(); |
| } |
| |
| public void onCallForwardingIndicatorChanged(boolean cfi) { |
| Message.obtain(mHandler, LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null) |
| .sendToTarget(); |
| } |
| |
| public void onCellLocationChanged(Bundle bundle) { |
| CellLocation location = CellLocation.newFromBundle(bundle); |
| Message.obtain(mHandler, LISTEN_CELL_LOCATION, 0, 0, location).sendToTarget(); |
| } |
| |
| public void onCallStateChanged(int state, String incomingNumber) { |
| Message.obtain(mHandler, LISTEN_CALL_STATE, state, 0, incomingNumber).sendToTarget(); |
| } |
| |
| public void onDataConnectionStateChanged(int state, int networkType) { |
| Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, networkType). |
| sendToTarget(); |
| } |
| |
| public void onDataActivity(int direction) { |
| Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget(); |
| } |
| |
| public void onSignalStrengthsChanged(SignalStrength signalStrength) { |
| Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget(); |
| } |
| |
| public void onOtaspChanged(int otaspMode) { |
| Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget(); |
| } |
| |
| public void onCellInfoChanged(List<CellInfo> cellInfo) { |
| Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget(); |
| } |
| |
| public void onPreciseCallStateChanged(PreciseCallState callState) { |
| Message.obtain(mHandler, LISTEN_PRECISE_CALL_STATE, 0, 0, callState).sendToTarget(); |
| } |
| |
| public void onPreciseDataConnectionStateChanged( |
| PreciseDataConnectionState dataConnectionState) { |
| Message.obtain(mHandler, LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, |
| dataConnectionState).sendToTarget(); |
| } |
| |
| public void onDataConnectionRealTimeInfoChanged( |
| DataConnectionRealTimeInfo dcRtInfo) { |
| Message.obtain(mHandler, LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, |
| dcRtInfo).sendToTarget(); |
| } |
| |
| public void onVoLteServiceStateChanged(VoLteServiceState lteState) { |
| Message.obtain(mHandler, LISTEN_VOLTE_STATE, 0, 0, lteState).sendToTarget(); |
| } |
| |
| public void onOemHookRawEvent(byte[] rawData) { |
| Message.obtain(mHandler, LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData).sendToTarget(); |
| } |
| |
| public void onCarrierNetworkChange(boolean active) { |
| Message.obtain(mHandler, LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active).sendToTarget(); |
| } |
| }; |
| |
| private void log(String s) { |
| Rlog.d(LOG_TAG, s); |
| } |
| } |