1# Reasonably Running Background Tasks
2
3## Introduction
4
5When you return to the home screen, lock the screen, or switch to another application, the current application is switched to the background. To reduce the device power consumption and deliver a positive user experience, the system manages the application running in the background, for example, suspending or terminating its process. To ensure the normal use of features such as music playback and calendar reminders in the background, the system provides constrained background tasks to extend the running time of applications in the background.
6
7This topic describes the basic concepts and use scenarios of different background tasks, and analyzes the performance of transient tasks and continuous tasks to explain the necessity of properly running background tasks.
8
9## Transient Task
10
11An application is suspended after it runs in the background for a short period of time. If the application needs to execute a short-time task in the background, it can request a transient task to extend the running time in the background.
12
13Transient tasks are suitable for tasks that have high requirements on real-time performance and occupies resources for a short period of time, for example, small file download, caching, and information sending. For details about the development guide, see [Transient Task](../task-management/transient-task.md).
14
15### Example
16
17The following code requests a transient task to execute a time-consuming computing task in the background. The source code is obtained from [Transient Task Sample](https://gitee.com/openharmony/applications_app_samples/blob/master/code/Performance/PerformanceLibrary/feature/backgroundTask/src/main/ets/view/TransientTaskView.ets).
18
19```javascript
20import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
21import { BusinessError } from '@ohos.base';
22import util from '@ohos.util';
23import hiTraceMeter from '@ohos.hiTraceMeter';
24
25const totalTimes: number = 50000000; // Number of loops.
26const calculateResult: string ='Total time costed = %s ms.'; // Text format.
27
28@Entry
29@Component
30struct Index {
31  @State message: string = 'Click button to calculate.';
32  private requestId: number = 0;
33
34  // Request a transient task.
35  requestSuspendDelay() {
36    try {
37      let delayInfo = backgroundTaskManager.requestSuspendDelay('compute', () => {
38        console.info('Request suspension delay will time out.');
39        // Cancel the transient task when the task is about to time out.
40        this.cancelSuspendDelay();
41      })
42      this.requestId = delayInfo.requestId;
43    } catch (error) {
44      console.error(`requestSuspendDelay failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
45    }
46  }
47
48  // Cancel the transient task.
49  cancelSuspendDelay() {
50    backgroundTaskManager.cancelSuspendDelay(this.requestId);
51    console.info('Request suspension delay cancel.');
52  }
53
54  // Computing task.
55  computeTask(times: number): number {
56    let start: number = new Date().getTime();
57    let a: number = 1;
58    let b: number = 1;
59    let c: number = 1;
60    for (let i: number = 0; i < times; i++) {
61      a = a * Math.random() + b * Math.random() + c * Math.random();
62      b = a * Math.random() + b * Math.random() + c * Math.random();
63      c = a * Math.random() + b * Math.random() + c * Math.random();
64    }
65    let end: number = new Date().getTime();
66    return end - start;
67  }
68
69  // Configure the touch callback.
70  clickCallback = () => {
71    this.requestSuspendDelay();
72    hiTraceMeter.startTrace('computeTask', 0); // Enable performance tracing.
73    let timeCost = this.computeTask(totalTimes);
74    this.message = util.format(calculateResult, timeCost.toString());
75    hiTraceMeter.finishTrace('computeTask', 0); // End performance tracing.
76    this.cancelSuspendDelay();
77  }
78
79  build() {
80    Column() {
81      Row(){
82        Text(this.message)
83      }
84      Row() {
85        Button ('Start Computing')
86          .onClick(this.clickCallback)
87      }
88      .width('100%')
89      .justifyContent(FlexAlign.Center)
90    }
91    .width('100%')
92    .height('100%')
93    .justifyContent(FlexAlign.Center)
94  }
95}
96```
97
98Time Profiler in DevEco Studio obtains the following data about the application performance within the duration (less than one minute) from the start of the computing task to switching to the background:
99
100**Figure 1** Time Profiler lane of a transient task
101
102![](./figures/reasonable-running-backgroundTask-image1.png)
103
104- ArkTS Callstack: displays the CPU usage and status changes based on the time axis.
105- User Trace: displays details about user-defined trace tasks triggered in the current period based on the time axis. **H:computeTask** indicates the execution duration of the transient task.
106- Native Callstack: displays the CPU usage changes, process/thread status, and function call stack based on the timeline.
107
108As shown in the preceding figure, in the period corresponding to **H:computeTask** in the Native Callstack lane, the application process is active and the CPU usage changes in a high range. After the task is canceled, the application is still running, but the process activeness and CPU usage decrease significantly. The system suspends the application several seconds later and reclaims the CPU.
109
110The figures below demonstrate the Native Callstack lane in the task execution phase and in the phase that the task is canceled but the process is not suspended. Check the average CPU usage and maximum CPU usage of the application main thread in the two phases.
111
112**Figure 2** CPU usage in the task execution phase
113
114![](./figures/reasonable-running-backgroundTask-image2.png)
115
116**Figure 3** CPU usage when the task is canceled but the process is not suspended
117
118![](./figures/reasonable-running-backgroundTask-image3.png)
119
120In the first phase, the average CPU usage of the application main thread is 12.6%, and the highest CPU usage is 40.0%. In the second phase, the average CPU usage is 2.2%, and the highest CPU usage is 28.6%.
121
122To sum up, running transient tasks in the background occupies system CPU resources, and too many transient tasks in the background may cause the applications in the foreground to freeze. Therefore, use transient tasks only when necessary, and do not request too many transient tasks at a time.
123
124For details about the constraints on transient tasks, see [Constraints](../task-management/transient-task.md#constraints).
125
126## Continuous Task
127
128If an application has a perceivable task that needs to run in an extended period of time in the background, it can request a continuous task to prevent itself from being suspended. Examples of continuous tasks include music playback and navigation in the background. After an application requests a continuous task, the system verifies whether the application is actually executing the continuous task. For details about the development guide, see [Continuous Task](../task-management/continuous-task.md).
129
130The table below lists the types of continuous tasks, which are used in various scenarios. You can select a task type suitable for your case based on the description.
131
132| Description                          | Example Scenario                            |
133| ------------------------------ | ------------------------------------ |
134| Data transfer                      | The browser downloads a large file in the background.|
135| Audio and video playback                    | A music application plays music in the background.          |
136| Audio recording                          | A recorder records audio in the background.                  |
137| Positioning and navigation                      | A navigation application provides navigation in the background.                |
138| Bluetooth-related task                      | Transfer a file through Bluetooth.            |
139| Multi-device connection                    | Carry out distributed service connection.                    |
140| WLAN-related task (for system applications only) | Transfer a file over WLAN.          |
141| Voice and video calls (for system applications only)| Use a system chat application to make an audio call in the background.        |
142| Computing task (for specific devices only)  | Run antivirus software.                            |
143
144- When an application requests a continuous task of the data transfer type, the system increases the priority of the application process to reduce the probability of terminating the process. However, it still suspends the process. To request a continuous task for file upload or download, the application must call the [upload and download agent API](../reference/apis-basic-services-kit/js-apis-request.md) so that the system functions as the agent. For details, see [Improving File Upload and Download Performance](improve-file-upload-and-download-performance.md/).
145- To request a continuous task for audio and video playback, the application must use the [AVSession service](../media/avsession/avsession-overview.md) for background playback.
146- To request a continuous recording task, a dialog box must be displayed dynamically to request user authorization for the microphone permission.
147
148### Example
149
150The following simulates a background location scenario. An application subscribes to device location changes and obtains the location every second. To continue the use of the location service after switching to the background, the application requests a continuous task of the location type. The source code is obtained from [Continuous Task Sample](https://gitee.com/openharmony/applications_app_samples/blob/master/code/Performance/PerformanceLibrary/feature/backgroundTask/src/main/ets/view/LongTermTaskView.ets).
151
152First, declare the continuous task type for the EntryAbility in the **module.json5** file.
153
154```javascript
155{
156  "module": {
157    ...
158    "abilities": [
159      {
160        "name": "EntryAbility",
161        ...
162        "backgroundModes": [
163          "location"
164        ]
165      }
166    ],
167  }
168}
169```
170
171The following permissions are required:
172
173- ohos.permission.INTERNET
174- ohos.permission.LOCATION_IN_BACKGROUND
175- ohos.permission.APPROXIMATELY_LOCATION
176- ohos.permission.LOCATION
177- ohos.permission.KEEP_BACKGROUND_RUNNING
178
179For details about how to request the permissions, see [Declaring Permissions in the Configuration File](../security/AccessToken/declare-permissions-in-acl.md).
180
181Configure the permission in the **module.json5** file. Confirmation from end users is required for the request of some permissions and the toggle of the notification switch. When the system publishes a notification for the continuous task, the notification feature of the application must be enabled. Otherwise, users cannot perceive the continuous task running in the background.
182
183The code for implementing background location is as follows:
184
185```javascript
186import wantAgent, { WantAgent } from '@ohos.app.ability.wantAgent';
187import common from '@ohos.app.ability.common';
188import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
189import { BusinessError } from '@ohos.base';
190import geolocation from '@ohos.geoLocationManager';
191import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
192import notificationManager from '@ohos.notificationManager';
193
194const TAG: string = 'BackgroundLocation';
195
196@Entry
197@Component
198export struct LongTermTaskView {
199  @State latitude: number = 0;
200  @State longitude: number = 0;
201
202  aboutToAppear() {
203    // Request the permission to send notifications.
204    notificationManager.requestEnableNotification().then(() => {
205      console.info(`[EntryAbility] requestEnableNotification success`);
206      // Request the permission for location.
207      let atManager = abilityAccessCtrl.createAtManager();
208      try {
209        atManager.requestPermissionsFromUser(getContext(this), ['ohos.permission.INTERNET',
210          'ohos.permission.LOCATION',
211          'ohos.permission.LOCATION_IN_BACKGROUND',
212          'ohos.permission.APPROXIMATELY_LOCATION'])
213          .then((data) => {
214            console.info(`[EntryAbility], data: ${JSON.stringify(data)}`);
215          })
216          .catch((err: BusinessError) => {
217            console.info(`[EntryAbility], err: ${JSON.stringify(err)}`);
218          })
219      } catch (err) {
220        console.info(`[EntryAbility], catch err->${JSON.stringify(err)}`);
221      }
222    }).catch((err: BusinessError) => {
223      console.error(`[EntryAbility] requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
224    });
225  }
226
227  // Location change callback.
228  locationChange = async (location: geolocation.Location) => {
229    console.info(TAG, `locationChange location =${JSON.stringify(location)}`);
230    this.latitude = location.latitude;
231    this.longitude = location.longitude;
232  }
233
234  // Obtain the location.
235  async getLocation() {
236    console.info(TAG, `enter getLocation`);
237    let requestInfo: geolocation.LocationRequest = {
238      priority: geolocation.LocationRequestPriority.FIRST_FIX, // Fast location preferred.
239      scenario: geolocation.LocationRequestScenario.UNSET, // Scenario unspecified.
240      timeInterval: 1, // Time interval at which location information is reported.
241      distanceInterval: 0, // Distance interval at which location information is reported, in meters.
242      maxAccuracy: 100 // Location accuracy.
243    };
244    console.info(TAG, `on locationChange before`);
245    geolocation.on('locationChange', requestInfo, this.locationChange);
246    console.info(TAG, `on locationChange end`);
247  }
248
249  // Start the continuous task.
250  startContinuousTask() {
251    let context: Context = getContext(this);
252    // Notification parameters, which are used to specify the target application that is redirected to when the continuous task notification is clicked.
253    let wantAgentInfo: wantAgent.WantAgentInfo = {
254      wants: [
255        {
256          bundleName: (context as common.UIAbilityContext).abilityInfo.bundleName,
257          abilityName: (context as common.UIAbilityContext).abilityInfo.name
258        }
259      ],
260      operationType: wantAgent.OperationType.START_ABILITY,
261      requestCode: 0,
262      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
263    };
264    wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
265      backgroundTaskManager.startBackgroundRunning(context,
266        backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {
267        console.info(`Succeeded in operationing startBackgroundRunning.`);
268      }).catch((err: BusinessError) => {
269        console.error(`Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
270      });
271    });
272  }
273
274  // Stop the continuous task.
275  stopContinuousTask() {
276    backgroundTaskManager.stopBackgroundRunning(getContext()).then(() => {
277      console.info(`Succeeded in operationing stopBackgroundRunning.`);
278    }).catch((err: BusinessError) => {
279      console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
280    });
281  }
282
283  build() {
284    Column() {
285      Column() {
286        Text(this.latitude.toString())
287        Text(this.longitude.toString())
288      }
289      .width('100%')
290
291      Column() {
292        Button('Enable Locating')
293          .onClick(() => {
294            this.startContinuousTask();
295            this.getLocation();
296          })
297        Button('Disable Locating')
298          .onClick(async () => {
299            await geolocation.off('locationChange');
300            this.stopContinuousTask();
301          })
302          .margin({ top: 10 })
303      }
304      .width('100%')
305    }
306    .width('100%')
307    .height('100%')
308    .justifyContent(FlexAlign.Center)
309  }
310}
311```
312
313Based on this scenario, the power consumption test tool obtains the following data about the device power consumption within 30 minutes.
314
315| Task            | Test Duration (s)| Normalized Current (mA)| Maximum Current (mA)| Normalized Power Consumption (mAH)|
316| -------------------- | ----------- | ------------ | ------------ | ------------- |
317| Locating task in the background| 1836.4      | 15.52        | 995.72       | 7.92          |
318| No background task          | 1839.9      | 0.85         | 404.03       | 0.44          |
319
320- Normalized current: average current when the voltage is 3.8 V.
321- Formula for calculating the normalized power consumption: Normalized current x Test duration/3600, where 3600 is the number of seconds in an hour.
322
323The test data shows that the device power consumption increases significantly within 30 minutes when the locating task keeps running in the background.
324
325Do not use too many continuous tasks from the perspective of power consumption. If continuous tasks must be used, you can optimize the task execution process to minimize the power consumption. The following provides some optimization suggestions:
326
327- In scenarios that do not have high requirements on locating, increase the reporting time interval and distance interval to reduce the update frequency.
328
329- Reduce the number of network requests and the network request interval as much as possible.
330
331- Use efficient data formats and parsing methods during data transmission to reduce task execution time.
332
333For details about the constraints on continuous tasks, see [Constraints](../task-management/continuous-task.md).
334
335## Deferred Task
336
337If an application needs to execute a non-real-time task after switching to the background, the application can request a deferred task. When the specified conditions (including the network type, charging type, storage status, battery status, and timing status) are met, the system adds the task to the execution queue. Then the system starts the application to execute the task based on the memory, power consumption, device temperature, and user habits.
338
339Deferred tasks apply to scenarios such as software updates, information collection, and data processing. For details about the development guide, see [Deferred Task](../task-management/work-scheduler.md).
340
341## Agent-powered Reminder
342
343After an application switches to the background or an application process is terminated, it may have scheduled tasks for reminding users, for example, flash sale reminders for shopping applications. To meet this requirement, the system provides agent-powered reminders (implemented by **reminderAgentManager**). When the application switches to the background or the process is terminated, the system sends reminders on behalf of the application. For details about the development guide, see [Agent-powered Reminder](../task-management/agent-powered-reminder.md).
344
345Currently, the following reminder types are supported:
346
347- Countdown timers: Applications can use this type to implement short-time timing notification services, for example, flash sale reminders.
348- Calendar events: Applications can use this type to implement long-time notification services, for example, birthday reminders.
349- Alarm clocks: Applications can use this type to implement alarm-related services, for example, wake-up alarms.
350
351## Summary
352
353Proper selection and use of background tasks are important for optimizing user experience and reducing performance consumption. The table below describes these background tasks from different dimensions.
354
355| Task Type| Task Description                                                                                    | Background Application Status                                                                                                                                                   | Example Scenario                                                                             |
356| -------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
357| No background  | The application does not execute any task in the background.                                                            | The application is suspended within several seconds after switching to the background.                                                                                                                                     | General                                                                                 |
358| Transient task| Suitable for tasks that have high requirements on real-time performance and can be completed in a short period of time.                                                            | Within the one-off quota, the application is not suspended until the task is canceled. If the task is not canceled when the one-off quota expires, the application process is terminated.                                                                                     | Small file download, caching, and information sending                     |
359| Continuous task| Suitable for perceivable task that needs to run in an extended period of time in the background.                                                      | The application is not suspended until the task is canceled. If the task is not canceled, the application process is terminated when the task is complete.                                                                                                         | Data transfer, audio playback, recording, positioning and navigation, Bluetooth-related task, WLAN-related task, multi-device connection, voice and video calls, and computing tasks|
360| Deferred task| Suitable for tasks that do not have high requirements on real-time performance and can be executed at a later time.| The system enqueues tasks and schedules them in a unified manner based on the memory and power consumption. The application is suspended after switching to the background. When the preset conditions are met, the system starts the application and creates an Extension process to execute the task. The maximum execution duration for a single callback is 2 minutes. If the task is not canceled when the maximum duration expires, the system terminates the Extension process.| Software update, information collection, and data processing                                                       |
361| Agent-powered reminder| The system sends reminders on behalf of the application.                                                                | The application is suspended or the process is terminated. When the conditions are met, the system sends reminders on behalf of the application.                                                                                                           | Alarm clocks, countdown timer, and calendar events                                                                   |
362