一:问题点
刚开机时,系统进行初始化,有很多广播在排队,一些定制广播发送就比较迟才能收到。基于此,研究如何优化特定广播发送流程。
二:优化方案
2.1 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
系统原始有三个广播队列,前台广播队列、后台广播队列和offload广播队列。在广播初始化的地方,增加一个紧急广播队列
//final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3];
boolean mEnableUrgentQueue =false;
private static final int FLAG_RECEIVER_URGENT = 0x00000400;
//Special intent which needs to be handled immediately
private static final String URGENT_BROADCAST_INTENT = "com.iwt.mmi.request,";//android.provider.Telephony.SMS_DELIVER,
BroadcastQueue mUrgentBroadcastQueue;
final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[4];
2.2 ActivityManagerService.broadcastQueueForIntent
在寻找intent对应广播队列的函数里,如果该intent属于紧急广播队列,增加FLAG_RECEIVER_URGENT的flag并返回紧急广播队列
BroadcastQueue broadcastQueueForIntent(Intent intent) {
if (isOnOffloadQueue(intent.getFlags())) {
return mOffloadBroadcastQueue;
}
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
//add begin
if(SystemProperties.getBoolean("ro.feature.urgent_broadcast",false) ){
if(URGENT_BROADCAST_INTENT.contains(intent.getAction()+",")){
if (DEBUG_BROADCAST_BACKGROUND) {
Slog.i(TAG_BROADCAST,
"Broadcast intent " + intent + " on Urgent queue");
}
intent.addFlags(FLAG_RECEIVER_URGENT);
return mUrgentBroadcastQueue;
}
}
//add end
return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
2.3 ActivityManagerService.ActivityManagerService
在AMS的构造函数中进行紧急广播队列的初始化
mUrgentBroadcastQueue = new BroadcastQueue(this, mHandler,
"Urgent", foreConstants, false);
mBroadcastQueues[3] = mUrgentBroadcastQueue;
2.4 ActivityManagerService.isPendingBroadcastProcessLocked
在是否是待处理广播队列函数的判断里,增加紧急广播
boolean isPendingBroadcastProcessLocked(int pid) {
return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
|| mUrgentBroadcastQueue.isPendingBroadcastProcessLocked(pid) //add
|| mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
|| mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
}
2.5 ActivityManagerService.finishReceiver
在广播发送流程里,查找下一个待发送广播队列,判断intent是否有FLAG_RECEIVER_URGENT flag,如果有,说明是紧急广播队列,则发送紧急广播队列
public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {
final long origId = Binder.clearCallingIdentity();
try {
boolean doNext = false;
BroadcastRecord r;
BroadcastQueue queue;
synchronized(this) {
if (isOnOffloadQueue(flags)) {
queue = mOffloadBroadcastQueue;
} else {
//add begin
if(mEnableUrgentQueue
&& (flags & FLAG_RECEIVER_URGENT) != 0) {
queue = mUrgentBroadcastQueue;
} else {
//The following is Android original code
//add end
queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
}
}
r = queue.getMatchingOrderedReceiver(who);
if (r != null) {
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
if (doNext) {
r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
}
// updateOomAdjLocked() will be done here
trimApplicationsLocked(false, OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
三:小结
当广播队列优先级不高,被系统其他广播队列抢占,导致收不到广播时,可采用此方案。方案的核心思想是在系统原有广播队列的基础上,增加一个优先级最高的广播队列,一旦判定intent对应的广播队列属于该广播队列,则在查找广播队列并发送的函数里,直接返回该广播队列,不会被前台或后台广播队列阻塞。