Android12系统源码分析:NativeTombstoneManager
Android12系统源码分析:NativeTombstoneManager
概述
android12新增的system_rver进程(LocalService)本地服务,⽤于管理native tombstones。
该服务在开机Systemerver初始化流程启动,添加到LocalService,然后启动⼀个ServiceThread线程⽤于(mHandler.post)处理本服务的业务。NativeTombstoneManager的功能主要是:
监听/data/tombstones ⽬录⽂件变动,解析为TombstoneFile 对象保存,通知dropbox
特定tombstones ⽂件删除
特定tombstones ⽂件检索
值得关注的是AMS对该服务的使⽤,也是Android11新增API:getHistoricalProcessExitReasons()软件架构如图:BootReceiver SystemServer 开机启动仅添加本地服务LocalServices.addService NativeTombstoneManager.class SystemService AppExitInfoTracker Nativ eTombs toneManager tombs
toneServ ic e void clearHistoryProcessExitInfo()ActivityManagerService Nativ eTombs toneManager tombs toneServ ic e public getHistoricalProcessExitReasons()暴露接⼝给app
NativeTombstoneManagerService
Nativ eTombs toneManager mManager
public v oid onStart()public v oid onBootPhas e()TombstoneFile by:qiucheng
ParcelFileDescriptorRetriever发形
NativeTombstoneManager
priv ate v oid handleTombs tone()priv ate v oid handleProtoTombs tone()public v oid c ollec tTombs tones ()服务核⼼实现TombstoneWatcher 监听⽬录:/data/tombstones FileObrver 图:NativeTombstoneManager类图
启动流程
SystemServer SystemServer SystemServiceManager SystemServiceManager NativeTombstoneMa
nagerService NativeTombstoneManagerService NativeTombstoneManager NativeTombstoneManager LocalServices
LocalServices 1startCoreServices
23by:qiucheng
4NativeTombstoneManager党歌曲
八股辫
567addService(NativeTombstoneManager.class
8startOtherServices
9startBootPha
PHASE_ACTIVITY_MANAGER_READY
10onBootPha
111213registerForPackageRemoval
14handleTombstone
图:NativeTombstoneManager服务启动时序图
服务⽐较简单,和其他SystemServer启动的服务⼀样,
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManagerService.java public class NativeTombstoneManagerService extends SystemService {
private NativeTombstoneManager mManager;
@Override
public void onStart() {
mManager = new NativeTombstoneManager(getContext());
//仅添加本地服务,没有binder服务
LocalServices.addService(NativeTombstoneManager.class, mManager);
}
@Override
public void onBootPha(int pha) {方便面制作过程
if (pha == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
}
}
}
本服务也是SystemService⼯具类的⼦类,通过重写onStart、onBootPha获得代码流程
在onStart中初始化真正的服务实现NativeTombstoneManager,实例化后添加到LocalServices
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java
public final class NativeTombstoneManager {
NativeTombstoneManager(Context context) {
/
/启动handler线程,⽤于后续处理本服务的业务
final ServiceThread thread = new ServiceThread(TAG + ":tombstoneWatcher",
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
thread.start();
mHandler = ThreadHandler();
//启动⽂件监听/data/tombstones
mWatcher = new TombstoneWatcher();
mWatcher.startWatching();
}
void onSystemReady() {
registerForUrRemoval();
registerForPackageRemoval();
// 开机阶段先扫描⼀次/data/tombstones⽬录
鸡肠
mHandler.post(() -> {
final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) {
if (tombstoneFiles[i].isFile()) {
handleTombstone(tombstoneFiles[i]);
开机流程有三个动作
启动handler线程,⽤于后续处理本服务的业务
TombstoneWatcher启动⽂件监听/data/tombstones
开机阶段先扫描⼀次/data/tombstones⽬录
看⼀下handleTombstone
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java
private void handleTombstone(File path) {
final String filename = Name();
if (!filename.startsWith("tombstone_")) {
return;
}
if (dsWith(".pb")) {
handleProtoTombstone(path);
BootReceiver.addTombstoneToDropBox(mContext, path, true);
} el {
BootReceiver.addTombstoneToDropBox(mContext, path, fal);
如果是以pb结尾的原型⽂件,则handleProtoTombstone⽅法中为该⽂件⽣成TombstoneFile对象,并添加到数据结构private final SparArray<TombstoneFile> mTombstones;
并且,每个新⽣成的tombstone⽂件都会同步给dropbox
新⽂件的监听
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java
class TombstoneWatcher extends FileObrver {
TombstoneWatcher() {
super(TOMBSTONE_DIR, FileObrver.CREATE | FileObrver.MOVED_TO);
}
@Override
public void onEvent(int event, @Nullable String path) {
mHandler.post(() -> {
handleTombstone(new File(TOMBSTONE_DIR, path));
});
内部类TombstoneWatcher,当⽬录/data/tombstones有⽂件⽣成时,回调到onEvent,然后通过handleTombstone⽅法做处理AciivtyManager#getHistoricalProcessExitReasons
ActivityManager ActivityManager ActivityManagerService
ActivityManagerService
LocalServices
LocalServices
NativeTombstoneManager
NativeTombstoneManager
getHistoricalProcessExitReasons
enforceNotIsolatedCaller
enforceDumpPermissionForPackage
by:qiucheng
getService
collectTombstones
new ParceledListSlice<ApplicationExitInfo>(results)
图:getHistoricalProcessExitReasons⽅法时序图
需要注意返回的数据结构的处理ApplicationExitInfo。
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java
public void collectTombstones(ArrayList<ApplicationExitInfo> output, int callingUid, int pid, int maxNum) {
CompletableFuture<Object> future = new CompletableFuture<>();
if (!UrHandle.isApp(callingUid)) {
return;
}
final int urId = UrId(callingUid);
final int appId = AppId(callingUid);
mHandler.post(() -> {
boolean appendedTombstones = fal;
synchronized (mLock) {
final int tombstonesSize = mTombstones.size();
tombstoneIter:
//遍历所有已知tombstoe,
/
/如果urid和appid和reason匹配
//则返回请求的数量的tombstone
for (int i = 0; i < tombstonesSize; ++i) {
TombstoneFile tombstone = mTombstones.valueAt(i);
if (tombstone.matches(Optional.of(urId), Optional.of(appId))) {
if (pid != 0 && tombstone.mPid != pid) {
continue;
}
//reason判断
// Try to attach to an existing REASON_CRASH_NATIVE.
final int outputSize = output.size();
for (int j = 0; j < outputSize; ++j) {
ApplicationExitInfo exitInfo = (j);
if (tombstone.matches(exitInfo)) {
exitInfo.PfdRetriever());
continue tombstoneIter;
}
}
//请求数量判断
if (output.size() < maxNum) {
appendedTombstones = true;
output.AppExitInfo());
}
}
}
}
//如果超过⼀个则按时间戳排序
if (appendedTombstones) {
Collections.sort(output, (lhs, rhs) -> {
// Reports should be ordered with newest reports first.
long diff = Timestamp() - Timestamp();
if (diff < 0) {
return -1;
面部骨骼} el if (diff == 0) {
return 0;
} el {
return 1;
}
});
}
});
try {
<();
遍历所有已知tombstoe,如果urid和appid和reason匹配则返回请求的数量的tombstone
如果数量超过⼀个则按时间戳排序
值得注意的是CompletableFuture,函数式编程,可参考:
tombstone⽂件的清理
元旦节的作文
⽬前有两种场景会清理⽂件
主动调⽤接⼝删除,AppExitInfoTracker-->purge()
app被卸载时,registerForPackageRemoval-->purgePackage()-->purge() clearHistoryProcessExitInfo
frameworks/ba/rvices/core/java/com/android/rver/am/AppExitInfoTracker.java
void clearHistoryProcessExitInfo(String packageName, int urId) {
NativeTombstoneManager tombstoneService = Service(
NativeTombstoneManager.class);
Optional<Integer> appId = pty();
if (TextUtils.isEmpty(packageName)) {
synchronized (mLock) {
removeByUrIdLocked(urId);
}
} el {
final int uid = PackageUid(packageName, PackageManager.MATCH_ALL, urId);
appId = Optional.AppId(uid));
synchronized (mLock) {
removePackageLocked(packageName, uid, true, urId);
}
}自律手抄报
tombstoneService.purge(Optional.of(urId), appId);
schedulePersistProcessExitInfo(true);
}
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java
* Remove native tombstones matching a ur and/or app.
public void purge(Optional<Integer> urId, Optional<Integer> appId) {
mHandler.post(() -> {
synchronized (mLock) {
for (int i = mTombstones.size() - 1; i >= 0; --i) {
TombstoneFile tombstone = mTombstones.valueAt(i);
if (tombstone.matches(urId, appId)) {
tombstone.purge();
----------------------------------------------------------------------
static class TombstoneFile {
public void purge() {
if (!mPurged) {
try {
Os.FileDescriptor(), 0);
} catch (ErrnoException ex) {
Slog.e(TAG, "Failed to truncate tombstone", ex);
}
mPurged = true;
purgePackage
frameworks/ba/rvices/core/java/com/android/rver/os/NativeTombstoneManager.java private void registerForPackageRemoval() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
filter.addDataScheme("package");
@Override
public void onReceive(Context context, Intent intent) {
final int uid = IntExtra(Intent.EXTRA_UID, UrHandle.USER_NULL);
if (uid == UrHandle.USER_NULL) return;
final boolean allUrs = BooleanExtra(
Intent.EXTRA_REMOVED_FOR_ALL_USERS, fal);
purgePackage(uid, allUrs);
}
}, filter, null, mHandler);
}
---------------------------------------------
private void purgePackage(int uid, boolean allUrs) {
final int appId = AppId(uid);
Optional<Integer> urId;
if (allUrs) {
urId = pty();
} el {
urId = Optional.UrId(uid));
}
purge(urId, Optional.of(appId));
}
private void purgeUr(int uid) {
purge(Optional.of(uid), pty());
}
f服务启动时registerForPackageRemoval调⽤,开启对⼴播的监听:ACTION_PACKAGE_FULLY_REMOVED 当app卸载时,此处也删除其对应uid的tombstone⽂件
同这个包删除类似,还有⽤户删除时也会删对应的⽂件:
private void registerForUrRemoval() {
filter.addAction(Intent.ACTION_USER_REMOVED);