android/base/packages/SystemUI/src/com/android/systemui/
android 8.0
statusbar/SignalClusterView.java
android 9.0
statusbar/StatusBarWifiView.java
一、 wifi 图片修改方式
public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
private final WifiManager mWifiManager;
private final AsyncChannel mWifiChannel;
private final boolean mHasMobileData;
private final WifiStatusTracker mWifiTracker;
public WifiSignalController(Context context, boolean hasMobileData,
CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
callbackHandler, networkController);
// WiFi only has one state.
// 从这里可以看出是定义在 wifiIcons中的图片
mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
"Wi-Fi Icons",
WifiIcons.WIFI_SIGNAL_STRENGTH,
WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
AccessibilityContentDescriptions.WIFI_NO_CONNECTION
);
WIFI_SIGNAL_STRENGTH就是一个二维数组,这个数组里面就定义了不同状态栏下的wifi信号强度
,第一个数组就是带有"x"号或者"!"号的wifi icon,第二个数组就是正常显示的wifi icon
二、
wifi 流量的图标可在 SignalClusterView.java 或 StatusBarWifiView.java 中进行修改,位置和逻辑
三、 data 流程
wifi 信号的流程其实和 sim 信号的流程图标差不多
NetworkControllerImpl 和 WifiSignalControll
3.1 wifi的数据上下行流程
WifiSignalController.java
public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
private final WifiManager mWifiManager;
private final AsyncChannel mWifiChannel;
private final boolean mHasMobileData;
private final WifiStatusTracker mWifiTracker;
public WifiSignalController(Context context, boolean hasMobileData,
CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
callbackHandler, networkController);
//===================================================================
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mWifiTracker = new WifiStatusTracker(mWifiManager);
mHasMobileData = hasMobileData;
Handler handler = new WifiHandler(Looper.getMainLooper());
//起到了类似代理类的作用
mWifiChannel = new AsyncChannel();
Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
if (wifiMessenger != null) {
//======= 通过 messager 进行跨进程通讯 AsyncChannel 在下面 ====================================
mWifiChannel.connect(context, handler, wifiMessenger);
}
...
...
}
/**
* Handler to receive the data activity on wifi.
*/
private class WifiHandler extends Handler {
WifiHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mWifiChannel.sendMessage(Message.obtain(this,
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
} else {
Log.e(mTag, "Failed to connect to wifi");
}
break;
case WifiManager.DATA_ACTIVITY_NOTIFICATION:
//得到framework 层发来的消息
setActivity(msg.arg1);
break;
default:
// Ignore
break;
}
}
}
//通过这个方法才更新 activityIn activityOut 状态
@VisibleForTesting
void setActivity(int wifiActivity) {
mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_IN;
mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
notifyListenersIfNecessary();
}
}
3.2 AsyncChannel 起到了一个连接的作用,通过connect方法
AsyncChannel.java
public class AsyncChannel {
.....
// 看注释便能理解,链接
srcHandler 与 dstMessenger
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
// We are connected
connected(srcContext, srcHandler, dstMessenger);
// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);
if (DBG) log("connect srcHandler to the dstMessenger X");
}
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connected srcHandler to the dstMessenger E");
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
//利用 messenegr 进行跨进成通信
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;
//从注释可以看出来是 在AsyncChannel 中, messenger 与 srcHandler 进行数据交互
if (DBG) log("connected srcHandler to the dstMessenger X");
}
/**
* Send a message to the destination handler.
* @param msg
*/
public void sendMessage(Message msg) {
msg.replyTo = mSrcMessenger;
try {
mDstMessenger.send(msg);
} catch (RemoteException e) {
replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}
/**
* Reply to the src handler that we're half connected.
* see: CMD_CHANNEL_HALF_CONNECTED for message contents
* @param status to be stored in msg.arg1
*/
private void replyHalfConnected(int status) {
Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
if (!linkToDeathMonitor()) {
// Override status to indicate failure
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
mSrcHandler.sendMessage(msg);
}
}
3.3 mWifiManager -> WifiServiceImpl.java , connet 时将 Messenger 传给WifiTrafficPoller 中的clent列表
public class WifiServiceImpl extends IWifiManager.Stub {
/**
* Handles client connections
*/
private class ClientHandler extends WifiHandler {
ClientHandler(String tag, Looper looper) {
super(tag, looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
// 在通过 AsyncChannel.java 中的 replyHalfConnected, add client( is )
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
// We track the clients by the Messenger
// since it is expected to be always available
//在这里add client
mTrafficPoller.addClient(msg.replyTo);
} else {
Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
}
......
.......
}
/**
* Get a reference to handler. This is used by a client to establish
* an AsyncChannel communication with WifiService
*/
// WifiSignalController 得到 messenger的对象,通过messager对象跨进程通讯
@Override
public Messenger getWifiServiceMessenger() {
enforceAccessPermission();
enforceChangePermission();
if (mVerboseLoggingEnabled) {
mLog.info("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush();
}
return new Messenger(mClientHandler);
}
3.4 WifiSignalController 中的 handleMessage中接收的消息是从 wifiTrafficPoller.java //流量轮询器
/frameworks/base/services/java/com/android/server/wifi/WifiTrafficPoller.java
public class WifiTrafficPoller {
WifiTrafficPoller(Context context, Looper looper, String iface) {
mInterface = iface;
mTrafficHandler = new TrafficHandler(looper);
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
context.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
return;
}
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(
intent.getAction())) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
mScreenOn.set(false);
} else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
mScreenOn.set(true);
}
//如果监听到广播,则处理
evaluateTrafficStatsPolling();
}
}, filter);
}
private void evaluateTrafficStatsPolling() {
Message msg;
if (mNetworkInfo == null) return;
if (mNetworkInfo.getDetailedState() == CONNECTED && mScreenOn.get()) {
msg = Message.obtain(mTrafficHandler,ENABLE_TRAFFIC_STATS_POLL, 1, 0);
} else {
msg = Message.obtain(mTrafficHandler, ENABLE_TRAFFIC_STATS_POLL, 0, 0);
}
//发送handler消息,最终再调用 notifyOnDataActivity
msg.sendToTarget();
}
//根据流量的上行还是下行选择出图片并将消息发送出去
private void notifyOnDataActivity() {
long sent, received;
//保存当前的上下行数据包的数量
long preTxPkts = mTxPkts, preRxPkts = mRxPkts;
int dataActivity = WifiManager.DATA_ACTIVITY_NONE;
//== 通过如下的方法获取当前的上下行的数据包的数量 ===
mTxPkts = TrafficStats.getTxPackets(mInterface);
mRxPkts = TrafficStats.getRxPackets(mInterface);
if (DBG) {
Log.d(TAG, " packet count Tx="+ Long.toString(mTxPkts)
+ " Rx="+ Long.toString(mRxPkts));
}
if (preTxPkts > 0 || preRxPkts > 0) {
sent = mTxPkts - preTxPkts;
received = mRxPkts - preRxPkts;
//如果是发送数据
if (sent > 0) {
dataActivity |= WifiManager.DATA_ACTIVITY_OUT;
}
//接受数据
if (received > 0) {
dataActivity |= WifiManager.DATA_ACTIVITY_IN;
}
if (dataActivity != mDataActivity && mScreenOn.get()) {
mDataActivity = dataActivity;
if (mVerboseLoggingEnabled) {
Log.e(TAG, "notifying of data activity "
+ Integer.toString(mDataActivity));
}
for (Messenger client : mClients) {
Message msg = Message.obtain();
msg.what = WifiManager.DATA_ACTIVITY_NOTIFICATION;
msg.arg1 = mDataActivity;
try {
//这里for循环将消息发给
client.send(msg);
} catch (RemoteException e) {
// Failed to reach, skip
// Client removal is handled in WifiService
}
}
}
}
}
5.5. frameworks/base/core/java/android/net/TrafficStats.java
WifiTrafficPoller 中的获取当前上下行 数据包的方法
public class TrafficStats {
/**
* The return value to indicate that the device does not support the statistic.
*/
public final static int UNSUPPORTED = -1;
/** @hide */
public static final long KB_IN_BYTES = 1024;
/** @hide */
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
/** @hide */
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
/** @hide */
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
/** @hide */
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
//调用 native方法得到数据,
/** {@hide} */
public static long getTxPackets(String iface) {
return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
}
}
5.6. //全局搜索 nativeGetIfaceStat ,找到 LINUX/android/frameworks/base/core/jni/android_net_TrafficStats.cpp文件中
// nativeGetIfaceStat是通过 getIfaceStat实现
static JNINativeMethod gMethods[] = {
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J",(void*) getIfaceStat}
}
static jlong getIfaceStat(JNIEnv* env,jclass clazz, jstring iface, jint type) {
ScopedUtfChars iface8(env, iface);
if (parseIfaceStats(iface8.c_str(), &stats) == 0)
}
//c_str
/** LINUX/android/libnativehelper/include/nativehelper/ScopedUtfChars.h中
const char* c_str() const {
//utf_chars_的值为wlan0
return utf_chars_;
} **/
QTAGUID_IFACE_STATS ="/proc/net/xt_qtaguid/iface_stat_fmt";
static int parseIfaceStats(const char* iface, struct Stats* stats) {
FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
if (fp == NULL) {
return -1;
}
char buffer[384];
char cur_iface[32];
bool foundTcp = false;
uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets;
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64
" %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u "
"%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes,
&rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets);
if (matched >= 5) {
if (matched == 7) {
foundTcp = true;
}
if (!iface || !strcmp(iface, cur_iface)) {
stats->rxBytes += rxBytes;
stats->rxPackets += rxPackets;
stats->txBytes += txBytes;
stats->txPackets += txPackets;
if (matched == 7) {
stats->tcpRxPackets += tcpRxPackets;
stats->tcpTxPackets += tcpTxPackets;
}
}
}
}
if (!foundTcp) {
stats->tcpRxPackets = UNKNOWN;
stats->tcpTxPackets = UNKNOWN;
}
if (fclose(fp) != 0) {
return -1;
}
return 0;
}
5.7、全局搜索 iface_stat_fmt, LINUX/android/kernel/net/netfilter/xt_qtaguid.c中
通过如下的方法创建 iface_stat_fmt
static const char*iface_stat_fmt_procfilename = "iface_stat_fmt";
iface_stat_fmt_procfile = proc_create_data(iface_stat_fmt_procfilename,
proc_iface_perms,
parent_procdir,&proc_iface_stat_fmt_fops, (void *)2 /* fmt2 */);