bug 如图
发送短信后,实际发送一条,界面显示发送两条,问题本质是发件箱数据中确实写入了两条。
2020-01-03 15:41:01.532 6736-6736/? D/cczSettingPreference: sms:: inbox
2020-01-03 15:41:01.547 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0
2020-01-03 15:41:01.550 6736-6736/? D/cczSettingPreference: sms:: sent
2020-01-03 15:41:01.561 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0
2020-01-03 15:41:01.562 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0
2020-01-03 15:41:01.567 6736-6736/? D/cczSettingPreference: sms:: draft
2020-01-03 15:41:01.579 6736-6736/? D/cczSettingPreference: sms:: outbox
2020-01-03 15:41:01.592 6736-6736/? D/cczSettingPreference: sms:: failed
2020-01-03 15:41:01.604 6736-6736/? D/cczSettingPreference: sms:: queued
这个问题困扰了好久,经过3天的排查终于解决了,来整理下排查思路
一、先确定是 app 层的问题还是 framework 层问题(开始方向搞错了,浪费了两天时间,唉~)
二、简单理下短信发送流程
三、根据发件箱 URI 全局搜索
在网上找了个经典版短信app发送短信,是正常的,只写入一条已发送,由此简单判定不是framework的问题,后来证明是自己坑自己[笑哭]
在系统短信 Mms 源码中搜索如下关键字段
Telephony.Sms.CONTENT_URI
Telephony.Mms.Sent.CONTENT_URI;
Telephony.Sms.MESSAGE_TYPE_SENT
Telephony.Sms.moveMessageToFolder
几乎没找到相关的。简单说下短信发送流程,先将短信写入 queued 中,发送成功后移动到 MESSAGE_TYPE_SENT 中
注释 SmsReceiverService 中的 moveMessageToFolder( 方法,短信发送后会显示感叹号,而且数据库查不到这条短信。
开始复写了 moveMessageToFolder() 的逻辑一度以为已经修改好了,但其实根本不是这的问题
SqliteWrapper.update() 其实就是 Telephony.Sms.moveMessageToFolder() 的方法体
vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.java
@@ -517,11 +517,19 @@ public class SmsReceiverService extends Service implements ISmsReceiverServiceCa
// so we shouldn't move it to other boxes.just keep it in failed box.
if (smsType != Sms.MESSAGE_TYPE_FAILED) {
//move sms from out box to sent box
//cczheng add
Log.e(TAG, "handleSmsSent: don't need move message "+ uri + " to sent folder");
/*ContentValues values = new ContentValues(3);
values.put(Sms.TYPE, Sms.MESSAGE_TYPE_SENT);
values.put(Sms.ERROR_CODE, error);
values.put(Sms.READ, Integer.valueOf(0));
SqliteWrapper.update(getApplicationContext(), getContentResolver(), uri, values, null, null);*/
if (!Sms.moveMessageToFolder(this,
uri, Sms.MESSAGE_TYPE_SENT, error)) {
Log.e(TAG, "handleSmsSent: failed to move message "
+ uri + " to sent folder");
}
}
}
} finally {
后来在framework 中找到 SMSDispatcher.java
frameworks\opt\telephony\src\java\com\android\internal\telephony\SMSDispatcher.java
private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) {
if (!mIsText || !mPersistMessage ||
!SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) {
Rlog.d(TAG, "Persist SMS into packageName="+ mAppInfo.packageName);
return null;
}
Rlog.d(TAG, "Persist SMS into "
+ (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT"));
final ContentValues values = new ContentValues();
values.put(Sms.SUBSCRIPTION_ID, mSubId);
values.put(Sms.ADDRESS, mDestAddress);
values.put(Sms.BODY, mFullMessageText);
values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds
values.put(Sms.SEEN, 1);
values.put(Sms.READ, 1);
final String creator = mAppInfo != null ? mAppInfo.packageName : null;
if (!TextUtils.isEmpty(creator)) {
values.put(Sms.CREATOR, creator);
}
if (mDeliveryIntent != null) {
values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING);
}
if (errorCode != 0) {
values.put(Sms.ERROR_CODE, errorCode);
}
final long identity = Binder.clearCallingIdentity();
final ContentResolver resolver = context.getContentResolver();
try {
final Uri uri = resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values);
if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) {
// Since we can't persist a message directly into FAILED box,
// we have to update the column after we persist it into SENT box.
// The gap between the state change is tiny so I would not expect
// it to cause any serious problem
// TODO: we should add a "failed" URI for this in SmsProvider?
final ContentValues updateValues = new ContentValues(1);
updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/);
}
return uri;
} catch (Exception e) {
Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e);
return null;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
通过抓取MMS和经典版短信发送短信 radio log 比对
resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); 发现就是这货插入的发件箱,幕后真凶终于找到了。
MMS
01-01 08:03:39.403 1309 1309 D MtkGsmSMSDispatcher: Remove Tracker
01-01 08:03:39.403 1309 1309 D MtkGsmSMSDispatcher: mSTrackersQueue is empty
01-01 08:03:39.403 1309 1309 D SMSDispatcher: onSent isSinglePartOrLastPart=true
01-01 08:03:39.444 1309 3916 D SMSDispatcher: Persist SMS into SENT
01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.datatransfer does not have system signature
01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.op18.plugin does not have system signature
01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.apst.target does not have system signature
01-01 08:03:39.503 1309 3916 E SmsApplication: com.mediatek.backuprestore does not have system signature
01-01 08:03:39.505 1309 3916 E SmsApplication: com.mediatek.rcs.messageservice does not have system signature
01-01 08:03:39.505 1309 3916 E SmsApplication: com.android.mms does not have system signature
01-01 08:03:39.506 1309 1309 D SMSDispatcher: message reference number : 144
01-01 08:03:39.644 922 960 I AT : AT< +ECSQ: 15,53,1,1,1,-50,-352,7,19 (RIL_URC_READER, tid:0)
01-01 08:03:39.646 1133 1413 D RpNwSC : [0] Sig: gsm[0 53] c2k[55 90 120 -64 8] lte[99 88 12 47 2147483647] tds[2147483647] umts[0 0 0]
经典版短信
01-10 10:01:59.210 1368 1368 D MtkGsmSMSDispatcher: Remove Tracker
01-10 10:01:59.210 1368 1462 D RILJ : [4040]< RIL_REQUEST_IMS_SEND_SMS { mMessageRef = 147, mErrorCode = 0, mAckPdu = } [SUB0]
01-10 10:01:59.210 1368 1368 D MtkGsmSMSDispatcher: mSTrackersQueue is empty
01-10 10:01:59.210 1368 1368 D SMSDispatcher: onSent isSinglePartOrLastPart=true
01-10 10:01:59.218 1368 4708 D SMSDispatcher: Persist SMS into packageName=com.thinkyeah.message
01-10 10:01:59.218 1368 1368 D SMSDispatcher: message reference number : 147
01-10 10:02:00.000 769 3178 D MtkTelephonyRegistryEx: idMatchEx: rSubId=2147483647, subId=1, dSubId=1, rPhoneId=-1, phoneId=0
简单解决办法就是 persistSentMessageIfRequired() if 判断直接 return,bug就解决了