/* * 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. *
* 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()}. *
* 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} *
* * @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} *
* 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} *
* 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). *
* 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)
* @hide
*/
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((ListOTASP_UNKNOWN=1
* means the value is currently unknown and the system should wait until
*
OTASP_NEEDED=2
or
OTASP_NOT_NEEDED=3
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