Performance optimization of Android power articles

Surface is electricity chapter study notes, part of the performance optimization model in front there was overlap, we welcome the exchange of learning together!

1) Understanding Battery Drain
the power consumption of each mobile phone hardware module is not the same, some module is power, while others seem module is relatively much smaller power consumption.

android_perf_battery_drain

Calculation and statistical power consumption is a cumbersome and contradictory things, itself a record power consumption cost electricity thing. The only possible solution is to use third-party monitoring equipment electricity, so as to obtain the real power consumption.

When the device is in standby power consumption is minimal to N5, for example, turn on flight mode, you can stand nearly a month. But light up the screen, the hardware modules need to begin to work, it would need to consume a lot of power.

After using WakeLock or JobScheduler timed wake-up task processing device, the device must be returned in time for the initial state. Each wakeup cellular signals data transfer, consumes a lot of power, it is more power than WiFi and other operations.

battery_drain_radio

2) Battery Historian
Battery Historian is the beginning of a new API Android 5.0 introduced. By the following commands, power consumption information can be obtained on the device:

1
2
$ adb shell dumpsys batterystats> xxx.txt // get the entire device power consumption information
$ adb shell dumpsys batterystats> com.package.name> xxx.txt // specify the app to get information related to power consumption
to get the original charge after consumption data, we need to convert a python script by Google written information into data more readable html file:

1
$ Python historian.py xxx.txt> xxx.html
open the html file after the conversion, you can see a list of similar TraceView data generated large amount of information here, where not carried out.

android_perf_battery_historian

3) Track Battery Status & Battery Manager
we can get the current state of charge of the mobile phone with the following code:

1
2
3
4
5
6
7
8
9
// It IS Very to the Subscribe to Changes to the Easy at The Battery State, But you CAN GET at The Current
// State Simply by passing null in your AS Receiver. Nifty, IS not that?
IntentFilter = the IntentFilter new new filter (Intent.ACTION_BATTERY_CHANGED);
the Intent in BatteryStatus = this.registerReceiver (null, filter);
int = chargePlug batteryStatus.getIntExtra (BatteryManager.EXTRA_PLUGGED, -1);
Boolean acCharge = (== chargePlug BatteryManager.BATTERY_PLUGGED_AC);
IF (acCharge) {
Log.v (LOG_TAG, "charging of the phone iS!");
}
after the above example shows how to get to the phone now charged state, the charging state information obtained, we can be targeted to the part of the code do optimization. For example, we can determine when the phone is currently only AC charging state to perform some very power-hungry operations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**

  • This method checks for power by comparing the current battery state against all possible

  • plugged in states. In this case, a device may be considered plugged in either by USB, AC, or

  • wireless charge. (Wireless charge was introduced in API Level 17.)
    */
    private boolean checkForPower() {
    // It is very easy to subscribe to changes to the battery state, but you can get the current
    // state by simply passing null in as your receiver. Nifty, isn’t that?
    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = this.registerReceiver(null, filter);

    There are Currently Three Ways // Device CAN BE A Plugged in Should We All Check Them..
    Int chargePlug = batteryStatus.getIntExtra (BatteryManager.EXTRA_PLUGGED, -1);
    Boolean usbCharge = (== chargePlug BatteryManager.BATTERY_PLUGGED_USB);
    Boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
    Boolean = wirelessCharge to false;
    IF (Build.VERSION.SDK_INT> = Build.VERSION_CODES.JELLY_BEAN_MR1) {
    wirelessCharge = (== chargePlug BatteryManager.BATTERY_PLUGGED_WIRELESS);
    }
    return (usbCharge acCharge || || wirelessCharge);
    }
    4) wakelock and battery Drain
    efficient to retain more power and continue to urge the user to use your App will consume power, which is contradictory choice. But we could use some better way to balance the two.

Suppose your phone which installed a large number of social networking applications, even if the phone is in standby mode, these applications will often wake up to check the new data synchronization information. Android will continue to shut down a variety of hardware to extend the standby time, first screen is gradually darkened until it closed, then the CPU goes to sleep, all operations are in order to save valuable power resources. But even in this sleep state, most applications will still try to work, they will continue to wake up the phone. One of the easiest way is to use the phone wake PowerManager.WakeLock API to keep the CPU work and prevent the screen darkens closed. This makes the phone can be awakened, implementation, and then go back to sleep. Know how to get WakeLock is simple, but the timely release of WakeLock is also very important, inappropriate use WakeLock cause serious errors. For example, the network returns the requested data time of uncertainty, leading to 10s had just been waiting for something one hour, this will make electricity wasted. This is why wakelock.acquice use with timeout parameter () method is critical.

But just to set the timeout is not enough to solve the problem, such as how long a timeout to set more appropriate? When a retry, and so on? Solve the above problem, the right way might be to use a non-precision timers. Under normal circumstances, we will set a time for an operation, but the dynamic modification might be better this time. For example, if there is another program needs to wake up later than the time you set for 5 minutes, it is best to wait until that time, the two tasks were tied together at the same time, which is the core principle of non-precision timer. We can customize a scheduled task, but if the system detects a better time, it can postpone your mission to save power consumption.

alarmmanager_inexact_wakelock

This is JobScheduler doing things API. It is based on the current situation of the task, the ideal combination of wake-up time, for example, performed together until being charged or connected to a WiFi time, or the Task. We can achieve a lot of free scheduling algorithm through this API.

5) Network and Battery Drain
the following content from the official Training document download section introduces efficient on the phone (Radio) on the power consumption of cellular signals.

Typically, the use of 3G mobile network to transmit data, the power consumption of three states:

Full power: the highest energy state, the mobile network connection is activated, allowing the device to operate a maximum transmission rate.
Low power: an intermediate state, electricity consumption of almost 50% of Full power state.
Standby: The lowest state, no data transmission connection requires a minimum of power consumption.
The figure is a typical 3G Radio State Machine diagram (from AT & T, please click here):

mobile_radio_state_machine.png

In short, in order to reduce power consumption in a cellular mobile network, the network is preferably done batch execution request, to avoid frequent network request interval.

Learned by the previous Battery Historian we can get the device power consumption data, the cellular network if the mobile (Mobile Radio) power consumption data presented below, the spacing is small, and intermittent frequently occurs, power consumption properties described very it is good:

android_perf_battery_bad.png

After optimization, if presented the following illustration, indicating power consumption performance is good:

android_perf_battery_good

Further the WiFi connection, network transmission power consumption much less than in a mobile network, data transmission should be minimized in mobile networks, the multi-transport data WiFi environment.

android_perf_battery_wifi

So how can cache up to the task, to do the bulk of the implementation of it? Here's turn to Job Scheduler played.

6) Using Job Scheduler
using the Job Scheduler, applications need to do is determine which tasks are not urgent, you can come to Job Scheduler processing, Job Scheduler centralized tasking received, select the appropriate time, the appropriate network, and then be executed together.

Here is a brief example of using Job Scheduler, you need to have a JobService:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
public class MyJobService extends JobService {
private static final String LOG_TAG = “MyJobService”;

@Override
public void onCreate() {
    super.onCreate();
    Log.i(LOG_TAG, "MyJobService created");
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.i(LOG_TAG, "MyJobService destroyed");
}

@Override
public boolean onStartJob(JobParameters params) {
    // This is where you would implement all of the logic for your job. Note that this runs
    // on the main thread, so you will want to use a separate thread for asynchronous work
    // (as we demonstrate below to establish a network connection).
    // If you use a separate thread, return true to indicate that you need a "reschedule" to
    // return to the job at some point in the future to finish processing the work. Otherwise,
    // return false when finished.
    Log.i(LOG_TAG, "Totally and completely working on job " + params.getJobId());
    // First, check the network, and then attempt to connect.
    if (isNetworkConnected()) {
        new SimpleDownloadTask() .execute(params);
        return true;
    } else {
        Log.i(LOG_TAG, "No connection on job " + params.getJobId() + "; sad face");
    }
    return false;
}

@Override
public boolean onStopJob(JobParameters params) {
    // Called if the job must be stopped before jobFinished() has been called. This may
    // happen if the requirements are no longer being met, such as the user no longer
    // connecting to WiFi, or the device no longer being idle. Use this callback to resolve
    // anything that may cause your application to misbehave from the job being halted.
    // Return true if the job should be rescheduled based on the retry criteria specified
    // when the job was created or return false to drop the job. Regardless of the value
    // returned, your job must stop executing.
    Log.i(LOG_TAG, "Whelp, something changed, so I'm calling it on job " + params.getJobId());
    return false;
}

/**
 * Determines if the device is currently online.
 */
private boolean isNetworkConnected() {
    ConnectivityManager connectivityManager =
            (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return (networkInfo != null && networkInfo.isConnected());
}

/**
 *  Uses AsyncTask to create a task away from the main UI thread. This task creates a
 *  HTTPUrlConnection, and then downloads the contents of the webpage as an InputStream.
 *  The InputStream is then converted to a String, which is logged by the
 *  onPostExecute() method.
 */
private class SimpleDownloadTask extends AsyncTask<JobParameters, Void, String> {

    protected JobParameters mJobParam;

    @Override
    protected String doInBackground(JobParameters... params) {
        // cache system provided job requirements
        mJobParam = params[0];
        try {
            InputStream is = null;
            // Only display the first 50 characters of the retrieved web page content.
            int len = 50;

            URL url = new URL("https://www.google.com");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000); //10sec
            conn.setConnectTimeout(15000); //15sec
            conn.setRequestMethod("GET");
            //Starts the query
            conn.connect();
            int response = conn.getResponseCode();
            Log.d(LOG_TAG, "The response is: " + response);
            is = conn.getInputStream();

            // Convert the input stream to a string
            Reader reader = null;
            reader = new InputStreamReader(is, "UTF-8");
            char[] buffer = new char[len];
            reader.read(buffer);
            return new String(buffer);

        } catch (IOException e) {
            return "Unable to retrieve web page.";
        }
    }

    @Override
    protected void onPostExecute(String result) {
        jobFinished(mJobParam, false);
        Log.i(LOG_TAG, result);
    }
}

}
Then the analog trigger by clicking Button N tasks, to be handled JobService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class FreeTheWakelockActivity extends ActionBarActivity {
public static final String LOG_TAG = “FreeTheWakelockActivity”;

TextView mWakeLockMsg;
ComponentName mServiceComponent;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wakelock);

    mWakeLockMsg = (TextView) findViewById(R.id.wakelock_txt);
    mServiceComponent = new ComponentName(this, MyJobService.class);
    Intent startServiceIntent = new Intent(this, MyJobService.class);
    startService(startServiceIntent);

    Button theButtonThatWakelocks = (Button) findViewById(R.id.wakelock_poll);
    theButtonThatWakelocks.setText(R.string.poll_server_button);

    theButtonThatWakelocks.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                pollServer();
        }
    });
}

/**
 * This method polls the server via the JobScheduler API. By scheduling the job with this API,
 * your app can be confident it will execute, but without the need for a wake lock. Rather, the
 * API will take your network jobs and execute them in batch to best take advantage of the
 * initial network connection cost.
 *
 * The JobScheduler API works through a background service. In this sample, we have
 * a simple service in MyJobService to get you started. The job is scheduled here in
 * the activity, but the job itself is executed in MyJobService in the startJob() method. For
 * example, to poll your server, you would create the network connection, send your GET
 * request, and then process the response all in MyJobService. This allows the JobScheduler API
 * to invoke your logic without needed to restart your activity.
 *
 * For brevity in the sample, we are scheduling the same job several times in quick succession,
 * but again, try to consider similar tasks occurring over time in your application that can
 * afford to wait and may benefit from batching.
 */
public void pollServer() {
    JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
    for (int i=0; i<10; i++) {
        JobInfo jobInfo = new JobInfo.Builder(i, mServiceComponent)
                .setMinimumLatency(5000) // 5 seconds
                .setOverrideDeadline(60000) // 60 seconds (for brevity in the sample)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // WiFi or data connections
                .build();

        mWakeLockMsg.append("Scheduling job " + i + "!\n");
        scheduler.schedule(jobInfo);
    }
}

}

Published 95 original articles · won praise 0 · Views 1903

Guess you like

Origin blog.csdn.net/qq_42894864/article/details/104234655