android配置应用开机启动,运行时不被kill

前言

在android系统开发过程中,我们有时候需要配置我们的某个应用,在开机后自动启动,并在设备低内存时不被kill。

如何实现

我们可以配置应用的AndroidManifest.xml

    <application android:name="PhoneApp"
            android:persistent="true"//设置成persistent应用,开机自动启动,kill后自动启动。
            android:label="@string/phoneAppLabel"
            android:icon="@mipmap/ic_launcher_phone"
            android:allowBackup="false"
            android:supportsRtl="true"
            android:usesCleartextTraffic="true"
            android:defaultToDeviceProtectedStorage="true"
            android:directBootAware="true">

配置peristent属性。

persist应用启动流程

ActivityManagerService.java

    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
        traceLog.traceBegin("PhaseActivityManagerReady");
        ...
            // Only start up encryption-aware persistent apps; once user is
            // unlocked we'll come back around and start unaware apps
            //启动persist应用,在启动launcher之前
            startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);     
            ...   
            
            if (bootingSystemUser) {
            	//启动luncher
                mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
            }
            ..
    }
            

继续看startPersistentApps 函数

    void startPersistentApps(int matchFlags) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;

        synchronized (this) {
            try {
                final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
                        .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
                for (ApplicationInfo app : apps) {
                    if (!"android".equals(app.packageName)) {
                        addAppLocked(app, null, false, null /* ABI override */);
                    }
                }
            } catch (RemoteException ex) {
            }
        }
    }

startPersistentApps 函数中,遍历当前系统中persistent属性的app,非android进程时执行addApplocked;

    @GuardedBy("this")
    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
            String abiOverride) {
        return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
                false /* mountExtStorageFull */, abiOverride);
    }

 // TODO: Move to ProcessList?
    @GuardedBy("this")
    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
            boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
                    info.uid, true);
        } else {
            app = null;
        }

        if (app == null) {
            app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
                    new HostingRecord("added application",
                            customProcess != null ? customProcess : info.processName));
            mProcessList.updateLruProcessLocked(app, false, null);
            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
        }

        // 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 & PERSISTENT_MASK) == PERSISTENT_MASK) {
            app.setPersistent(true);
            app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
        }
        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
            mPersistentStartingProcesses.add(app);
            mProcessList.startProcessLocked(app, new HostingRecord("added application",
                    customProcess != null ? customProcess : app.processName),
                    disableHiddenApiChecks, mountExtStorageFull, abiOverride);
        }

        return app;
    }

addAppLocked 启动persistent应用,并配置maxAdj = PERSISTENT_PROC_ADJ = -800;
同时将app,添加到mPersistentStartingProcesses 列表中
-800 表示进程属于高优先级,当系统资源紧张时,lowmemorykiller机制回收应用时会跳过persistent进程。

重启机制

虽然我们设置了persistent 应用的adj = -800,但是并不能保证100%不会被kill,例如通过adb kill pids kill。
google 对persistent应用做了重启机制。
重启机制
android在进程启动后调用到attachApplicationLocked时会创建一个进程死亡监听器AppDeathRecipient
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @GuardedBy("this")
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
			......
        final String processName = app.processName;
        try {
        //app死亡监听器
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            mProcessList.startProcessLocked(app,
                    new HostingRecord("link fail", processName));
            return false;
        }
		......
		}	
	
	
    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() {
        //当应用死亡后,调用binderDied
            if (DEBUG_ALL) Slog.v(
                TAG, "Death received in " + this
                + " for thread " + mAppThread.asBinder());
            synchronized(ActivityManagerService.this) {
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
    }	
	// 	appDiedLocked
    @GuardedBy("this")
    final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
            boolean fromBinderDied) {
			......
            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
                //处理app died
            handleAppDiedLocked(app, false, true);		
            ......
	}

	//hadlerAppDiedLocked
    @GuardedBy("this")
    final void handleAppDiedLocked(ProcessRecord app,
            boolean restarting, boolean allowRestart) {
        int pid = app.pid;
        //
        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
                false /*replacingPid*/);
        if (!kept && !restarting) {
            removeLruProcessLocked(app);
            if (pid > 0) {
                ProcessList.remove(pid);
            }
        }

        if (mProfileData.getProfileProc() == app) {
            clearProfilerLocked();
        }

        mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {
            Slog.w(TAG, "Crash of app " + app.processName
                    + " running instrumentation " + app.getActiveInstrumentation().mClass);
            Bundle info = new Bundle();
            info.putString("shortMsg", "Process crashed.");
            finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
        });
    }

appDiedLocked()最终会执行到cleanUpApplicationRecordLocked(),我们可以看一下这个方法做了什么

    @GuardedBy("this")
    final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
            boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
            ......

        } 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.
            // app是mPersistentStartingProcesses 列表中的应用时,restart = true
            if (mPersistentStartingProcesses.indexOf(app) < 0) {
                mPersistentStartingProcesses.add(app);
                restart = true;
            }
        }
        //restart  = true app应用重启      
      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);
            }
            mProcessList.addProcessNameLocked(app);
            app.pendingStart = false;
            mProcessList.startProcessLocked(app,
                    new HostingRecord("restart", app.processName));
            return true;

我们看到发现是persistent应用时,设置restart = true,并调用重启。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值