转:http://bbs.pediy.com/showthread.php?p=1446927#post1446927

标 题: 【原创】安卓刷量技术揭秘(一) 工具篇
作 者: ckis
时 间: 2016-10-02,00:25:52
链 接: http://bbs.pediy.com/showthread.php?t=213042

目前 市面上你能买到的一些安卓刷量变机工具例如 008K、变机宝等等 使用的都是XPOSED框架来修改手机的机型。这种修改方式目前是一种主流技术,主流技术的优点就是兼容性好、开发(包括文档支持、社区支持、第三方模块)成本低、稳定性高等特点。但对于当前项目来说,主流技术并不是一个好的解决办法,因为主流技术不光你了解,APP的厂商的技术人员也很了解,而且一般规律来看,厂商的技术实力、人力、财力以及这三方面的积累,不是一个小团队的作者可以对抗的。

目前改机软件所实现的修改机型项目汇总起来分为以下几类
1:手机唯一身份标志
这个很好理解,主要包括 IMEI IMSI ICCID 等等这些全球唯一的身份标志,来表示这台手机的独立性,另外要实现一些编号的校验位运算,一般情况下,这些标志身份的序号都有校验位和一些固定的格式和算法,这里有很多渠道和积分墙是对这些序号的合法性有检测的。
2 : 唯一标志衍生信息
这个衍生信息就有很多项了,例如一些改机软件 随便的把某个厂商的型号和一个合法的IMEI结合在一起,殊不知IMEI的前6位为TAC,是每个机型独有的身份标志,随便搭配后,一定会被检测出来的。再例如联通的IMSI是46001开头,移动和电信的就不一样,IMSI,ICCID,NUMBER,运营商,网络制式,mnc,mcc这些信息最起码是要匹配的。
3:环境信息
环境信息分为两部分 ①:手机内部环境 包括你的系统特定信息,用户特定信息。②:手机外部环境:基站信息、GPS信息、WIFI信息等等。

本文中所有的操作都基于Android Studio环境。下面进入实战操作环节!

1 首先创建一个APP,并配置XPOSED的开发环境,配置过程可以参考以下两篇文章,此处不再重复。
http://www.cnblogs.com/csonezp/p/5177928.html
http://www.open-open.com/lib/view/open1451364108964.html

2 配置好XPOSED环境后,在该APP中创建HOOK类 本文为MainHook,该类必须继承IXposedHookLoadPackage

代码:

public class MainHook implements IXposedHookLoadPackage
{@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable{//xposed程序入口 do something...}
}

3 实际修改项

目前市面上的很多改机软件都没有修改第二处的IMEI 
另外一个位置是在com.android.internal.telephony.PhoneSubInfo类中,
导致有些反作弊系统读取这个位置的IMEI值后不会下分

代码:

HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getDeviceId", GetCatValue("imei"));
HTool.XHookMethod("com.android.internal.telephony.PhoneSubInfo",mLpp.classLoader, "getDeviceId", GetCatValue("imei"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSubscriberId", GetCatValue("imsi"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getLine1Number", GetCatValue("number"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimSerialNumber", GetCatValue("simserial"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimCountryIso", GetCatValue("simcountryiso"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimOperator", GetCatValue("simoperator"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimOperatorName", GetCatValue("simoperatorname"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkCountryIso", GetCatValue("networkcountryiso"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkOperator", GetCatValue("networkoperator"));
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkOperatorName", GetCatValue("networkoperatorname"));//WIFI信息
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getMacAddress", GetCatValue("wifimac"));
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getBSSID", GetCatValue("bssid"));
HTool.XHookMethod(android.net.wifi.WifiInfo.class.getName(),mLpp.classLoader, "getSSID", "\""+GetCatValue("ssid")+"\"");
XposedHelpers.findAndHookMethod(java.net.NetworkInterface.class.getName(),mLpp.classLoader, "getHardwareAddress", new Object[] {new XC_MethodHook(){protected void afterHookedMethod(MethodHookParam param) throws Throwable{//每个安卓系统中 至少存在5个以上的MAC地址 //但大多数软件只修改了MAC和BSSID //真正的MAC修改是在此处理函数中监听每次访问.}}});//蓝牙信息
HTool.XHookMethod(BluetoothAdapter.class.getName(),mLpp.classLoader,"getAddress", GetCatValue("bluemac"));
HTool.XHookMethod(BluetoothAdapter.class.getName(),mLpp.classLoader, "getName", GetCatValue("bluename"));//设置手机信息 无论手机是否插入了sim卡 都会模拟出SIM卡的信息 APP获得SIM卡消息时返回该手机已有SIM卡
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getPhoneType", TelephonyManager.PHONE_TYPE_GSM);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getNetworkType", TelephonyManager.NETWORK_TYPE_HSPAP);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "getSimState", TelephonyManager.SIM_STATE_READY);
HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLpp.classLoader, "hasIccCard", true);//修改手机系统信息 此处是手机的基本信息 包括厂商 信号 ROM版本 安卓版本 主板 设备名 指纹名称等信息
XposedHelpers.setStaticObjectField(android.os.Build.class, "MODEL", GetCatValue("model"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "MANUFACTURER", GetCatValue("manufacturer"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "BRAND", GetCatValue("brand"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "HARDWARE", GetCatValue("hardware"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "BOARD", GetCatValue("board"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "SERIAL", GetCatValue("serial"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "DEVICE", GetCatValue("device"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "ID", GetCatValue("id"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "PRODUCT", GetCatValue("product"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "DISPLAY", GetCatValue("display"));
XposedHelpers.setStaticObjectField(android.os.Build.class, "FINGERPRINT", GetCatValue("fingerprint"));XposedHelpers.findAndHookMethod("android.os.SystemProperties",mLpp.classLoader, "native_get", new Object[] {String.class,String.class,new XC_MethodHook(){//为了防止某些APP跳过Build类 而直接使用SystemProperties.native_get获得参数}});
//修改系统版本 我看到世面上的软件基本上都是不能修改系统版本的 从而造成了刷量后 很多渠道最终会显示你的APP用户全部使用的某一系统版本
//这样的话数据就太假了.
XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "RELEASE", GetCatValue("version"));
XposedHelpers.setStaticObjectField(android.os.Build.VERSION.class, "SDK", GetCatValue("apilevel"));HTool.XHookMethod(android.os.Build.class.getName(),mLpp.classLoader, "getRadioVersion", GetCatValue("radioversion"));//修改为指定的运营商mnc mcc信息
XposedHelpers.findAndHookMethod(android.content.res.Resources.class.getName(),mLpp.classLoader, "getConfiguration", new Object[] {new XC_MethodHook(){...........................//此处的mnc和mcc必须和系统中其他关于运营商的数据对应!}});//修改ANDROID_ID
XposedHelpers.findAndHookMethod(android.provider.Settings.Secure.class.getName(),mLpp.classLoader, "getString",
new Object[] {ContentResolver.class,String.class,new XC_MethodHook(){...............................//此处会根据传入的String参数 判断返回值 其中包括比较关键的数据就是android_id}});//防止APP使用Runtime.exec方式获取一些特定的系统属性
XposedHelpers.findAndHookMethod(Runtime.class.getName(),mLpp.classLoader, "exec",new Object[] {String.class,String[].class, File.class,new XC_MethodHook(){//一些APP从JAVA层获得到了数据 还会从shell(native)层获得一些更底层的数据 来判断用户的合法性//经常用到的有 cat、getprop、ifconfig等等命令,当exec执行这些命令后 往往会返回一些手机的真实信息//因为框架和处理方式不同,...部分此处根据自己需求,编写重定向返回值的过程...}});//修改位置信息
XposedHelpers.findAndHookMethod(LocationManager.class.getName(),mLpp.classLoader, "getLastKnownLocation",new Object[] {String.class,new XC_MethodHook(){..........................//返回预先设置好的经纬度信息以伪装地理位置}});HTool.XHookMethod(Location.class.getName(),mLpp.classLoader, "getLatitude", latitude);
HTool.XHookMethod(Location.class.getName(),mLpp.classLoader, "getLongitude", longitude);//修改GSM制式手机的基站信息
HTool.XHookMethod(android.telephony.gsm.GsmCellLocation.class.getName(),mLpp.classLoader, "getLac", GsmLac);
HTool.XHookMethod(android.telephony.gsm.GsmCellLocation.class.getName(),mLpp.classLoader, "getCid", GsmCid);//修改CDMA制式手机的基站信息
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationLatitude", CdmaLatitude);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationLongitude", CdmaLongitude);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getBaseStationId", CdmaBid);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getSystemId", CdmaSid);
HTool.XHookMethod(android.telephony.cdma.CdmaCellLocation.class.getName(),mLpp.classLoader, "getNetworkId", CdmaNid);//模拟手机的APP列表
XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager",mLpp.classLoader, "getInstalledPackages",new Object[] {int.class,new XC_MethodHook(){//此处模拟正常用户的APP列表 其中随机的增加和删除一些常用APP 以达到每个手机的APP有很大的随意性和合理性}});XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager",mLpp.classLoader, "getInstalledApplications",new Object[] {int.class,new XC_MethodHook(){//此处模拟正常用户的APP列表 其中随机的增加和删除一些常用APP 以达到每个手机的APP有很大的随意性和合理性}});//防止APP的VPN SOCK5 HTTP代理检测
XposedHelpers.findAndHookMethod(java.net.NetworkInterface.class.getName(),mLpp.classLoader, "getNetworkInterfacesList",new Object[] {new XC_MethodHook(){........................................//此处对于一些连接信息 对JAVA做了隐藏处理 但对于系统和Native层依然是可见的 所以APP不会检测到代理 但代理却可以正常的运行...}});

以上这些做下来 从信息采集上基本可以过市面上70%的系统了 对于某些系统的高级检测,则需要我们采用更高级的处理方式才能攻破对方的防线,这些处理方式我们随后会讲到。

但目前推广市场上 不光是采用技术手段 还采取大数据分析等方式判断你的数据是否合格 所以想把这个作为一个项目来做 从技术方面解决工具问题只是刚刚开始。*转载请注明来自看雪论坛@PEdiy.com

贴个利用反射机制来获取imei的代码:(这段代码手机上执行不会调用TelephonyManager.getDeviceId,没有调用shell,没有jni,但是确实能获取到imei):

  TelephonyManager tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);Method TelephonyManager_private_getSubscriberInfo = tel.getClass().getDeclaredMethod("getSubscriberInfo");TelephonyManager_private_getSubscriberInfo.setAccessible(true);Object iphonesubinfo = TelephonyManager_private_getSubscriberInfo.invoke(tel);log(iphonesubinfo.toString());Method getDeviceId = iphonesubinfo.getClass().getDeclaredMethod("getDeviceId");log(getDeviceId.toString());getDeviceId.setAccessible(true);Object deviceid = getDeviceId.invoke(iphonesubinfo);log("deviceid:" + deviceid.toString()); 

TelephonyManager.java (android-19):

/** 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.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.telephony.Rlog;import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** Provides access to information about the telephony services on* the device. Applications can use the methods in this class to* determine telephony services and states, as well as to access some* types of subscriber information. Applications can also register* a listener to receive notification of telephony state changes.* <p>* You do not instantiate this class directly; instead, you retrieve* a reference to an instance through* {@link android.content.Context#getSystemService* Context.getSystemService(Context.TELEPHONY_SERVICE)}.* <p>* Note that access to some telephony information is* permission-protected. Your application cannot access the protected* information unless it has the appropriate permissions declared in* its manifest file. Where permissions apply, they are noted in the* the methods through which you access the protected information.*/
public class TelephonyManager {private static final String TAG = "TelephonyManager";private static ITelephonyRegistry sRegistry;private final Context mContext;/** @hide */public TelephonyManager(Context context) {Context appContext = context.getApplicationContext();if (appContext != null) {mContext = appContext;} else {mContext = context;}if (sRegistry == null) {sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));}}/** @hide */private TelephonyManager() {mContext = null;}private static TelephonyManager sInstance = new TelephonyManager();/** @hide/* @deprecated - use getSystemService as described above */public static TelephonyManager getDefault() {return sInstance;}/** {@hide} */public static TelephonyManager from(Context context) {return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);}//// Broadcast Intent actions///*** Broadcast intent action indicating that the call state (cellular)* on the device has changed.** <p>* The {@link #EXTRA_STATE} extra indicates the new call state.* If the new state is RINGING, a second extra* {@link #EXTRA_INCOMING_NUMBER} provides the incoming phone number as* a String.** <p class="note">* Requires the READ_PHONE_STATE permission.** <p class="note">* This was a {@link android.content.Context#sendStickyBroadcast sticky}* broadcast in version 1.0, but it is no longer sticky.* Instead, use {@link #getCallState} to synchronously query the current call state.** @see #EXTRA_STATE* @see #EXTRA_INCOMING_NUMBER* @see #getCallState*/@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)public static final String ACTION_PHONE_STATE_CHANGED ="android.intent.action.PHONE_STATE";/*** The Phone app sends this intent when a user opts to respond-via-message during an incoming* call. By default, the device's default SMS app consumes this message and sends a text message* to the caller. A third party app can also provide this functionality by consuming this Intent* with a {@link android.app.Service} and sending the message using its own messaging system.* <p>The intent contains a URI (available from {@link android.content.Intent#getData})* describing the recipient, using either the {@code sms:}, {@code smsto:}, {@code mms:},* or {@code mmsto:} URI schema. Each of these URI schema carry the recipient information the* same way: the path part of the URI contains the recipient's phone number or a comma-separated* set of phone numbers if there are multiple recipients. For example, {@code* smsto:2065551234}.</p>** <p>The intent may also contain extras for the message text (in {@link* android.content.Intent#EXTRA_TEXT}) and a message subject* (in {@link android.content.Intent#EXTRA_SUBJECT}).</p>** <p class="note"><strong>Note:</strong>* The intent-filter that consumes this Intent needs to be in a {@link android.app.Service}* that requires the* permission {@link android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE}.</p>* <p>For example, the service that receives this intent can be declared in the manifest file* with an intent filter like this:</p>* <pre>* <!-- Service that delivers SMS messages received from the phone "quick response" -->* <service android:name=".HeadlessSmsSendService"*          android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"*          android:exported="true" >*   <intent-filter>*     <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />*     <category android:name="android.intent.category.DEFAULT" />*     <data android:scheme="sms" />*     <data android:scheme="smsto" />*     <data android:scheme="mms" />*     <data android:scheme="mmsto" />*   </intent-filter>* </service></pre>* <p>* Output: nothing.*/@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)public static final String ACTION_RESPOND_VIA_MESSAGE ="android.intent.action.RESPOND_VIA_MESSAGE";/*** The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast* for a String containing the new call state.** @see #EXTRA_STATE_IDLE* @see #EXTRA_STATE_RINGING* @see #EXTRA_STATE_OFFHOOK** <p class="note">* Retrieve with* {@link android.content.Intent#getStringExtra(String)}.*/public static final String EXTRA_STATE = PhoneConstants.STATE_KEY;/*** Value used with {@link #EXTRA_STATE} corresponding to* {@link #CALL_STATE_IDLE}.*/public static final String EXTRA_STATE_IDLE = PhoneConstants.State.IDLE.toString();/*** Value used with {@link #EXTRA_STATE} corresponding to* {@link #CALL_STATE_RINGING}.*/public static final String EXTRA_STATE_RINGING = PhoneConstants.State.RINGING.toString();/*** Value used with {@link #EXTRA_STATE} corresponding to* {@link #CALL_STATE_OFFHOOK}.*/public static final String EXTRA_STATE_OFFHOOK = PhoneConstants.State.OFFHOOK.toString();/*** The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast* for a String containing the incoming phone number.* Only valid when the new call state is RINGING.** <p class="note">* Retrieve with* {@link android.content.Intent#getStringExtra(String)}.*/public static final String EXTRA_INCOMING_NUMBER = "incoming_number";////// Device Info/////*** Returns the software version number for the device, for example,* the IMEI/SV for GSM phones. Return null if the software version is* not available.** <p>Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getDeviceSoftwareVersion() {try {return getSubscriberInfo().getDeviceSvn();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {return null;}}/*** Returns the unique device ID, for example, the IMEI for GSM and the MEID* or ESN for CDMA phones. Return null if device ID is not available.** <p>Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getDeviceId() {try {return getSubscriberInfo().getDeviceId();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {return null;}}/*** Returns the current location of the device.*<p>* If there is only one radio in the device and that radio has an LTE connection,* this method will return null. The implementation must not to try add LTE* identifiers into the existing cdma/gsm classes.*<p>* In the future this call will be deprecated.*<p>* @return Current location of the device or null if not available.** <p>Requires Permission:* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.*/public CellLocation getCellLocation() {try {Bundle bundle = getITelephony().getCellLocation();if (bundle.isEmpty()) return null;CellLocation cl = CellLocation.newFromBundle(bundle);if (cl.isEmpty())return null;return cl;} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {return null;}}/*** Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged* PhoneStateListener.onCellLocationChanged} will be called on location updates.** <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES* CONTROL_LOCATION_UPDATES}** @hide*/public void enableLocationUpdates() {try {getITelephony().enableLocationUpdates();} catch (RemoteException ex) {} catch (NullPointerException ex) {}}/*** Disables location update notifications.  {@link PhoneStateListener#onCellLocationChanged* PhoneStateListener.onCellLocationChanged} will be called on location updates.** <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES* CONTROL_LOCATION_UPDATES}** @hide*/public void disableLocationUpdates() {try {getITelephony().disableLocationUpdates();} catch (RemoteException ex) {} catch (NullPointerException ex) {}}/*** Returns the neighboring cell information of the device. The getAllCellInfo is preferred* and use this only if getAllCellInfo return nulls or an empty list.*<p>* In the future this call will be deprecated.*<p>* @return List of NeighboringCellInfo or null if info unavailable.** <p>Requires Permission:* (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}*/public List<NeighboringCellInfo> getNeighboringCellInfo() {try {return getITelephony().getNeighboringCellInfo(mContext.getOpPackageName());} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {return null;}}/** No phone radio. */public static final int PHONE_TYPE_NONE = PhoneConstants.PHONE_TYPE_NONE;/** Phone radio is GSM. */public static final int PHONE_TYPE_GSM = PhoneConstants.PHONE_TYPE_GSM;/** Phone radio is CDMA. */public static final int PHONE_TYPE_CDMA = PhoneConstants.PHONE_TYPE_CDMA;/** Phone is via SIP. */public static final int PHONE_TYPE_SIP = PhoneConstants.PHONE_TYPE_SIP;/*** Returns the current phone type.* TODO: This is a last minute change and hence hidden.** @see #PHONE_TYPE_NONE* @see #PHONE_TYPE_GSM* @see #PHONE_TYPE_CDMA* @see #PHONE_TYPE_SIP** {@hide}*/public int getCurrentPhoneType() {try{ITelephony telephony = getITelephony();if (telephony != null) {return telephony.getActivePhoneType();} else {// This can happen when the ITelephony interface is not up yet.return getPhoneTypeFromProperty();}} catch (RemoteException ex) {// This shouldn't happen in the normal case, as a backup we// read from the system property.return getPhoneTypeFromProperty();} catch (NullPointerException ex) {// This shouldn't happen in the normal case, as a backup we// read from the system property.return getPhoneTypeFromProperty();}}/*** Returns a constant indicating the device phone type.  This* indicates the type of radio used to transmit voice calls.** @see #PHONE_TYPE_NONE* @see #PHONE_TYPE_GSM* @see #PHONE_TYPE_CDMA* @see #PHONE_TYPE_SIP*/public int getPhoneType() {if (!isVoiceCapable()) {return PHONE_TYPE_NONE;}return getCurrentPhoneType();}private int getPhoneTypeFromProperty() {int type =SystemProperties.getInt(TelephonyProperties.CURRENT_ACTIVE_PHONE,getPhoneTypeFromNetworkType());return type;}private int getPhoneTypeFromNetworkType() {// When the system property CURRENT_ACTIVE_PHONE, has not been set,// use the system property for default network type.// This is a fail safe, and can only happen at first boot.int mode = SystemProperties.getInt("ro.telephony.default_network", -1);if (mode == -1)return PHONE_TYPE_NONE;return getPhoneType(mode);}/*** This function returns the type of the phone, depending* on the network mode.** @param networkMode* @return Phone Type** @hide*/public static int getPhoneType(int networkMode) {switch(networkMode) {case RILConstants.NETWORK_MODE_CDMA:case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:return PhoneConstants.PHONE_TYPE_CDMA;case RILConstants.NETWORK_MODE_WCDMA_PREF:case RILConstants.NETWORK_MODE_GSM_ONLY:case RILConstants.NETWORK_MODE_WCDMA_ONLY:case RILConstants.NETWORK_MODE_GSM_UMTS:case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA:case RILConstants.NETWORK_MODE_LTE_WCDMA:case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA:return PhoneConstants.PHONE_TYPE_GSM;// Use CDMA Phone for the global mode including CDMAcase RILConstants.NETWORK_MODE_GLOBAL:case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:return PhoneConstants.PHONE_TYPE_CDMA;case RILConstants.NETWORK_MODE_LTE_ONLY:if (getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {return PhoneConstants.PHONE_TYPE_CDMA;} else {return PhoneConstants.PHONE_TYPE_GSM;}default:return PhoneConstants.PHONE_TYPE_GSM;}}/*** The contents of the /proc/cmdline file*/private static String getProcCmdLine(){String cmdline = "";FileInputStream is = null;try {is = new FileInputStream("/proc/cmdline");byte [] buffer = new byte[2048];int count = is.read(buffer);if (count > 0) {cmdline = new String(buffer, 0, count);}} catch (IOException e) {Rlog.d(TAG, "No /proc/cmdline exception=" + e);} finally {if (is != null) {try {is.close();} catch (IOException e) {}}}Rlog.d(TAG, "/proc/cmdline=" + cmdline);return cmdline;}/** Kernel command line */private static final String sKernelCmdLine = getProcCmdLine();/** Pattern for selecting the product type from the kernel command line */private static final Pattern sProductTypePattern =Pattern.compile("\\sproduct_type\\s*=\\s*(\\w+)");/** The ProductType used for LTE on CDMA devices */private static final String sLteOnCdmaProductType =SystemProperties.get(TelephonyProperties.PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE, "");/*** Return if the current radio is LTE on CDMA. This* is a tri-state return value as for a period of time* the mode may be unknown.** @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}* or {@link PhoneConstants#LTE_ON_CDMA_TRUE}** @hide*/public static int getLteOnCdmaModeStatic() {int retVal;int curVal;String productType = "";curVal = SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,PhoneConstants.LTE_ON_CDMA_UNKNOWN);retVal = curVal;if (retVal == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);if (matcher.find()) {productType = matcher.group(1);if (sLteOnCdmaProductType.equals(productType)) {retVal = PhoneConstants.LTE_ON_CDMA_TRUE;} else {retVal = PhoneConstants.LTE_ON_CDMA_FALSE;}} else {retVal = PhoneConstants.LTE_ON_CDMA_FALSE;}}Rlog.d(TAG, "getLteOnCdmaMode=" + retVal + " curVal=" + curVal +" product_type='" + productType +"' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'");return retVal;}////// Current Network/////*** Returns the alphabetic name of current registered operator.* <p>* Availability: Only when user is registered to a network. Result may be* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if* on a CDMA network).*/public String getNetworkOperatorName() {return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);}/*** Returns the numeric name (MCC+MNC) of current registered operator.* <p>* Availability: Only when user is registered to a network. Result may be* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if* on a CDMA network).*/public String getNetworkOperator() {return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);}/*** Returns true if the device is considered roaming on the current* network, for GSM purposes.* <p>* Availability: Only when user registered to a network.*/public boolean isNetworkRoaming() {return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));}/*** Returns the ISO country code equivalent of the current registered* operator's MCC (Mobile Country Code).* <p>* Availability: Only when user is registered to a network. Result may be* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if* on a CDMA network).*/public String getNetworkCountryIso() {return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);}/** Network type is unknown */public static final int NETWORK_TYPE_UNKNOWN = 0;/** Current network is GPRS */public static final int NETWORK_TYPE_GPRS = 1;/** Current network is EDGE */public static final int NETWORK_TYPE_EDGE = 2;/** Current network is UMTS */public static final int NETWORK_TYPE_UMTS = 3;/** Current network is CDMA: Either IS95A or IS95B*/public static final int NETWORK_TYPE_CDMA = 4;/** Current network is EVDO revision 0*/public static final int NETWORK_TYPE_EVDO_0 = 5;/** Current network is EVDO revision A*/public static final int NETWORK_TYPE_EVDO_A = 6;/** Current network is 1xRTT*/public static final int NETWORK_TYPE_1xRTT = 7;/** Current network is HSDPA */public static final int NETWORK_TYPE_HSDPA = 8;/** Current network is HSUPA */public static final int NETWORK_TYPE_HSUPA = 9;/** Current network is HSPA */public static final int NETWORK_TYPE_HSPA = 10;/** Current network is iDen */public static final int NETWORK_TYPE_IDEN = 11;/** Current network is EVDO revision B*/public static final int NETWORK_TYPE_EVDO_B = 12;/** Current network is LTE */public static final int NETWORK_TYPE_LTE = 13;/** Current network is eHRPD */public static final int NETWORK_TYPE_EHRPD = 14;/** Current network is HSPA+ */public static final int NETWORK_TYPE_HSPAP = 15;/*** @return the NETWORK_TYPE_xxxx for current data connection.*/public int getNetworkType() {return getDataNetworkType();}/*** Returns a constant indicating the radio technology (network type)* currently in use on the device for data transmission.* @return the network type** @see #NETWORK_TYPE_UNKNOWN* @see #NETWORK_TYPE_GPRS* @see #NETWORK_TYPE_EDGE* @see #NETWORK_TYPE_UMTS* @see #NETWORK_TYPE_HSDPA* @see #NETWORK_TYPE_HSUPA* @see #NETWORK_TYPE_HSPA* @see #NETWORK_TYPE_CDMA* @see #NETWORK_TYPE_EVDO_0* @see #NETWORK_TYPE_EVDO_A* @see #NETWORK_TYPE_EVDO_B* @see #NETWORK_TYPE_1xRTT* @see #NETWORK_TYPE_IDEN* @see #NETWORK_TYPE_LTE* @see #NETWORK_TYPE_EHRPD* @see #NETWORK_TYPE_HSPAP** @hide*/public int getDataNetworkType() {try{ITelephony telephony = getITelephony();if (telephony != null) {return telephony.getDataNetworkType();} else {// This can happen when the ITelephony interface is not up yet.return NETWORK_TYPE_UNKNOWN;}} catch(RemoteException ex) {// This shouldn't happen in the normal casereturn NETWORK_TYPE_UNKNOWN;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn NETWORK_TYPE_UNKNOWN;}}/*** Returns the NETWORK_TYPE_xxxx for voice** @hide*/public int getVoiceNetworkType() {try{ITelephony telephony = getITelephony();if (telephony != null) {return telephony.getVoiceNetworkType();} else {// This can happen when the ITelephony interface is not up yet.return NETWORK_TYPE_UNKNOWN;}} catch(RemoteException ex) {// This shouldn't happen in the normal casereturn NETWORK_TYPE_UNKNOWN;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn NETWORK_TYPE_UNKNOWN;}}/** Unknown network class. {@hide} */public static final int NETWORK_CLASS_UNKNOWN = 0;/** Class of broadly defined "2G" networks. {@hide} */public static final int NETWORK_CLASS_2_G = 1;/** Class of broadly defined "3G" networks. {@hide} */public static final int NETWORK_CLASS_3_G = 2;/** Class of broadly defined "4G" networks. {@hide} */public static final int NETWORK_CLASS_4_G = 3;/*** Return general class of network type, such as "3G" or "4G". In cases* where classification is contentious, this method is conservative.** @hide*/public static int getNetworkClass(int networkType) {switch (networkType) {case NETWORK_TYPE_GPRS:case NETWORK_TYPE_EDGE:case NETWORK_TYPE_CDMA:case NETWORK_TYPE_1xRTT:case NETWORK_TYPE_IDEN:return NETWORK_CLASS_2_G;case NETWORK_TYPE_UMTS:case NETWORK_TYPE_EVDO_0:case NETWORK_TYPE_EVDO_A:case NETWORK_TYPE_HSDPA:case NETWORK_TYPE_HSUPA:case NETWORK_TYPE_HSPA:case NETWORK_TYPE_EVDO_B:case NETWORK_TYPE_EHRPD:case NETWORK_TYPE_HSPAP:return NETWORK_CLASS_3_G;case NETWORK_TYPE_LTE:return NETWORK_CLASS_4_G;default:return NETWORK_CLASS_UNKNOWN;}}/*** Returns a string representation of the radio technology (network type)* currently in use on the device.* @return the name of the radio technology** @hide pending API council review*/public String getNetworkTypeName() {return getNetworkTypeName(getNetworkType());}/** {@hide} */public static String getNetworkTypeName(int type) {switch (type) {case NETWORK_TYPE_GPRS:return "GPRS";case NETWORK_TYPE_EDGE:return "EDGE";case NETWORK_TYPE_UMTS:return "UMTS";case NETWORK_TYPE_HSDPA:return "HSDPA";case NETWORK_TYPE_HSUPA:return "HSUPA";case NETWORK_TYPE_HSPA:return "HSPA";case NETWORK_TYPE_CDMA:return "CDMA";case NETWORK_TYPE_EVDO_0:return "CDMA - EvDo rev. 0";case NETWORK_TYPE_EVDO_A:return "CDMA - EvDo rev. A";case NETWORK_TYPE_EVDO_B:return "CDMA - EvDo rev. B";case NETWORK_TYPE_1xRTT:return "CDMA - 1xRTT";case NETWORK_TYPE_LTE:return "LTE";case NETWORK_TYPE_EHRPD:return "CDMA - eHRPD";case NETWORK_TYPE_IDEN:return "iDEN";case NETWORK_TYPE_HSPAP:return "HSPA+";default:return "UNKNOWN";}}////// SIM Card/////** SIM card state: Unknown. Signifies that the SIM is in transition*  between states. For example, when the user inputs the SIM pin*  under PIN_REQUIRED state, a query for sim status returns*  this state before turning to SIM_STATE_READY. */public static final int SIM_STATE_UNKNOWN = 0;/** SIM card state: no SIM card is available in the device */public static final int SIM_STATE_ABSENT = 1;/** SIM card state: Locked: requires the user's SIM PIN to unlock */public static final int SIM_STATE_PIN_REQUIRED = 2;/** SIM card state: Locked: requires the user's SIM PUK to unlock */public static final int SIM_STATE_PUK_REQUIRED = 3;/** SIM card state: Locked: requries a network PIN to unlock */public static final int SIM_STATE_NETWORK_LOCKED = 4;/** SIM card state: Ready */public static final int SIM_STATE_READY = 5;/*** @return true if a ICC card is present*/public boolean hasIccCard() {try {return getITelephony().hasIccCard();} catch (RemoteException ex) {// Assume no ICC card if remote exception which shouldn't happenreturn false;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn false;}}/*** Returns a constant indicating the state of the* device SIM card.** @see #SIM_STATE_UNKNOWN* @see #SIM_STATE_ABSENT* @see #SIM_STATE_PIN_REQUIRED* @see #SIM_STATE_PUK_REQUIRED* @see #SIM_STATE_NETWORK_LOCKED* @see #SIM_STATE_READY*/public int getSimState() {String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);if ("ABSENT".equals(prop)) {return SIM_STATE_ABSENT;}else if ("PIN_REQUIRED".equals(prop)) {return SIM_STATE_PIN_REQUIRED;}else if ("PUK_REQUIRED".equals(prop)) {return SIM_STATE_PUK_REQUIRED;}else if ("NETWORK_LOCKED".equals(prop)) {return SIM_STATE_NETWORK_LOCKED;}else if ("READY".equals(prop)) {return SIM_STATE_READY;}else {return SIM_STATE_UNKNOWN;}}/*** Returns the MCC+MNC (mobile country code + mobile network code) of the* provider of the SIM. 5 or 6 decimal digits.* <p>* Availability: SIM state must be {@link #SIM_STATE_READY}** @see #getSimState*/public String getSimOperator() {return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);}/*** Returns the Service Provider Name (SPN).* <p>* Availability: SIM state must be {@link #SIM_STATE_READY}** @see #getSimState*/public String getSimOperatorName() {return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA);}/*** Returns the ISO country code equivalent for the SIM provider's country code.*/public String getSimCountryIso() {return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY);}/*** Returns the serial number of the SIM, if applicable. Return null if it is* unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getSimSerialNumber() {try {return getSubscriberInfo().getIccSerialNumber();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Return if the current radio is LTE on CDMA. This* is a tri-state return value as for a period of time* the mode may be unknown.** @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}* or {@link PhoneConstants#LTE_ON_CDMA_TRUE}** @hide*/public int getLteOnCdmaMode() {try {return getITelephony().getLteOnCdmaMode();} catch (RemoteException ex) {// Assume no ICC card if remote exception which shouldn't happenreturn PhoneConstants.LTE_ON_CDMA_UNKNOWN;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn PhoneConstants.LTE_ON_CDMA_UNKNOWN;}}////// Subscriber Info/////*** Returns the unique subscriber ID, for example, the IMSI for a GSM phone.* Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getSubscriberId() {try {return getSubscriberInfo().getSubscriberId();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the Group Identifier Level1 for a GSM phone.* Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getGroupIdLevel1() {try {return getSubscriberInfo().getGroupIdLevel1();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the phone number string for line 1, for example, the MSISDN* for a GSM phone. Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getLine1Number() {try {return getSubscriberInfo().getLine1Number();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the alphabetic identifier associated with the line 1 number.* Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}* @hide* nobody seems to call this.*/public String getLine1AlphaTag() {try {return getSubscriberInfo().getLine1AlphaTag();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the MSISDN string.* for a GSM phone. Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}** @hide*/public String getMsisdn() {try {return getSubscriberInfo().getMsisdn();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the voice mail number. Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getVoiceMailNumber() {try {return getSubscriberInfo().getVoiceMailNumber();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the complete voice mail number. Return null if it is unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED}** @hide*/public String getCompleteVoiceMailNumber() {try {return getSubscriberInfo().getCompleteVoiceMailNumber();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the voice mail count. Return 0 if unavailable.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}* @hide*/public int getVoiceMessageCount() {try {return getITelephony().getVoiceMessageCount();} catch (RemoteException ex) {return 0;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn 0;}}/*** Retrieves the alphabetic identifier associated with the voice* mail number.* <p>* Requires Permission:*   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}*/public String getVoiceMailAlphaTag() {try {return getSubscriberInfo().getVoiceMailAlphaTag();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the IMS private user identity (IMPI) that was loaded from the ISIM.* @return the IMPI, or null if not present or not loaded* @hide*/public String getIsimImpi() {try {return getSubscriberInfo().getIsimImpi();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the IMS home network domain name that was loaded from the ISIM.* @return the IMS domain name, or null if not present or not loaded* @hide*/public String getIsimDomain() {try {return getSubscriberInfo().getIsimDomain();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}/*** Returns the IMS public user identities (IMPU) that were loaded from the ISIM.* @return an array of IMPU strings, with one IMPU per string, or null if*      not present or not loaded* @hide*/public String[] getIsimImpu() {try {return getSubscriberInfo().getIsimImpu();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {// This could happen before phone restarts due to crashingreturn null;}}private IPhoneSubInfo getSubscriberInfo() {// get it each time because that process crashes a lotreturn IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));}/** Device call state: No activity. */public static final int CALL_STATE_IDLE = 0;/** Device call state: Ringing. A new call arrived and is*  ringing or waiting. In the latter case, another call is*  already active. */public static final int CALL_STATE_RINGING = 1;/** Device call state: Off-hook. At least one call exists* that is dialing, active, or on hold, and no calls are ringing* or waiting. */public static final int CALL_STATE_OFFHOOK = 2;/*** Returns a constant indicating the call state (cellular) on the device.*/public int getCallState() {try {return getITelephony().getCallState();} catch (RemoteException ex) {// the phone process is restarting.return CALL_STATE_IDLE;} catch (NullPointerException ex) {// the phone process is restarting.return CALL_STATE_IDLE;}}/** Data connection activity: No traffic. */public static final int DATA_ACTIVITY_NONE = 0x00000000;/** Data connection activity: Currently receiving IP PPP traffic. */public static final int DATA_ACTIVITY_IN = 0x00000001;/** Data connection activity: Currently sending IP PPP traffic. */public static final int DATA_ACTIVITY_OUT = 0x00000002;/** Data connection activity: Currently both sending and receiving*  IP PPP traffic. */public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT;/*** Data connection is active, but physical link is down*/public static final int DATA_ACTIVITY_DORMANT = 0x00000004;/*** Returns a constant indicating the type of activity on a data connection* (cellular).** @see #DATA_ACTIVITY_NONE* @see #DATA_ACTIVITY_IN* @see #DATA_ACTIVITY_OUT* @see #DATA_ACTIVITY_INOUT* @see #DATA_ACTIVITY_DORMANT*/public int getDataActivity() {try {return getITelephony().getDataActivity();} catch (RemoteException ex) {// the phone process is restarting.return DATA_ACTIVITY_NONE;} catch (NullPointerException ex) {// the phone process is restarting.return DATA_ACTIVITY_NONE;}}/** Data connection state: Unknown.  Used before we know the state.* @hide*/public static final int DATA_UNKNOWN        = -1;/** Data connection state: Disconnected. IP traffic not available. */public static final int DATA_DISCONNECTED   = 0;/** Data connection state: Currently setting up a data connection. */public static final int DATA_CONNECTING     = 1;/** Data connection state: Connected. IP traffic should be available. */public static final int DATA_CONNECTED      = 2;/** Data connection state: Suspended. The connection is up, but IP* traffic is temporarily unavailable. For example, in a 2G network,* data activity may be suspended when a voice call arrives. */public static final int DATA_SUSPENDED      = 3;/*** Returns a constant indicating the current data connection state* (cellular).** @see #DATA_DISCONNECTED* @see #DATA_CONNECTING* @see #DATA_CONNECTED* @see #DATA_SUSPENDED*/public int getDataState() {try {return getITelephony().getDataState();} catch (RemoteException ex) {// the phone process is restarting.return DATA_DISCONNECTED;} catch (NullPointerException ex) {return DATA_DISCONNECTED;}}private ITelephony getITelephony() {return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));}////// PhoneStateListener/////*** Registers a listener object to receive notification of changes* in specified telephony states.* <p>* To register a listener, pass a {@link PhoneStateListener}* and specify at least one telephony state of interest in* the events argument.** At registration, and when a specified telephony state* changes, the telephony manager invokes the appropriate* callback method on the listener object and passes the* current (udpated) values.* <p>* To unregister a listener, pass the listener object and set the* events argument to* {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).** @param listener The {@link PhoneStateListener} object to register*                 (or unregister)* @param events The telephony state(s) of interest to the listener,*               as a bitwise-OR combination of {@link PhoneStateListener}*               LISTEN_ flags.*/public void listen(PhoneStateListener listener, int events) {String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";try {Boolean notifyNow = true;sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);} catch (RemoteException ex) {// system process dead} catch (NullPointerException ex) {// system process dead}}/*** Returns the CDMA ERI icon index to display** @hide*/public int getCdmaEriIconIndex() {try {return getITelephony().getCdmaEriIconIndex();} catch (RemoteException ex) {// the phone process is restarting.return -1;} catch (NullPointerException ex) {return -1;}}/*** Returns the CDMA ERI icon mode,* 0 - ON* 1 - FLASHING** @hide*/public int getCdmaEriIconMode() {try {return getITelephony().getCdmaEriIconMode();} catch (RemoteException ex) {// the phone process is restarting.return -1;} catch (NullPointerException ex) {return -1;}}/*** Returns the CDMA ERI text,** @hide*/public String getCdmaEriText() {try {return getITelephony().getCdmaEriText();} catch (RemoteException ex) {// the phone process is restarting.return null;} catch (NullPointerException ex) {return null;}}/*** @return true if the current device is "voice capable".* <p>* "Voice capable" means that this device supports circuit-switched* (i.e. voice) phone calls over the telephony network, and is allowed* to display the in-call UI while a cellular voice call is active.* This will be false on "data only" devices which can't make voice* calls and don't support any in-call UI.* <p>* Note: the meaning of this flag is subtly different from the* PackageManager.FEATURE_TELEPHONY system feature, which is available* on any device with a telephony radio, even if the device is* data-only.** @hide pending API review*/public boolean isVoiceCapable() {if (mContext == null) return true;return mContext.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);}/*** @return true if the current device supports sms service.* <p>* If true, this means that the device supports both sending and* receiving sms via the telephony network.* <p>* Note: Voicemail waiting sms, cell broadcasting sms, and MMS are*       disabled when device doesn't support sms.** @hide pending API review*/public boolean isSmsCapable() {if (mContext == null) return true;return mContext.getResources().getBoolean(com.android.internal.R.bool.config_sms_capable);}/*** Returns all observed cell information from all radios on the* device including the primary and neighboring cells. This does* not cause or change the rate of PhoneStateListner#onCellInfoChanged.*<p>* The list can include one or more of {@link android.telephony.CellInfoGsm CellInfoGsm},* {@link android.telephony.CellInfoCdma CellInfoCdma},* {@link android.telephony.CellInfoLte CellInfoLte} and* {@link android.telephony.CellInfoWcdma CellInfoCdma} in any combination.* Specifically on devices with multiple radios it is typical to see instances of* one or more of any these in the list. In addition 0, 1 or more CellInfo* objects may return isRegistered() true.*<p>* This is preferred over using getCellLocation although for older* devices this may return null in which case getCellLocation should* be called.*<p>* @return List of CellInfo or null if info unavailable.** <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}*/public List<CellInfo> getAllCellInfo() {try {return getITelephony().getAllCellInfo();} catch (RemoteException ex) {return null;} catch (NullPointerException ex) {return null;}}/*** Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged* PhoneStateListener.onCellInfoChanged} will be invoked.*<p>* The default, 0, means invoke onCellInfoChanged when any of the reported* information changes. Setting the value to INT_MAX(0x7fffffff) means never issue* A onCellInfoChanged.*<p>* @param rateInMillis the rate** @hide*/public void setCellInfoListRate(int rateInMillis) {try {getITelephony().setCellInfoListRate(rateInMillis);} catch (RemoteException ex) {} catch (NullPointerException ex) {}}/*** Returns the MMS user agent.*/public String getMmsUserAgent() {if (mContext == null) return null;return mContext.getResources().getString(com.android.internal.R.string.config_mms_user_agent);}/*** Returns the MMS user agent profile URL.*/public String getMmsUAProfUrl() {if (mContext == null) return null;return mContext.getResources().getString(com.android.internal.R.string.config_mms_user_agent_profile_url);}
}

安卓刷量技术揭秘(一) 工具篇相关推荐

  1. 安卓刷量技术揭秘(二) 高级攻防技巧

    标 题: [原创]安卓刷量技术揭秘(二) 高级攻防技巧 作 者: ckis 时 间: 2016-10-02,00:28:27 链 接: http://bbs.pediy.com/showthread. ...

  2. 【CDS技术揭秘系列 总篇】阿里云的云定义存储来了

    简介: 全新发布的云定义存储 CDS 和传统的存储阵列.分布式存储.软件定义存储的区别在哪里?阿里云存储团队如何看待将来存储的发展趋势?本文邀请了 CDS 研发团队的核心技术负责人为大家揭开围绕着阿里 ...

  3. 搜狐视频P2P技术揭秘 - 流控篇

    1 各种流控算法 说到流控算法,业内人士脑海中应该立刻就能够浮现出下面的名词: TCP,拥塞控制,滑动窗口: QUIC,BBR: WebRTC,GCC,TransportCC UDT: KCP: -- ...

  4. 【CDS技术揭秘系列 02】阿里云CDS-SLS大揭秘

    简介:CDS-SLS 作为云化的日志平台,将组件进行高内聚低耦合,线下用户最低可以在6台规模的机器上将上述所有的功能自动化部署,在运维.运营.财务管理.数据分析报表等大数据场景领域以低代码模式有效解决 ...

  5. 卧底“刷量”卖家,有关微信公众号“刷量”的五个劲爆事实

    今天,公众号"刷量"工具瘫痪的消息被爆出后,迅速成为了朋友圈刷屏的新主题,吃瓜群众基本分为两拨,一拨纯属"看热闹不嫌事大"的,一拨与媒体利益相关或曾经利益相关的 ...

  6. 信公号刷量工具昨崩溃 大V“裸泳”阅读量打回原形

    "公号刷量"戳破新媒体经济的泡沫 微信公号不能刷阅读量了 大潮退去谁在裸泳?传微信公号刷量工具昨崩溃 大V"裸泳"阅读量打回原形 据报道,9月28日晚,因微信方 ...

  7. 搜狐视频P2P技术揭秘 - 分享率控制篇

    搜狐视频P2P技术揭秘 - 分享率控制篇 1 业务决定控制逻辑 2 搜狐影音/搜狐视频 2.1 状态定义 2.2 输入事件 2.3 状态转换 2.4 转换逻辑 3 Flash 播放器/H5 播放器 在 ...

  8. 揭秘中国刷量“点击农场”:两人操纵上万台手机暴利赚钱

    本文讲的是揭秘中国刷量"点击农场":两人操纵上万台手机暴利赚钱,小伙伴们平时上微信.微博时都会看到很多点赞量特高的帖子,对于这种帖子我们一般都比较关注,但是"点击农场&q ...

  9. 揭秘-Android刷量有多容易 1

    做互联网开发的同学可能对流量这个词很熟悉, 在互联网行业中对一个产品的质量有一些关键指标,比如日活DAU,比如次日留存,点击率. 往往评估一个产品的变现能力会通过日活来计算. 因此也就诞生了一些灰色产 ...

最新文章

  1. 机器学习(MACHINE LEARNING)MATLAB求解状态转移矩阵
  2. 【OpenCV3】cv::convertScaleAbs()使用详解
  3. Javascript的调试利器:Firebug使用详解
  4. 手把手教你写高质量Android技术博客,画图工具,录像工具,Markdown写法
  5. (原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(8): 生成只读table
  6. Caffe学习 五 conv_layer与im2col
  7. 在PyCharm环境下使用Jupyter Notebook
  8. [面试] C/C++语法(三)—— 字符串
  9. 软件测试成熟度与自动化测试
  10. 【滤波器】基于matlab GUI IIR数字滤波器设计【含Matlab源码 044期】
  11. roundcube mysql_Roundcube Webmail 安装配置
  12. 展锐Android-Q LCD调试
  13. 删除字符串数组中的空字符串
  14. 【Apache+Tomcat+Session+Memcache 高性能群集搭建】
  15. 大学生软件设计大赛文档要求
  16. Craft CMS简介
  17. 【Windows】hiberfil.sys相关操作
  18. C#开发实战视频教程_基于多线程C#开发QQ农场
  19. 学习Python的三种境界,你现在是在什么境界?
  20. 学java双十一电脑推荐_双十一,有什么值得学生购买的电脑吗?

热门文章

  1. 解决VSCode终端Ctrl+V无法粘贴问题
  2. java记录日志不打印控制台,java异常在控制台和日志里面的打印记录
  3. android+蓝牙遥控器,一种通过蓝牙遥控安卓设备的方法与流程
  4. SQLSERVER 数据库邮件发送以表格形式发送(存储过程内容发邮件)
  5. 如何查看eclipse是32位还是64位
  6. js字符串常见操作方法
  7. Hadoop/Hive-学习笔记【中级篇】
  8. 阿里云新Logo:生于代码
  9. [hadoop那些事]hadoop及其组件资源 115/百度云
  10. 微信端中的企业号、订阅号、服务号之前的区别