Performance Optimization 07-In-depth analysis of the process keep-alive mechanism

Performance optimization 07-process keep alive

1. Process recycling

1, the priority of the process

The Android system will keep the application process as long as possible, but in order to create a new process or run a more important process, it is necessary to clear the old process to reclaim the memory.
To determine which processes to keep or kill, the system classifies processes. When needed, the system will first eliminate the least important process, then the less important process, and so on, to reclaim system resources.

There are 5 levels of importance hierarchy:

  1. Foreground process: The process necessary for the user's current operation, and also the process that is interacting with the user. Foreground processes are the most important processes, and the system will only kill them as a last resort if there is not enough memory to support them while continuing to run.
  2. Visible Process: A process that does not have any foreground components, but still affects what the user sees on the screen, such as an Activity that calls a onPause()method . Visible processes are considered extremely important processes that are not terminated by the system unless they must be terminated in order to keep all foreground processes running simultaneously.
  3. Service Process: A process that is running a service that has been started using the startService()method and does not belong to the two higher categories of processes above. The system keeps the service process running unless there is insufficient memory to keep all foreground and visible processes running at the same time.
  4. Background process: The process that contains the activity that is not currently visible to the user (the activity's onStop()method ). These processes have no direct impact on the user experience, and the system may terminate them at any time to reclaim memory for use by foreground, visible, or service processes.
  5. Empty process; a process that does not contain any active application components. The sole purpose of keeping such a process as a cache is to reduce the startup time required to run a component in it the next time. These processes are often killed by the system in order to balance overall system resources between the process cache and the underlying kernel cache.

Reference: https://developer.android.google.cn/guide/components/processes-and-threads.html?hl=zh-cn

2、Low Memory Killer

For the sake of experience and performance, the system does not really kill the process when the app exits to the background, but caches it. The more apps you have open, the more processes are cached in the background. In the case of insufficient system memory, the system begins to determine which processes to kill based on its own set of process recycling mechanisms to free up memory to supply the required apps. This mechanism for killing processes to recycle memory is called Low Memory Killer.

The memory threshold refers to the minimum available memory of the mobile phone, which is different on different mobile phones. Once the value is lower than this value, Android starts to close the process in order. View memory thresholds:

adb shell
cat /sys/module/lowmemorykiller/parameters/minfree
18432,23040,27648,32256,55296,80640
//它的单位是page,1page=4kb,80640page就是315M

3、oom_adj

The priority of the process is reflected by the adj value of the process, which is a value assigned by the Linux kernel to each system process, and the process recycling mechanism decides whether to recycle according to this value. The smaller the value of adj, the higher the priority of the process.

You can see the adj value of the current process through cat /proc/process id/oom_adj. (requires [root] privileges)

adb shell
cat /proc/3715/oom_adj
0 //处于前台时
8 //处于后台时

The larger the adj, the more memory it occupies, and it will be killed first, so keep alive is to reduce the value of oom_adj, and how to make our application occupy the least memory.

2. Process keep alive

There are two main ways to keep the process alive: increasing the priority of the process and restarting the process.

1. Increase process priority

1 pixel Activity

Monitor the lock screen unlock event of the phone, start a 1-pixel transparent Activity when the screen is locked, and destroy the Activity when the user unlocks it. In order to achieve the effect of increasing the priority of the process. This is to increase the process priority during lock screen.

Defect: There is an Activity that is not clean enough, and it also needs to be escalated after the screen is locked.

accomplish:

//设置1像素且透明
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.e(TAG,"启动Keep");
    Window window = getWindow();
    //设置这个act 左上角
    window.setGravity(Gravity.START | Gravity.TOP);
    //宽 高都为1
    WindowManager.LayoutParams attributes = window.getAttributes();
    attributes.width = 1;
    attributes.height = 1;
    attributes.x = 0;
    attributes.y = 0;
    window.setAttributes(attributes);
}

//监听屏幕广播
public void registerKeep(Context context) {
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_SCREEN_ON);
    keepReceiver = new KeepReceiver();
    context.registerReceiver(keepReceiver, filter);
}

Reception

The foreground service belongs to the foreground process, so you can open a foreground service to improve the process priority of the service.

To enable the foreground service, you need to call startForeground(ID, Notification) in the onCreate() of the service. After the foreground service is enabled, a notification will be displayed in the notification bar. There are two ways to not show notifications:

  1. If APIlevel < 18, set parameter 2 to new Notification().
  2. If APIlevel >= 18, start an InnerService in service A that needs to be prioritized. Both services startForeground and are bound to the same ID. Stop InnerService, the notification bar icon is removed.
public void onCreate() {
    super.onCreate();
    //让服务变成前台服务
    startForeground(10, new Notification());
    //如果 18 以上的设备 启动一个Service startForeground给相同的id
    //然后结束这个Service
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        startService(new Intent(this, InnnerService.class));
    }
}

public static class InnnerService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        startForeground(10, new Notification());
        stopSelf();
    }
}

2. Restart the process

Service restart mechanism

Set the return value of onStartCommand, the system will automatically restart the service. The return values ​​that can be set are as follows:

  1. START_STICKY: "Sticky". If the service process is killed, the state of the service is retained as the start state, but the delivered intent object is not retained. Then the system will try to recreate the service. Since the service state is the start state, the onStartCommand(Intent,int,int) method will be called after the service is created. If no startup commands have been passed to the service during this time, the parameter Intent will be null.
  2. START_NOT_STICKY: "non-sticky". When using this return value, if the service is killed abnormally after onStartCommand is executed, the system will not restart the service automatically.
  3. START_REDELIVER_INTENT: Retransmit the intent. When using this return value, if the service is killed abnormally after executing onStartCommand, the system will automatically restart the service and pass in the value of Intent.
  4. START_STICKY_COMPATIBILITY: Compatible version of START_STICKY, but does not guarantee that the service will restart after being killed. As long as targetSdkVersion is not less than 5, the default is START_STICKY.

But some ROM systems will not pull live. And after testing, the Service is restarted soon after being killed abnormally for the first time, the second time will be slower than the first time, and the third time will be slower than the previous time, once the Service is killed 4-5 times in a short period of time, The system will no longer pull up.

account synchronization

There will be an "account" function in the mobile phone system settings, any third-party APP can use this function to synchronize data to the server within a certain period of time. When the system synchronizes the APP account, it will activate the unstarted APP process.

Reference: https://github.com/googlesamples/android-BasicSyncAdapter .

JobScheduler pulls live

JobScheduler allows tasks to be executed periodically at specific states and at specific time intervals. This feature can be used to complete the keep-alive function, and the effect is to start a timer. Unlike ordinary timers, its scheduling is completed by the system.

Also in some ROMs may not achieve the desired effect (a certain meter).

accomplish:

First create a JobService:

public class MyJobService extends JobService {
    private static final String TAG = "MyJobService";
    public static void StartJob(Context context) {
        JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context
                .JOB_SCHEDULER_SERVICE);
        //setPersisted 在设备重启依然执行
        JobInfo.Builder builder = new JobInfo.Builder(10, new ComponentName(context
                .getPackageName(), MyJobService.class
                .getName())).setPersisted(true);
        //小于7.0
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            // 每隔1s 执行一次 job
            builder.setPeriodic(1000);
        } else {
            //延迟执行任务
            builder.setMinimumLatency(1000);
        }

        jobScheduler.schedule(builder.build());
    }   

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.e(TAG, "开启job");
        //如果7.0以上,需要手动重新开启JobInfo,因为7.0以上不支持循环执行
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StartJob(this);
        }
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }
}

Then, register in the manifest file:

<service
    android:name=".jobschuduler.MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

push and pull

Depending on the terminal, Xiaomi mobile phones (including MIUI) are connected to Xiaomi Push, and Huawei mobile phones are connected to Huawei Push.

broadcast live

When a specific system event occurs, the system will send a broadcast. By statically registering the corresponding broadcast listener in the AndroidManifest, it can be activated when a response event occurs.

But since android 7.0, there is a restriction on broadcasting, and in 8.0 it is more strict: apps cannot continue to register broadcast receivers in their manifest for implicit broadcasts. For details, see: https://developer.android.google.cn/about/versions/oreo/background.html#broadcasts .

List of broadcasts that can be statically registered for Android8.0: https://developer.android.google.cn/guide/components/broadcast-exceptions.html .

In addition, the Android system stipulates that the application must run once after the system is turned on to monitor these system broadcasts: boot broadcast, unlock screen broadcast, network status broadcast, etc., so the APP cannot be automatically started by monitoring the system broadcast.

Dual process daemon

There are multiple apps installed on the user's device, and as long as one of them is opened, the other apps can also be activated. For example, if mobile QQ, QQ space, interest tribe, etc. are installed in the mobile phone, after opening any app, other apps will also be awakened.

However, after Android 6.0, the keep-alive scheme of dual-process daemons is prohibited.

Previous: Performance Optimization 06-Multi-dex Encryption

Next: Performance optimization 08-APK slimming

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325367461&siteId=291194637