IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 系统persist应用 -> 正文阅读

[移动开发]Android 系统persist应用

引入
在Android系统App中(注意是系统App),都会添加一个persistent 属性,表明此应用是一个永久性应用,就是从系统一开机就一直运行,直到系统关机。他的另外一个特写是,服务被杀死后会自动重启,本篇就来一探究竟。

AndroidManifest.xml
android:persistent="true" 

启动

Android系统在启动时,ActivityManagerService 会调用systemReady 方法,在这里会调起所谓的 永久性应用:

public void systemReady(final Runnable goingCallback) {
        ...       
        try {
            List apps = AppGlobals.getPackageManager().getPersistentApplications(STOCK_PM_FLAGS);
            if (apps != null) {
                int N = apps.size();
                int i;                
                for (i=0; i<N; i++) {
                    ApplicationInfo info
                        = (ApplicationInfo)apps.get(i);   
                    if (info != null &&
                            !info.packageName.equals("android")) {
                        addAppLocked(info, false, null /* ABI override */);
                    }
                }
            }
        } catch (RemoteException ex) { 
        }

	...
    }

先来看看 getPersistentApplications(),它的定义在PKMS中:

public List<ApplicationInfo> getPersistentApplications(int flags) {
        final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();

        // reader
        synchronized (mPackages) {
            final Iterator<PackageParser.Package> i = mPackages.values().iterator();
            final int userId = UserHandle.getCallingUserId();
            while (i.hasNext()) {
                final PackageParser.Package p = i.next();
                if (p.applicationInfo != null
                        && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
                        && (!mSafeMode || isSystemApp(p))) {
                    PackageSetting ps = mSettings.mPackages.get(p.packageName);
                    if (ps != null) {
                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                ps.readUserState(userId), userId);
                        if (ai != null) {
                            finalList.add(ai);
                        }
                    }
                }
            }
        }

        return finalList;
    }

注意这里有过滤非系统App:isSystemApp§,只有系统App 才会添加到列表里面。
再回到传给AMS的addAppLocked()方法:

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
            String abiOverride) {
        ProcessRecord app;
     	...
        if (app == null) {
        	//这里启动进程
            app = newProcessRecordLocked(info, null, isolated, 0);
            mProcessNames.put(info.processName, app.uid, app);
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
            updateLruProcessLocked(app, false, null);
            updateOomAdjLocked();
        }

        // This package really, really can not be stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    info.packageName, false, UserHandle.getUserId(app.uid));
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + info.packageName + ": " + e);
        }

        if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
                == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
            app.persistent = true;
            app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
        }
        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
            mPersistentStartingProcesses.add(app);
            startProcessLocked(app, "added application", app.processName, abiOverride,
                    null /* entryPoint */, null /* entryPointArgs */);
        }
        return app;
    }

这里再次通过ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT 过滤非系统APP.
并设置 app.persistent = true;最后调用startProcessLocked()启动进程。
当进程启动成功之后,便会从mPersistentStartingProcesses里删除这个进程。

private final boolean attachApplicationLocked() {
	...
	//下面这段代码很关键,与Persisten服务重启有关
	final String processName = app.processName;
    try {
         AppDeathRecipient adr = new AppDeathRecipient(
                 app, pid, thread);
         thread.asBinder().linkToDeath(adr, 0);
         app.deathRecipient = adr;
     } catch (RemoteException e) {
         app.resetPackageList(mProcessStats);
         startProcessLocked(app, "link fail", processName);
         return false;
     }

	mPersistentStartingProcesses.remove(app);
	mProcessesOnHold.remove(app);
	if (!didSomething) {
	  updateOomAdjLocked();
	}
	...
}

补充:第三方应用及时带有persist属性,在进程创建时,也会被拦截

private static final int PERSISTENT_MASK =
            ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
            boolean isolated, int isolatedUid) {
        ...
        final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid);
        if (!mBooted && !mBooting
                && userId == UserHandle.USER_SYSTEM
                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
            // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
            r.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            r.persistent = true;
            r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
        }
      	...
        addProcessNameLocked(r);
        return r;
    }

服务重启

我们知道每一个应用进程里都会有一个ApplicationThread mAppThread对象,AMS通过它在AMS里的代理接口IApplicationThread与应用进程进行通信。(attachApplicationLocked 函数里面的第一个参数thread,就是一个应用进程在AMS里的代理对象)
在应用进程启动时,会调用ActivityThread的attach()方法将自己依附于AMS当中,也就是由AMS启动它并对它进行管理,attach()最终通过binder机制调用到AMS的attachApplicationLocked()方法。
再次贴出上面的关键代码:

private final boolean attachApplicationLocked(IApplicationThread thread...) {
	...
	//下面这段代码很关键,与Persisten服务重启有关
	final String processName = app.processName;
    try {
         AppDeathRecipient adr = new AppDeathRecipient(
                 app, pid, thread);
         thread.asBinder().linkToDeath(adr, 0);
         app.deathRecipient = adr;
     } catch (RemoteException e) {
         app.resetPackageList(mProcessStats);
         startProcessLocked(app, "link fail", processName);
         return false;
     }
	...
}

上面AppDeathRecipient 在AMS中声明如下:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final class AppDeathRecipient implements IBinder.DeathRecipient {
        final ProcessRecord mApp;
        final int mPid;
        final IApplicationThread mAppThread;

        AppDeathRecipient(ProcessRecord app, int pid,
                IApplicationThread thread) {
            if (DEBUG_ALL) Slog.v(
                TAG, "New death recipient " + this
                + " for thread " + thread.asBinder());
            mApp = app;
            mPid = pid;
            mAppThread = thread;
        }

        @Override
        public void binderDied() {
            if (DEBUG_ALL) Slog.v(
                TAG, "Death received in " + this
                + " for thread " + mAppThread.asBinder());
            synchronized(ActivityManagerService.this) {
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
    }

当应用进程死掉时,系统会回调由linkToDeath()注册的AppDeathRecipient对象的binderDied()方法。
有如下调用关系

binderDied();
	appDiedLocked();
		handleAppDiedLocked();
			cleanUpApplicationRecordLocked();

在cleanUpApplicationRecordLocked() 函数里面,我们看到了关键处理:

private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
            boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
        ...
        if (!app.persistent || app.isolated) {
            if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                    "Removing non-persistent process during cleanup: " + app);
            if (!replacingPid) {
                removeProcessNameLocked(app.processName, app.uid, app);
            }
            if (mHeavyWeightProcess == app) {
                mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
                        mHeavyWeightProcess.userId, 0));
                mHeavyWeightProcess = null;
            }
        } else if (!app.removed) {
            // This app is persistent, so we need to keep its record around.
            // If it is not already on the pending app list, add it there
            // and start a new process for it.
            if (mPersistentStartingProcesses.indexOf(app) < 0) {
                mPersistentStartingProcesses.add(app);
                restart = true;
            }
        }
    	...
        if (restart && !app.isolated) {
            // We have components that still need to be running in the
            // process, so re-launch it.
            if (index < 0) {
                ProcessList.remove(app.pid);
            }
            addProcessNameLocked(app);
            app.pendingStart = false;
            startProcessLocked(app, "restart", app.processName);
            return true;
        } else if (app.pid > 0 && app.pid != MY_PID) {
            ...
    }

可以看到,如果是非persist的进程死亡,则直接回收所有的进程资源。
persist的进程,就会再加入mPersistentStartingProcesses队列,然后等待重启。


彩蛋:利用persist 属性可以自启动的原理,我们也可以利用增加白名单方式,将进程加入persist属性, 实现常驻和自启动:

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            ...
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            // Begin  add for white list.
            //自定义的白名单
			List<String> persistentAdList = ThirdPartyPermissions.getPersistentAdApps(mContext);

            if (app != null && null != persistentAdList && persistentAdList.contains(processName)) {
                app.persistent = true;
                app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
                if (mPersistentStartingProcesses.indexOf(app) < 0) {
                    mPersistentStartingProcesses.add(app);
                }
            }
            // End add for white list.
            app.crashHandler = crashHandler;
            mProcessNames.put(processName, app.uid, app);
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
            checkTime(startTime, "startProcess: done creating new process record");
        }
       ...
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-26 22:18:57  更:2021-12-26 22:19:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:44:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码