当前位置:   article > 正文

Android 深入理解 ANR 触发原理:Broadcast_mpendingbroadcast

mpendingbroadcast

三、BroadcastReceiver Timeout

3.1 processNextBroadcastLocked

在学习Broadcast timeout 之前最好对广播的发生流程有一定了解,可以参考gityuan大神《Android Broadcast广播机制分析》。在广播流程有基础后,我们再来看最关键的代码块processNextBroadcastLocked,我们同样提两个问题:1.broadcast 什么情况下会ANR ? 2.ANR会有哪些log。

  1. final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
  2. BroadcastRecord r;
  3. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
  4. + mQueueName + "]: "
  5. + mParallelBroadcasts.size() + " parallel broadcasts; "
  6. + mDispatcher.describeStateLocked());
  7. mService.updateCpuStats();//更新cpu状态
  8. //fromMsg是指processNextBroadcast()是否由BroadcastHandler所调用的. 第一次从sendBroadcast是true。
  9. if (fromMsg) {
  10. mBroadcastsScheduled = false;
  11. }
  12. // First, deliver any non-serialized broadcasts right away.
  13. //part1: 处理并行广播,并行广播没有ANR的问题。
  14. while (mParallelBroadcasts.size() > 0) {
  15. r = mParallelBroadcasts.remove(0);//获取广播。
  16. r.dispatchTime = SystemClock.uptimeMillis();
  17. r.dispatchClockTime = System.currentTimeMillis();
  18. if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
  19. Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
  20. createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
  21. System.identityHashCode(r));
  22. Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
  23. createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
  24. System.identityHashCode(r));
  25. }
  26. final int N = r.receivers.size();
  27. if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
  28. + mQueueName + "] " + r);
  29. for (int i=0; i<N; i++) {
  30. Object target = r.receivers.get(i);
  31. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  32. "Delivering non-ordered on [" + mQueueName + "] to registered "
  33. + target + ": " + r);
  34. //分发广播给已注册的receive
  35. deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
  36. }
  37. addBroadcastToHistoryLocked(r);//将广播添加历史统计
  38. if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
  39. + mQueueName + "] " + r);
  40. }
  41. // Now take care of the next serialized one...
  42. // If we are waiting for a process to come up to handle the next
  43. // broadcast, then do nothing at this point. Just in case, we
  44. // check that the process we're waiting for still exists.
  45. //mPendingBroadcast 表示的是等待进程启动来处理的广播,如果进程存活则直接 return 继续等待
  46. //如果该进程已经被杀,则重置 mPendingBroadcast 为空
  47. if (mPendingBroadcast != null) {
  48. if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
  49. "processNextBroadcast [" + mQueueName + "]: waiting for "
  50. + mPendingBroadcast.curApp);
  51. boolean isDead;
  52. if (mPendingBroadcast.curApp.pid > 0) {
  53. synchronized (mService.mPidsSelfLocked) {
  54. ProcessRecord proc = mService.mPidsSelfLocked.get(
  55. mPendingBroadcast.curApp.pid);
  56. isDead = proc == null || proc.isCrashing();
  57. }
  58. } else {
  59. final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
  60. mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
  61. isDead = proc == null || !proc.pendingStart;
  62. }
  63. if (!isDead) {
  64. // It's still alive, so keep waiting
  65. return;
  66. } else {
  67. Slog.w(TAG, "pending app ["
  68. + mQueueName + "]" + mPendingBroadcast.curApp
  69. + " died before responding to broadcast");
  70. mPendingBroadcast.state = BroadcastRecord.IDLE;
  71. mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
  72. mPendingBroadcast = null;
  73. }
  74. }
  75. boolean looped = false;
  76. // 这后面的都是处理有序广播
  77. do {
  78. final long now = SystemClock.uptimeMillis();
  79. r = mDispatcher.getNextBroadcastLocked(now);//从有序广播list中取出一个广播。
  80. if (r == null) {//如果是空的话,说明没有广播需要处理,就返回。
  81. // No more broadcasts are deliverable right now, so all done!
  82. mDispatcher.scheduleDeferralCheckLocked(false);
  83. mService.scheduleAppGcsLocked();//所有串行广播处理完成,则调度执行gc
  84. if (looped) {
  85. // If we had finished the last ordered broadcast, then
  86. // make sure all processes have correct oom and sched
  87. // adjustments.
  88. mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
  89. }
  90. // when we have no more ordered broadcast on this queue, stop logging
  91. if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
  92. mLogLatencyMetrics = false;
  93. }
  94. return;
  95. }
  96. boolean forceReceive = false;
  97. // Ensure that even if something goes awry with the timeout
  98. // detection, we catch "hung" broadcasts here, discard them,
  99. // and continue to make progress.
  100. //
  101. // This is only done if the system is ready so that early-stage receivers
  102. // don't get executed with timeouts; and of course other timeout-
  103. // exempt broadcasts are ignored.
  104. //如果广播处理的总时间超过2 * mConstants.TIMEOUT * numReceivers ,broadcastTimeoutLocked 也就ANR.
  105. //所以在处理有序广播的时候不仅对单个广播时长有做限制,对于总的Receivers时间也有限制。
  106. int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
  107. if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
  108. if ((numReceivers > 0) &&
  109. (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers)) &&
  110. /// M: ANR Debug Mechanism
  111. !mService.mAnrManager.isAnrDeferrable()) {
  112. Slog.w(TAG, "Hung broadcast ["
  113. + mQueueName + "] discarded after timeout failure:"
  114. + " now=" + now
  115. + " dispatchTime=" + r.dispatchTime
  116. + " startTime=" + r.receiverTime
  117. + " intent=" + r.intent
  118. + " numReceivers=" + numReceivers
  119. + " nextReceiver=" + r.nextReceiver
  120. + " state=" + r.state);
  121. //发送超时广播。
  122. broadcastTimeoutLocked(false); // forcibly finish this broadcast
  123. forceReceive = true;
  124. r.state = BroadcastRecord.IDLE;
  125. }
  126. }
  127. if (r.state != BroadcastRecord.IDLE) {
  128. if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
  129. "processNextBroadcast("
  130. + mQueueName + ") called when not idle (state="
  131. + r.state + ")");
  132. return;
  133. }
  134. // Is the current broadcast is done for any reason?
  135. //如果广播接收者为空、下一个接收者下标越界、广播被中止等则继续分发下一个广播 ,r.receivers 什么时候会是null,finishReceiverLocked
  136. if (r.receivers == null || r.nextReceiver >= numReceivers
  137. || r.resultAbort || forceReceive) {
  138. // Send the final result if requested
  139. if (r.resultTo != null) {
  140. boolean sendResult = true;
  141. // if this was part of a split/deferral complex, update the refcount and only
  142. // send the completion when we clear all of them
  143. if (r.splitToken != 0) {
  144. int newCount = mSplitRefcounts.get(r.splitToken) - 1;
  145. if (newCount == 0) {
  146. // done! clear out this record's bookkeeping and deliver
  147. if (DEBUG_BROADCAST_DEFERRAL) {
  148. Slog.i(TAG_BROADCAST,
  149. "Sending broadcast completion for split token "
  150. + r.splitToken + " : " + r.intent.getAction());
  151. }
  152. mSplitRefcounts.delete(r.splitToken);
  153. } else {
  154. // still have some split broadcast records in flight; update refcount
  155. // and hold off on the callback
  156. if (DEBUG_BROADCAST_DEFERRAL) {
  157. Slog.i(TAG_BROADCAST,
  158. "Result refcount now " + newCount + " for split token "
  159. + r.splitToken + " : " + r.intent.getAction()
  160. + " - not sending completion yet");
  161. }
  162. sendResult = false;
  163. mSplitRefcounts.put(r.splitToken, newCount);
  164. }
  165. }
  166. if (sendResult) {
  167. try {
  168. if (DEBUG_BROADCAST) {
  169. Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] "
  170. + r.intent.getAction() + " app=" + r.callerApp);
  171. }
  172. //处理广播消息消息,调用到onReceive()
  173. performReceiveLocked(r.callerApp, r.resultTo,
  174. new Intent(r.intent), r.resultCode,
  175. r.resultData, r.resultExtras, false, false, r.userId);
  176. // Set this to null so that the reference
  177. // (local and remote) isn't kept in the mBroadcastHistory.
  178. r.resultTo = null;
  179. } catch (RemoteException e) {
  180. r.resultTo = null;
  181. Slog.w(TAG, "Failure ["
  182. + mQueueName + "] sending broadcast result of "
  183. + r.intent, e);
  184. }
  185. }
  186. }
  187. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
  188. //取消BROADCAST_TIMEOUT_MSG消息
  189. cancelBroadcastTimeoutLocked();
  190. if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
  191. "Finished with ordered broadcast " + r);
  192. // ... and on to the next...
  193. addBroadcastToHistoryLocked(r);//已经发过的广播添加到list
  194. if (r.intent.getComponent() == null && r.intent.getPackage() == null
  195. && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
  196. // This was an implicit broadcast... let's record it for posterity.
  197. mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
  198. r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
  199. }
  200. mDispatcher.retireBroadcastLocked(r);
  201. r = null;
  202. looped = true;
  203. continue;
  204. }
  205. // Check whether the next receiver is under deferral policy, and handle that
  206. // accordingly. If the current broadcast was already part of deferred-delivery
  207. // tracking, we know that it must now be deliverable as-is without re-deferral.
  208. if (!r.deferred) {
  209. final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
  210. if (mDispatcher.isDeferringLocked(receiverUid)) {
  211. if (DEBUG_BROADCAST_DEFERRAL) {
  212. Slog.i(TAG_BROADCAST, "Next receiver in " + r + " uid " + receiverUid
  213. + " at " + r.nextReceiver + " is under deferral");
  214. }
  215. // If this is the only (remaining) receiver in the broadcast, "splitting"
  216. // doesn't make sense -- just defer it as-is and retire it as the
  217. // currently active outgoing broadcast.
  218. BroadcastRecord defer;
  219. if (r.nextReceiver + 1 == numReceivers) {
  220. if (DEBUG_BROADCAST_DEFERRAL) {
  221. Slog.i(TAG_BROADCAST, "Sole receiver of " + r
  222. + " is under deferral; setting aside and proceeding");
  223. }
  224. defer = r;
  225. mDispatcher.retireBroadcastLocked(r);
  226. } else {
  227. // Nontrivial case; split out 'uid's receivers to a new broadcast record
  228. // and defer that, then loop and pick up continuing delivery of the current
  229. // record (now absent those receivers).
  230. // The split operation is guaranteed to match at least at 'nextReceiver'
  231. defer = r.splitRecipientsLocked(receiverUid, r.nextReceiver);
  232. if (DEBUG_BROADCAST_DEFERRAL) {
  233. Slog.i(TAG_BROADCAST, "Post split:");
  234. Slog.i(TAG_BROADCAST, "Original broadcast receivers:");
  235. for (int i = 0; i < r.receivers.size(); i++) {
  236. Slog.i(TAG_BROADCAST, " " + r.receivers.get(i));
  237. }
  238. Slog.i(TAG_BROADCAST, "Split receivers:");
  239. for (int i = 0; i < defer.receivers.size(); i++) {
  240. Slog.i(TAG_BROADCAST, " " + defer.receivers.get(i));
  241. }
  242. }
  243. // Track completion refcount as well if relevant
  244. if (r.resultTo != null) {
  245. int token = r.splitToken;
  246. if (token == 0) {
  247. // first split of this record; refcount for 'r' and 'deferred'
  248. r.splitToken = defer.splitToken = nextSplitTokenLocked();
  249. mSplitRefcounts.put(r.splitToken, 2);
  250. if (DEBUG_BROADCAST_DEFERRAL) {
  251. Slog.i(TAG_BROADCAST,
  252. "Broadcast needs split refcount; using new token "
  253. + r.splitToken);
  254. }
  255. } else {
  256. // new split from an already-refcounted situation; increment count
  257. final int curCount = mSplitRefcounts.get(token);
  258. if (DEBUG_BROADCAST_DEFERRAL) {
  259. if (curCount == 0) {
  260. Slog.wtf(TAG_BROADCAST,
  261. "Split refcount is zero with token for " + r);
  262. }
  263. }
  264. mSplitRefcounts.put(token, curCount + 1);
  265. if (DEBUG_BROADCAST_DEFERRAL) {
  266. Slog.i(TAG_BROADCAST, "New split count for token " + token
  267. + " is " + (curCount + 1));
  268. }
  269. }
  270. }
  271. }
  272. mDispatcher.addDeferredBroadcast(receiverUid, defer);
  273. r = null;
  274. looped = true;
  275. continue;
  276. }
  277. }
  278. } while (r == null);
  279. // Get the next receiver...
  280. // recIdx 表示当前接收者的下标,r.nextReceiver 为下一个接收者的下标,默认为 0
  281. int recIdx = r.nextReceiver++;
  282. // Keep track of when this receiver started, and make sure there
  283. // is a timeout message pending to kill it if need be.
  284. r.receiverTime = SystemClock.uptimeMillis();
  285. if (recIdx == 0) {
  286. r.dispatchTime = r.receiverTime;//设置分发时间,这个时间对timeout比较关键。
  287. r.dispatchClockTime = System.currentTimeMillis();
  288. if (mLogLatencyMetrics) {
  289. StatsLog.write(
  290. StatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED,
  291. r.dispatchClockTime - r.enqueueClockTime);
  292. }
  293. 打印一些trace 信息。一般情况是不开启打印的。eng版本才有开启。
  294. if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
  295. Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
  296. createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
  297. System.identityHashCode(r));
  298. Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
  299. createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
  300. System.identityHashCode(r));
  301. }
  302. if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
  303. + mQueueName + "] " + r);
  304. }
  305. //mPendingBroadcastTimeoutMessage 这个值在刚才执行cancelBroadcastTimeoutLocked 设置false。
  306. if (! mPendingBroadcastTimeoutMessage) {
  307. long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
  308. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  309. "Submitting BROADCAST_TIMEOUT_MSG ["
  310. + mQueueName + "] for " + r + " at " + timeoutTime);
  311. setBroadcastTimeoutLocked(timeoutTime);//在10s 后发送BROADCAST_TIMEOUT_MSG 广播,最终会执行broadcastTimeoutLocked。后面有对这个方法说明。
  312. }
  313. final BroadcastOptions brOptions = r.options;
  314. final Object nextReceiver = r.receivers.get(recIdx);
  315. //如果是动态广播
  316. if (nextReceiver instanceof BroadcastFilter) {
  317. // Simple case: this is a registered receiver who gets
  318. // a direct call.
  319. BroadcastFilter filter = (BroadcastFilter)nextReceiver;
  320. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  321. "Delivering ordered ["
  322. + mQueueName + "] to registered "
  323. + filter + ": " + r);
  324. deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);//直接执行
  325. //如果广播已经执行完的情况
  326. if (r.receiver == null || !r.ordered) {
  327. // The receiver has already finished, so schedule to
  328. // process the next one.
  329. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
  330. + mQueueName + "]: ordered="
  331. + r.ordered + " receiver=" + r.receiver);
  332. r.state = BroadcastRecord.IDLE;
  333. scheduleBroadcastsLocked();
  334. } else {
  335. if (filter.receiverList != null) {
  336. maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
  337. // r is guaranteed ordered at this point, so we know finishReceiverLocked()
  338. // will get a callback and handle the activity start token lifecycle.
  339. }
  340. if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
  341. scheduleTempWhitelistLocked(filter.owningUid,
  342. brOptions.getTemporaryAppWhitelistDuration(), r);
  343. }
  344. }
  345. return;
  346. }
  347. // Hard case: need to instantiate the receiver, possibly
  348. // starting its application process to host it.
  349. //对于静态注册的广播接收者 对各种权限进行判断处理,跟之前的并行广播类似。
  350. ResolveInfo info =
  351. (ResolveInfo)nextReceiver;
  352. ComponentName component = new ComponentName(
  353. info.activityInfo.applicationInfo.packageName,
  354. info.activityInfo.name);
  355. boolean skip = false;
  356. if (brOptions != null &&
  357. (info.activityInfo.applicationInfo.targetSdkVersion
  358. < brOptions.getMinManifestReceiverApiLevel() ||
  359. info.activityInfo.applicationInfo.targetSdkVersion
  360. > brOptions.getMaxManifestReceiverApiLevel())) {
  361. skip = true;
  362. }
  363. if (!skip && !mService.validateAssociationAllowedLocked(r.callerPackage, r.callingUid,
  364. component.getPackageName(), info.activityInfo.applicationInfo.uid)) {
  365. Slog.w(TAG, "Association not allowed: broadcasting "
  366. + r.intent.toString()
  367. + " from " + r.callerPackage + " (pid=" + r.callingPid
  368. + ", uid=" + r.callingUid + ") to " + component.flattenToShortString());
  369. skip = true;
  370. }
  371. if (!skip) {
  372. skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
  373. r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
  374. if (skip) {
  375. Slog.w(TAG, "Firewall blocked: broadcasting "
  376. + r.intent.toString()
  377. + " from " + r.callerPackage + " (pid=" + r.callingPid
  378. + ", uid=" + r.callingUid + ") to " + component.flattenToShortString());
  379. }
  380. }
  381. int perm = mService.checkComponentPermission(info.activityInfo.permission,
  382. r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
  383. info.activityInfo.exported);
  384. if (!skip && perm != PackageManager.PERMISSION_GRANTED) {
  385. if (!info.activityInfo.exported) {
  386. Slog.w(TAG, "Permission Denial: broadcasting "
  387. + r.intent.toString()
  388. + " from " + r.callerPackage + " (pid=" + r.callingPid
  389. + ", uid=" + r.callingUid + ")"
  390. + " is not exported from uid " + info.activityInfo.applicationInfo.uid
  391. + " due to receiver " + component.flattenToShortString());
  392. } else {
  393. Slog.w(TAG, "Permission Denial: broadcasting "
  394. + r.intent.toString()
  395. + " from " + r.callerPackage + " (pid=" + r.callingPid
  396. + ", uid=" + r.callingUid + ")"
  397. + " requires " + info.activityInfo.permission
  398. + " due to receiver " + component.flattenToShortString());
  399. }
  400. skip = true;
  401. } else if (!skip && info.activityInfo.permission != null) {
  402. final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
  403. if (opCode != AppOpsManager.OP_NONE
  404. && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
  405. r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
  406. Slog.w(TAG, "Appop Denial: broadcasting "
  407. + r.intent.toString()
  408. + " from " + r.callerPackage + " (pid="
  409. + r.callingPid + ", uid=" + r.callingUid + ")"
  410. + " requires appop " + AppOpsManager.permissionToOp(
  411. info.activityInfo.permission)
  412. + " due to registered receiver "
  413. + component.flattenToShortString());
  414. skip = true;
  415. }
  416. }
  417. if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
  418. r.requiredPermissions != null && r.requiredPermissions.length > 0) {
  419. for (int i = 0; i < r.requiredPermissions.length; i++) {
  420. String requiredPermission = r.requiredPermissions[i];
  421. try {
  422. perm = AppGlobals.getPackageManager().
  423. checkPermission(requiredPermission,
  424. info.activityInfo.applicationInfo.packageName,
  425. UserHandle
  426. .getUserId(info.activityInfo.applicationInfo.uid));
  427. } catch (RemoteException e) {
  428. perm = PackageManager.PERMISSION_DENIED;
  429. }
  430. if (perm != PackageManager.PERMISSION_GRANTED) {
  431. Slog.w(TAG, "Permission Denial: receiving "
  432. + r.intent + " to "
  433. + component.flattenToShortString()
  434. + " requires " + requiredPermission
  435. + " due to sender " + r.callerPackage
  436. + " (uid " + r.callingUid + ")");
  437. skip = true;
  438. break;
  439. }
  440. int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
  441. if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
  442. && mService.mAppOpsService.noteOperation(appOp,
  443. info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
  444. != AppOpsManager.MODE_ALLOWED) {
  445. Slog.w(TAG, "Appop Denial: receiving "
  446. + r.intent + " to "
  447. + component.flattenToShortString()
  448. + " requires appop " + AppOpsManager.permissionToOp(
  449. requiredPermission)
  450. + " due to sender " + r.callerPackage
  451. + " (uid " + r.callingUid + ")");
  452. skip = true;
  453. break;
  454. }
  455. }
  456. }
  457. if (!skip && r.appOp != AppOpsManager.OP_NONE
  458. && mService.mAppOpsService.noteOperation(r.appOp,
  459. info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
  460. != AppOpsManager.MODE_ALLOWED) {
  461. Slog.w(TAG, "Appop Denial: receiving "
  462. + r.intent + " to "
  463. + component.flattenToShortString()
  464. + " requires appop " + AppOpsManager.opToName(r.appOp)
  465. + " due to sender " + r.callerPackage
  466. + " (uid " + r.callingUid + ")");
  467. skip = true;
  468. }
  469. boolean isSingleton = false;
  470. try {
  471. isSingleton = mService.isSingleton(info.activityInfo.processName,
  472. info.activityInfo.applicationInfo,
  473. info.activityInfo.name, info.activityInfo.flags);
  474. } catch (SecurityException e) {
  475. Slog.w(TAG, e.getMessage());
  476. skip = true;
  477. }
  478. if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
  479. if (ActivityManager.checkUidPermission(
  480. android.Manifest.permission.INTERACT_ACROSS_USERS,
  481. info.activityInfo.applicationInfo.uid)
  482. != PackageManager.PERMISSION_GRANTED) {
  483. Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
  484. + " requests FLAG_SINGLE_USER, but app does not hold "
  485. + android.Manifest.permission.INTERACT_ACROSS_USERS);
  486. skip = true;
  487. }
  488. }
  489. if (!skip && info.activityInfo.applicationInfo.isInstantApp()
  490. && r.callingUid != info.activityInfo.applicationInfo.uid) {
  491. Slog.w(TAG, "Instant App Denial: receiving "
  492. + r.intent
  493. + " to " + component.flattenToShortString()
  494. + " due to sender " + r.callerPackage
  495. + " (uid " + r.callingUid + ")"
  496. + " Instant Apps do not support manifest receivers");
  497. skip = true;
  498. }
  499. if (!skip && r.callerInstantApp
  500. && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0
  501. && r.callingUid != info.activityInfo.applicationInfo.uid) {
  502. Slog.w(TAG, "Instant App Denial: receiving "
  503. + r.intent
  504. + " to " + component.flattenToShortString()
  505. + " requires receiver have visibleToInstantApps set"
  506. + " due to sender " + r.callerPackage
  507. + " (uid " + r.callingUid + ")");
  508. skip = true;
  509. }
  510. if (r.curApp != null && r.curApp.isCrashing()) {
  511. // If the target process is crashing, just skip it.
  512. Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
  513. + " to " + r.curApp + ": process crashing");
  514. skip = true;
  515. }
  516. if (!skip) {
  517. boolean isAvailable = false;
  518. try {
  519. isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
  520. info.activityInfo.packageName,
  521. UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
  522. } catch (Exception e) {
  523. // all such failures mean we skip this receiver
  524. Slog.w(TAG, "Exception getting recipient info for "
  525. + info.activityInfo.packageName, e);
  526. }
  527. if (!isAvailable) {
  528. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  529. "Skipping delivery to " + info.activityInfo.packageName + " / "
  530. + info.activityInfo.applicationInfo.uid
  531. + " : package no longer available");
  532. skip = true;
  533. }
  534. }
  535. // If permissions need a review before any of the app components can run, we drop
  536. // the broadcast and if the calling app is in the foreground and the broadcast is
  537. // explicit we launch the review UI passing it a pending intent to send the skipped
  538. // broadcast.
  539. if (!skip) {
  540. if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
  541. info.activityInfo.packageName, UserHandle.getUserId(
  542. info.activityInfo.applicationInfo.uid))) {
  543. skip = true;
  544. }
  545. }
  546. // This is safe to do even if we are skipping the broadcast, and we need
  547. // this information now to evaluate whether it is going to be allowed to run.
  548. final int receiverUid = info.activityInfo.applicationInfo.uid;
  549. // If it's a singleton, it needs to be the same app or a special app
  550. if (r.callingUid != Process.SYSTEM_UID && isSingleton
  551. && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
  552. info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
  553. }
  554. //该receiver所对应的进程已经运行,则直接处理
  555. String targetProcess = info.activityInfo.processName;
  556. ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
  557. info.activityInfo.applicationInfo.uid, false);
  558. if (!skip) {
  559. final int allowed = mService.getAppStartModeLocked(
  560. info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
  561. info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
  562. if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
  563. // We won't allow this receiver to be launched if the app has been
  564. // completely disabled from launches, or it was not explicitly sent
  565. // to it and the app is in a state that should not receive it
  566. // (depending on how getAppStartModeLocked has determined that).
  567. if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
  568. Slog.w(TAG, "Background execution disabled: receiving "
  569. + r.intent + " to "
  570. + component.flattenToShortString());
  571. skip = true;
  572. } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
  573. || (r.intent.getComponent() == null
  574. && r.intent.getPackage() == null
  575. && ((r.intent.getFlags()
  576. & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
  577. && !isSignaturePerm(r.requiredPermissions))) {
  578. mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
  579. component.getPackageName());
  580. Slog.w(TAG, "Background execution not allowed: receiving "
  581. + r.intent + " to "
  582. + component.flattenToShortString());
  583. skip = true;
  584. }
  585. }
  586. }
  587. if (!skip && !Intent.ACTION_SHUTDOWN.equals(r.intent.getAction())
  588. && !mService.mUserController
  589. .isUserRunning(UserHandle.getUserId(info.activityInfo.applicationInfo.uid),
  590. 0 /* flags */)) {
  591. skip = true;
  592. Slog.w(TAG,
  593. "Skipping delivery to " + info.activityInfo.packageName + " / "
  594. + info.activityInfo.applicationInfo.uid + " : user is not running");
  595. }
  596. /// M: DuraSpeed @{
  597. boolean isSuppress = false;
  598. isSuppress = mService.mAmsExt.onBeforeStartProcessForStaticReceiver(
  599. info.activityInfo.packageName);
  600. if (isSuppress) {
  601. skip = true;
  602. }
  603. /// @}
  604. /// M: For ago performance
  605. if (!mService.mAmsExt.isComponentNeedsStart(info.activityInfo.packageName,
  606. "static_broadcast")) {
  607. skip = true;
  608. }
  609. if (skip) {
  610. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  611. "Skipping delivery of ordered [" + mQueueName + "] "
  612. + r + " for reason described above");
  613. r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
  614. r.receiver = null;
  615. r.curFilter = null;
  616. r.state = BroadcastRecord.IDLE;
  617. r.manifestSkipCount++;
  618. scheduleBroadcastsLocked();
  619. return;
  620. }
  621. r.manifestCount++;
  622. r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
  623. r.state = BroadcastRecord.APP_RECEIVE;
  624. r.curComponent = component;
  625. r.curReceiver = info.activityInfo;
  626. if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
  627. Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
  628. + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
  629. + receiverUid);
  630. }
  631. if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
  632. scheduleTempWhitelistLocked(receiverUid,
  633. brOptions.getTemporaryAppWhitelistDuration(), r);
  634. }
  635. // Broadcast is being executed, its package can't be stopped.
  636. try {
  637. AppGlobals.getPackageManager().setPackageStoppedState(
  638. r.curComponent.getPackageName(), false, r.userId);
  639. } catch (RemoteException e) {
  640. } catch (IllegalArgumentException e) {
  641. Slog.w(TAG, "Failed trying to unstop package "
  642. + r.curComponent.getPackageName() + ": " + e);
  643. }
  644. // Is this receiver's application already running?
  645. if (app != null && app.thread != null && !app.killed) {
  646. try {
  647. app.addPackage(info.activityInfo.packageName,
  648. info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
  649. maybeAddAllowBackgroundActivityStartsToken(app, r);
  650. processCurBroadcastLocked(r, app, skipOomAdj);
  651. return;
  652. } catch (RemoteException e) {
  653. Slog.w(TAG, "Exception when sending broadcast to "
  654. + r.curComponent, e);
  655. } catch (RuntimeException e) {
  656. Slog.wtf(TAG, "Failed sending broadcast to "
  657. + r.curComponent + " with " + r.intent, e);
  658. // If some unexpected exception happened, just skip
  659. // this broadcast. At this point we are not in the call
  660. // from a client, so throwing an exception out from here
  661. // will crash the entire system instead of just whoever
  662. // sent the broadcast.
  663. logBroadcastReceiverDiscardLocked(r);
  664. finishReceiverLocked(r, r.resultCode, r.resultData,
  665. r.resultExtras, r.resultAbort, false);
  666. scheduleBroadcastsLocked();
  667. // We need to reset the state if we failed to start the receiver.
  668. r.state = BroadcastRecord.IDLE;
  669. return;
  670. }
  671. // If a dead object exception was thrown -- fall through to
  672. // restart the application.
  673. }
  674. // Not running -- get it started, to be executed when the app comes up.
  675. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  676. "Need to start app ["
  677. + mQueueName + "] " + targetProcess + " for broadcast " + r);
  678. //该receiver所对应的进程尚未启动,则创建该进程
  679. if ((r.curApp=mService.startProcessLocked(targetProcess,
  680. info.activityInfo.applicationInfo, true,
  681. r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
  682. new HostingRecord("broadcast", r.curComponent),
  683. (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
  684. == null) {
  685. // Ah, this recipient is unavailable. Finish it if necessary,
  686. // and mark the broadcast record as ready for the next.
  687. //启动失败的情况
  688. Slog.w(TAG, "Unable to launch app "
  689. + info.activityInfo.applicationInfo.packageName + "/"
  690. + receiverUid + " for broadcast "
  691. + r.intent + ": process is bad");
  692. logBroadcastReceiverDiscardLocked(r);
  693. finishReceiverLocked(r, r.resultCode, r.resultData,
  694. r.resultExtras, r.resultAbort, false);
  695. scheduleBroadcastsLocked();
  696. r.state = BroadcastRecord.IDLE;
  697. return;
  698. }
  699. maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);
  700. mPendingBroadcast = r;
  701. mPendingBroadcastRecvIndex = recIdx;
  702. }

  上面的代码很长总的可以分为两部分:1.处理并行广播的情况。2 .处理串行广播的情况,也就我们说的有序广播。 而ANR只有是有序广播的时候才会发生。

    归纳是:1.while 循环先把并行广播处理完成。

               2. 从mDispatcher.getNextBroadcastLocked 获取 BroadcastRecord实例,如果是空的话,说明没有广播需要处理,就返回。

              3.对总的 numReceivers时间进行判断,判断依据是:2 * mConstants.TIMEOUT * numReceivers 。如果超过这个时间就broadcastTimeoutLocked,产生ANR。系统不仅对单个receiver的时间有管控,总的receivers时间也有管控。

             4 . cancelBroadcastTimeoutLocked,取消超时广播,这个对广播第一个receiver来说没什么意义,主要是对第二个之后的receiver的影响。

            5. 如果是第一个receiver的话就把分发时间付给它。  if (recIdx == 0) {r.dispatchTime = r.receiverTime}。

           6 .发生一个延迟广播 setBroadcastTimeoutLocked(timeoutTime),时间是10s ,如果超过这个时间还没有执行cancelBroadcastTimeoutLocked 。就会引发ANR。那么提个问题,什么情况下会执行cancelBroadcastTimeoutLocked 。答案是,当广播结束完会调用AMS finishReceiver方法,nextreceiver ,执行  r.queue.processNextBroadcastLocked。由回到processNextBroadcastLocked方法中,然后就会调用cancelBroadcastTimeoutLocked

       7.如果是动态广播,就比较简单,执行deliverToRegisteredReceiverLocked,静态广播 要判断各种权限问题,还需要判断广播的进程是否存在,如果不存在需要创建新的进程。

  1. public void finishReceiver(IBinder who, int resultCode, String resultData,
  2. Bundle resultExtras, boolean resultAbort, int flags) {
  3. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + who);
  4. // Refuse possible leaked file descriptors
  5. if (resultExtras != null && resultExtras.hasFileDescriptors()) {
  6. throw new IllegalArgumentException("File descriptors passed in Bundle");
  7. }
  8. final long origId = Binder.clearCallingIdentity();
  9. try {
  10. boolean doNext = false;
  11. BroadcastRecord r;
  12. BroadcastQueue queue;
  13. synchronized(this) {
  14. if (isOnOffloadQueue(flags)) {
  15. queue = mOffloadBroadcastQueue;
  16. } else {
  17. queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
  18. ? mFgBroadcastQueue : mBgBroadcastQueue;
  19. }
  20. r = queue.getMatchingOrderedReceiver(who);
  21. if (r != null) {
  22. doNext = r.queue.finishReceiverLocked(r, resultCode,
  23. resultData, resultExtras, resultAbort, true);
  24. }
  25. if (doNext) {
  26. r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
  27. }
  28. // updateOomAdjLocked() will be done here
  29. trimApplicationsLocked(OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
  30. }
  31. } finally {
  32. Binder.restoreCallingIdentity(origId);
  33. }
  34. }

      3.2  broadcastTimeoutLocked    

      

  1. final void broadcastTimeoutLocked(boolean fromMsg) {
  2. if (fromMsg) {
  3. mPendingBroadcastTimeoutMessage = false;
  4. /// M: ANR Debug Mechanism
  5. mService.mAnrManager.removeBroadcastMonitorMessage();
  6. }
  7. //有序广播已经执行结束,或者广播接受者已经finish了。
  8. if (mDispatcher.isEmpty() || mDispatcher.getActiveBroadcastLocked() == null) {
  9. return;
  10. }
  11. long now = SystemClock.uptimeMillis();
  12. BroadcastRecord r = mDispatcher.getActiveBroadcastLocked();
  13. if (fromMsg) {
  14. /// M: ANR Debug Mechanism @{
  15. if (mService.mAnrManager.isAnrDeferrable()) {
  16. setBroadcastTimeoutLocked(SystemClock.uptimeMillis() + mConstants.TIMEOUT);
  17. return;
  18. } /// @}
  19. if (!mService.mProcessesReady) {
  20. // Only process broadcast timeouts if the system is ready; some early
  21. // broadcasts do heavy work setting up system facilities
  22. return;
  23. }
  24. // If the broadcast is generally exempt from timeout tracking, we're done
  25. if (r.timeoutExempt) {
  26. if (DEBUG_BROADCAST) {
  27. Slog.i(TAG_BROADCAST, "Broadcast timeout but it's exempt: "
  28. + r.intent.getAction());
  29. }
  30. return;
  31. }
  32. long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
  33. //如果现在的时间小于超时时间,说明还没有超时,就再执行setBroadcastTimeoutLocked,TIMEOUT=10s
  34. if (timeoutTime > now) {
  35. // We can observe premature timeouts because we do not cancel and reset the
  36. // broadcast timeout message after each receiver finishes. Instead, we set up
  37. // an initial timeout then kick it down the road a little further as needed
  38. // when it expires.
  39. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
  40. "Premature timeout ["
  41. + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
  42. + timeoutTime);
  43. setBroadcastTimeoutLocked(timeoutTime);
  44. return;
  45. }
  46. }
  47. //已经finish receiver ,也就是在执行 finishReceiverLocked方法时
  48. if (r.state == BroadcastRecord.WAITING_SERVICES) {
  49. // In this case the broadcast had already finished, but we had decided to wait
  50. // for started services to finish as well before going on. So if we have actually
  51. // waited long enough time timeout the broadcast, let's give up on the whole thing
  52. // and just move on to the next.
  53. Slog.i(TAG, "Waited long enough for: " + (r.curComponent != null
  54. ? r.curComponent.flattenToShortString() : "(null)"));
  55. r.curComponent = null;
  56. r.state = BroadcastRecord.IDLE;
  57. processNextBroadcast(false);
  58. return;
  59. }
  60. // If the receiver app is being debugged we quietly ignore unresponsiveness, just
  61. // tidying up and moving on to the next broadcast without crashing or ANRing this
  62. // app just because it's stopped at a breakpoint.
  63. final boolean debugging = (r.curApp != null && r.curApp.isDebugging());
  64. Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
  65. + ", started " + (now - r.receiverTime) + "ms ago");
  66. r.receiverTime = now;
  67. if (!debugging) {
  68. r.anrCount++;
  69. }
  70. ProcessRecord app = null;
  71. String anrMessage = null;
  72. Object curReceiver;
  73. if (r.nextReceiver > 0) {
  74. curReceiver = r.receivers.get(r.nextReceiver-1);
  75. r.delivery[r.nextReceiver-1] = BroadcastRecord.DELIVERY_TIMEOUT;
  76. } else {
  77. curReceiver = r.curReceiver;
  78. }
  79. Slog.w(TAG, "Receiver during timeout of " + r + " : " + curReceiver);
  80. logBroadcastReceiverDiscardLocked(r);
  81. //查询App进程
  82. if (curReceiver != null && curReceiver instanceof BroadcastFilter) {
  83. BroadcastFilter bf = (BroadcastFilter)curReceiver;
  84. if (bf.receiverList.pid != 0
  85. && bf.receiverList.pid != ActivityManagerService.MY_PID) {
  86. synchronized (mService.mPidsSelfLocked) {
  87. app = mService.mPidsSelfLocked.get(
  88. bf.receiverList.pid);
  89. }
  90. }
  91. } else {
  92. app = r.curApp;
  93. }
  94. if (app != null) {//如果进程还存在没有被杀死的话创建anrMessage
  95. anrMessage = "Broadcast of " + r.intent.toString();
  96. }
  97. if (mPendingBroadcast == r) {
  98. mPendingBroadcast = null;
  99. }
  100. // Move on to the next receiver.
  101. //关闭receiver 启动下一个receiver
  102. finishReceiverLocked(r, r.resultCode, r.resultData,
  103. r.resultExtras, r.resultAbort, false);
  104. scheduleBroadcastsLocked();
  105. if (!debugging && anrMessage != null) {
  106. // Post the ANR to the handler since we do not want to process ANRs while
  107. // potentially holding our lock.
  108. mHandler.post(new AppNotResponding(app, anrMessage));
  109. }
  110. }
  1. //向event log 里面写log,关键字是:am_broadcast_discard_app
  2. final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
  3. final int logIndex = r.nextReceiver - 1;
  4. if (logIndex >= 0 && logIndex < r.receivers.size()) {
  5. Object curReceiver = r.receivers.get(logIndex);
  6. if (curReceiver instanceof BroadcastFilter) {
  7. BroadcastFilter bf = (BroadcastFilter) curReceiver;
  8. EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
  9. bf.owningUserId, System.identityHashCode(r),
  10. r.intent.getAction(), logIndex, System.identityHashCode(bf));
  11. } else {
  12. ResolveInfo ri = (ResolveInfo) curReceiver;
  13. EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
  14. UserHandle.getUserId(ri.activityInfo.applicationInfo.uid),
  15. System.identityHashCode(r), r.intent.getAction(), logIndex, ri.toString());
  16. }
  17. } else {
  18. if (logIndex < 0) Slog.w(TAG,
  19. "Discarding broadcast before first receiver is invoked: " + r);
  20. EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
  21. -1, System.identityHashCode(r),
  22. r.intent.getAction(),
  23. r.nextReceiver,
  24. "NONE");
  25. }
  26. }

3.3  mHandler.post(new AppNotResponding(app, anrMessage))

  1. public void run() {
  2. mApp.appNotResponding(null, null, null, null, false, mAnnotation);
  3. }

 mApp是ProcessRecord ,所有会调用ProcessRecord 的appNotResponding,这部分上一章有说过:深入理解 ANR 触发原理:一

 

所以对于Broadcast ANR问题算研究完毕。那么对于开始提的两个问题我们就回答了

 1.broadcast 什么情况下会ANR ?

  答:1.所属的广播必须是有序广播,并行广播不会产生ANR问题。

         2.发生有序广播,receivers>=2。如果只有一个那么也是不会产生ANR.

         3 前台超时10s,后台超时60s,如果是多个receivers 那么总的时间不能超过 2 * mConstants.TIMEOUT * numReceivers

         4.如果 有序广播是最后一个执行者,或者进程已经被杀掉。也不会产生ANR.   if (mDispatcher.isEmpty() || mDispatcher.getActiveBroadcastLocked() == null) {
            return;
        }

         5.或者在执行broadcastTimeoutLocked 方法是,receiver在执行finishReceiverLocked的方法。

 

2.ANR会有哪些log

答:1.  Slog.w(TAG, "Hung broadcast ["
                            + mQueueName + "] discarded after timeout failure:"
                            + " now=" + now
                            + " dispatchTime=" + r.dispatchTime
                            + " startTime=" + r.receiverTime
                            + " intent=" + r.intent
                            + " numReceivers=" + numReceivers
                            + " nextReceiver=" + r.nextReceiver
                            + " state=" + r.state);

  2. 在event log 里面能搜索到 am_broadcast_discard_app  ,是由logBroadcastReceiverDiscardLocked 方法得来。

 3 .Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
                + ", started " + (now - r.receiverTime) + "ms ago");

 4.  Slog.w(TAG, "Receiver during timeout of " + r + " : " + curReceiver);

 

 5.   EventLog.writeEvent(EventLogTags.AM_ANR, userId, pid, processName, info.flags,
                    annotation); 这个log的输出在某些情况是不会输出的,用户定义了ANR的处理。还有就是另外几种情况,isShuttingDown ,isNotResponding ,isCrashing ,killedByAm,killed

   6 .生成 data/anr/文件,里面保存了一些pid的trace 信息以及cpu信息。

  7.DropBoxManager也会输出一些anr的trace信息。

  8 .如果是前台进程还会有一个AppNotRespondingDialog。
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/989697
推荐阅读
相关标签
  

闽ICP备14008679号