com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_link3' is unknown.

Invoking the Android System Service API

The Android system service application provides an API for the external applications to know the device firmware upgrade package status, download progress and to check if a new firmware upgrade is available. It also initiates new firmware upgrades and enables/disables Automatic Retry for firmware upgrades. To invoke these APIs, external applications should invoke the service exposed by the system service application and implement a BroadcastReceiver to receive results. Let's take a look at how it's done by following the subsections.

Configure the external application

Follow the steps given below to configure the external application:

  1. In order to use this API, you need to sign the android application with the same key, which you have used to signed the EMM agent and the System service.
  2. Add the uses-permission entry to the org.wso2.emm.system.service.permission.ACCESS to the manifest.xml file of the application.
  3. Add the receiver to receive broadcasts from the Android system service application.

Take a look at the sample given below to understand how the above entries need to be added to your applications manifest.xml file.

AndroidManifest.xml
<manifest ...>
    ...
    <uses-permission android:name="org.wso2.emm.system.service.permission.ACCESS"/>
    ...
    <application ...>
        ...
        <receiver android:name=.UpgradeServiceResponseReceiver>
            <intent-filter>
                <action android:name="org.wso2.emm.system.service.MESSAGE_PROCESSED"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        ...
    </application>
</manifest>

Receiving the Broadcasts

Follow the steps given below to receive broadcasts from system service application.

  1. Configure the BroadcastReceiver.

    UpgradeServiceResponseReceiver.java
    public class UpgradeServiceResponseReceiver extends BroadcastReceiver {
       @Override
       public void onReceive(Context context, Intent intent) {
             String operation = intent.getStringExtra(“operation”); //The operation result broadcast belongs
             String code = intent.getStringExtra(“code”); //Status code (200 for success, 300 for pending and 400 for failures)
             String status = intent.getStringExtra(“status”); //Sub status of the broadcast for more details.
             //Optional message or stringified JSON data related to the sub status.
             String payload = intent.getStringExtra(“payload”); 
             //Your result manipulation code goes here
       }
    }
  2. Register a receiver in your activity or service to listen to the service results. 

    IntentFilter filter = new IntentFilter(“org.wso2.emm.system.service.MESSAGE_PROCESSED”);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    UpgradeServiceResponseReceiver receiver = new UpgradeServiceResponseReceiver();
    registerReceiver(receiver, filter);

Supported broadcasts

The Systems Service uses the following broadcast codes to indicate success, pending and failure status.

CodeStatus of the result
200Success
300Pending
400Failure

The following states are defined in the broadcasts to identify specific sub status related to the above status codes.

StatusDescription
2000Successful
2001Ongoing
2002Request placed.
3000User canceled.
3001No data available.
4000Malformed request. i.e. command is not in valid format
4001Insufficient battery level to download firmware.
4002Wi-Fi off.
4003Unreachable network.
4004No upgrade found.
4005Upgrade info not readable.
4006OTA download failed.
4007OTA image invalid.
4008Low disk space.
4009Malformed OTA URL.
4010Another pending upgrade in line.
4011Insufficient battery level to install the firmware.
4012OTA verification failed.
4013Connection failed.
4014File not found.
5001Internal error

Broadcast operations, code, and the status descriptions.

OperationCodeStatus

Payload

Description
FIRMWARE_UPGRADE_
DOWNLOAD_PROGRESS
200

2001

{
"progress":<PROGRESS VALUE>
}
The Payload contains the firmware progress as a percentage.
FIRMWARE_UPGRADE_
DOWNLOAD_PROGRESS
2003001-

Indicates that the system service doesn't have any records related to the latest firmware download progress.

This status is returned if a firmware upgrade has not yet being carried out.

FIRMWARE_UPGRADE_
DOWNLOAD_PROGRESS
3002002,
4001 to 4003,
4008
-

The pending code with the status indicating that the operation is pending. (Please refer the status descriptions.)

FIRMWARE_UPGRADE_
DOWNLOAD_PROGRESS
4004000 to 4014,
5001
<optional error message>

The failure code with the status indicating the root cause of the failure. (Please refer the status descriptions.)

Optionally, an error message may be available in the payload.

UPGRADE_FIRMWARE 2002000-The success code with the status indicating the completion of the firmware upgrade.
UPGRADE_FIRMWARE 200

2001

{
"progress":<PROGRESS VALUE>
}
The Payload contains the firmware upgrade progress as a percentage.

UPGRADE_FIRMWARE

2002002-

The success code along with the request placed status. This indicates that the request entered the critical path of the execution.

UPGRADE_FIRMWARE 3002001-

The operation pending code along with ongoing OTA upgrade status.

UPGRADE_FIRMWARE 4003000,
4000 to 4014,
5001
<optional error message>

The failure code along with the status indicating the root cause of the failure. (Please refer the status descriptions.)

Optionally, an error message may be available in the payload.

FIRMWARE_BUILD_
DATE
2002000
{
"buildDate":<UTC DATE & TIME>
}
The success code along with the value of the ro.build.date.utc property.
FIRMWARE_BUILD_
DATE
4005001<error message>

The failure code along with the status indicating the internal error.

The error message is available in the payload.

FIRMWARE_UPGRADE_
PACKAGE_STATUS
2002000
{  
   "size":<UPGRADE PACKAGE SIZE>,
   "release":<RELEASE CODE>,
   "version":<VERSION CODE>,
   "description":<DESCRIPTION>
}

The Success code along with the success status of the firmware upgrade.

The payload contains a JSON string with the details of the upgrade.

FIRMWARE_UPGRADE_
PACKAGE_STATUS
2002002-

The success code along with the request placed status. This indicates that the request entered the critical path of the execution.

FIRMWARE_UPGRADE_
PACKAGE_STATUS
2004004-The success status with the no upgrade found status.
FIRMWARE_UPGRADE_
PACKAGE_STATUS
400

4000,4002,
4003, 4005,
4009, 4013,
4014, 5001

<optional error message>

The failure code with the status that indicates the root cause of the failure. (Please refer the status descriptions.)

Optionally, an error message may be available in the payload.

Invoking the API

Follow the steps given below to invoke the API by starting the exposed service.

  1. Create an explicit intent method.

    public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
      //Retrieve all services that can match the given intent
      PackageManager pm = context.getPackageManager();
      List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
    
      //Make sure only one match was found
      if (resolveInfo == null || resolveInfo.size() != 1) {
         return null;
      }
    
      //Get component info and create ComponentName
      ResolveInfo serviceInfo = resolveInfo.get(0);
      String packageName = serviceInfo.serviceInfo.packageName;
      String className = serviceInfo.serviceInfo.name;
      ComponentName component = new ComponentName(packageName, className);
    
      //Create a new intent. Use the old one for extras and such reuse
      Intent explicitIntent = new Intent(implicitIntent);
    
      //Set the component to be explicit
      explicitIntent.setComponent(component);
    
      return explicitIntent;
    }
  2. Call the service. 

    This should always happen after registering the receiver. Else, you will not receive the results of your API call from the systems service.

    Intent intent =  new Intent(“org.wso2.emm.system.service.START_SERVICE”);
    Intent explicitIntent = createExplicitFromImplicitIntent(context, intent);
    if (explicitIntent != null) {
      intent = explicitIntent;
    }
    intent.putExtra("operation", <Operation code>); //Operation code which need to perform
    intent.putExtra("command", <Commands for the operation>); //Optional command string which might required for the particular operation.
    startService(intent); //Start the service with intent

Supported operations by the API

After calling to below operations System Service will send a broadcast with the response. Please check the Broadcast operations, code, and the status descriptions section for the corresponding responses.

Operation CodeCommand formatDescription

FIRMWARE_UPGRADE_
AUTOMATIC_RETRY
 

"true" or "false"

Enable or disable the automatic retry on failure option for firmware upgrades. The value set by this operation will be overwritten by the autoRetry parameter that is specified in the UPGRADE_FIRMWARE command.

The command should be specified as a string that contains true or false as the value.

UPGRADE_FIRMWARE
{  
   "schedule":<ISO 8601 DATA & TIME>,
   "server":<OTA SERVER URL>,
   "autoRetry":<TRUE or FALSE>
}

The firmware upgrade has the following 3 parameters by default.

  • schedule
  • server
  • autoRetry

Let's look at how this operation works:

  • The default values assigned to the parameters are as follows:
    • server is assigned an empty string.
    • schedule doesn't have a default value. If a value is not defined, the firmware upgrade will happen instantly and will not be scheduled.
    • autoRetry is assigned true by default.
  • If you don't assign any values to the parameters, the default values will be used, else the value that was assigned to it will be used throughout until a new value is assigned to the parameter/s again.
  • If you had previously defined a value for the FIRMWARE_UPGRADE_AUTOMATIC_RETRY operation, then that value will be assigned to the autoRetry parameter until you define a new value for it through the FIRMWARE_UPGRADE_ AUTOMATIC_RETRY operation or the UPGRADE_FIRMWARE operation.
 Click here to see an example on how the operation works.

To get a better understanding of how things work, let's take a look at the following scenario, where you define values for the autoRetry parameter.

Scenario (These scenarios occur consecutively)Value assigned to autoRetry
Defaulttrue
The UPGRADE_FIRMWARE is executed with the autoRetry value set as false.false
The UPGRADE_FIRMWARE is executed with no value assigned to autoRetry.false
The FIRMWARE_UPGRADE_ AUTOMATIC_RETRY is executed with the autoRetry value set as true.true
The UPGRADE_FIRMWARE is executed with no value assigned to autoRetry.true
FIRMWARE_UPGRADE_
PACKAGE_STATUS
{
"server": <OTA server URL>
}
Check the availability of the firmware upgrade. The server parameter is optional and if you don't define a value the default value will be used.
FIRMWARE_BUILD_DATE-Get the build date of the current firmware.
FIRMWARE_UPGRADE_
DOWNLOAD_PROGRESS
-Get the download progress of the current firmware upgrade.
com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.