Skip to content

Commit

Permalink
[#52516] android-client: Handle unreachable network during app startup
Browse files Browse the repository at this point in the history
Previously, we required MAC address discovery to succeed during MainActivity
creation. This caused the app to crash when the network wasn't yet accessible
during startup. This removes that requirement, and MAC address discovery now
happens lazily and is cached for the entire duration of the app's runtime.
  • Loading branch information
lkedziora committed Dec 13, 2023
1 parent 20fce9a commit 97904b4
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import android.util.Log;

import com.antmicro.update.rdfm.exceptions.DeviceInfoException;
import com.antmicro.update.rdfm.exceptions.DeviceUnauthorizedException;
import com.antmicro.update.rdfm.exceptions.ServerConnectionException;
import com.antmicro.update.rdfm.mgmt.DeviceInfoProvider;
import com.antmicro.update.rdfm.mgmt.IDeviceTokenProvider;
import com.antmicro.update.rdfm.mgmt.ManagementClient;
import com.antmicro.update.rdfm.utilities.KeyUtils;
Expand Down Expand Up @@ -60,18 +62,16 @@ public HttpClient(String otaPackagesPath, IDeviceTokenProvider tokenProvider) {
mTokenProvider = tokenProvider;
}

public void checkUpdate(String bspVersion, String serverAddress, Utils utils,
public void checkUpdate(DeviceInfoProvider deviceInfo, String serverAddress, Utils utils,
UpdateManager mUpdateManager) {
String macAddress = SysUtils.findDeviceMAC();
String devType = SysUtils.getDeviceType();
String serialNumber = SysUtils.getSerialNumber();
Log.d(TAG, "Device serial number: " + serialNumber);

Map<String, String> devParams = new HashMap<>();
devParams.put("rdfm.software.version", bspVersion);
devParams.put("rdfm.hardware.macaddr", macAddress);
devParams.put("rdfm.hardware.devtype", devType);
String reqData = new JSONObject(devParams).toString();
String reqData;
try {
reqData = new JSONObject(deviceInfo.toMap())
.toString();
} catch (DeviceInfoException e) {
Log.w(TAG, "Cannot check for updates, could not get device metadata: " + e.getMessage());
return;
}
RequestBody reqBody = RequestBody.create(reqData, JSON);

String token;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import androidx.preference.PreferenceManager;

import com.antmicro.update.rdfm.mgmt.AuthorizationProvider;
import com.antmicro.update.rdfm.mgmt.DeviceInfoProvider;
import com.antmicro.update.rdfm.mgmt.ManagementClient;
import com.antmicro.update.rdfm.utilities.SysUtils;

Expand All @@ -35,8 +36,8 @@ public class MainActivity extends Activity {
private TextView mTextViewBuild;
private TextView mTextViewAddress;
private String serverAddress;
private String buildVersion;
private ReentrantLock updaterLock;
private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider();
private AuthorizationProvider mDeviceAuthorizationProvider;
private ManagementClient mWsClient;

Expand All @@ -48,17 +49,14 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main_layout);
this.mTextViewBuild = findViewById(R.id.textViewBuild);
this.mTextViewAddress = findViewById(R.id.textViewUrlAddress);
buildVersion = SysUtils.getBuildVersion();
Log.d(TAG, "Build version: " + buildVersion);
Log.d(TAG, "Build version: " + mDeviceInfo.getSoftwareVersion());
serverAddress = utils.getServerAddress();
Log.d(TAG, "OTA server address: " + serverAddress);
this.mTextViewBuild.setText(buildVersion);
this.mTextViewBuild.setText(mDeviceInfo.getSoftwareVersion());
this.mTextViewAddress.setText(serverAddress);
updaterLock = new ReentrantLock();

String devType = SysUtils.getDeviceType();
String macAddress = SysUtils.findDeviceMAC();
mDeviceAuthorizationProvider = new AuthorizationProvider(buildVersion, devType, macAddress, serverAddress, this);
mDeviceAuthorizationProvider = new AuthorizationProvider(mDeviceInfo, serverAddress, this);
mHttpClient = new HttpClient(otaPackagePath, mDeviceAuthorizationProvider);
mWsClient = new ManagementClient(utils, mDeviceAuthorizationProvider);

Expand Down Expand Up @@ -99,7 +97,7 @@ private void onStartUpdateIntent() {

Log.d(TAG, "Start system update");
try {
mHttpClient.checkUpdate(buildVersion, serverAddress, utils, mUpdateManager);
mHttpClient.checkUpdate(mDeviceInfo, serverAddress, utils, mUpdateManager);
} catch (RuntimeException e) {
Log.e(TAG, "Update failed with exception:", e);
} finally {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.antmicro.update.rdfm.exceptions;

public class DeviceInfoException extends Exception {
public DeviceInfoException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.content.Context;
import android.util.Log;

import com.antmicro.update.rdfm.exceptions.DeviceInfoException;
import com.antmicro.update.rdfm.exceptions.DeviceUnauthorizedException;
import com.antmicro.update.rdfm.exceptions.ServerConnectionException;
import com.antmicro.update.rdfm.utilities.KeyUtils;
Expand All @@ -14,6 +15,7 @@
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

Expand All @@ -29,20 +31,15 @@ public class AuthorizationProvider implements IDeviceTokenProvider {
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
private static final int READ_TIMEOUT_MS = 500;
private static final long TOKEN_EXPIRATION_GRACE_PERIOD_MS = 5000;
private final String mSoftwareVersion;
private final String mDeviceType;
private final String mMacAddress;
private final String mServerAddress;
private final Context mContext;
private final OkHttpClient mClient;
private final DeviceInfoProvider mDeviceInfo;
private String mDeviceToken;
private long mTokenExpiresAt;

public AuthorizationProvider(String bspVersion, String devType, String macAddress,
String serverAddress, Context context) {
mSoftwareVersion = bspVersion;
mDeviceType = devType;
mMacAddress = macAddress;
public AuthorizationProvider(DeviceInfoProvider deviceInfo, String serverAddress, Context context) {
mDeviceInfo = deviceInfo;
mServerAddress = serverAddress;
mContext = context;
mDeviceToken = "";
Expand All @@ -62,10 +59,7 @@ private String registerRequest() throws ServerConnectionException, DeviceUnautho
Log.d(TAG, "Public key: " + key);

try {
JSONObject devParamsJSON = new JSONObject()
.put("rdfm.hardware.devtype", mDeviceType)
.put("rdfm.software.version", mSoftwareVersion)
.put("rdfm.hardware.macaddr", mMacAddress);
JSONObject devParamsJSON = new JSONObject(mDeviceInfo.toMap());
String reqJSON = new JSONObject()
.put("metadata", devParamsJSON)
.put("public_key", key)
Expand Down Expand Up @@ -115,7 +109,7 @@ private String registerRequest() throws ServerConnectionException, DeviceUnautho
Log.e(TAG, "Authorization request failed", e);
throw new ServerConnectionException("Failed to make authorization request");
}
} catch (JSONException e) {
} catch (JSONException | DeviceInfoException e) {
Log.e(TAG, "Authorization request failed", e);
throw new ServerConnectionException("Failed to make authorization request");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.antmicro.update.rdfm.mgmt;

import com.antmicro.update.rdfm.exceptions.DeviceInfoException;
import com.antmicro.update.rdfm.utilities.SysUtils;

import java.util.HashMap;
import java.util.Map;

import kotlin.contracts.Returns;

public class DeviceInfoProvider {
private String mDeviceMAC;

public DeviceInfoProvider() {
}

/**
* Get the device MAC to be used as a unique device identifier.
*
* @return device MAC
*/
public String getDeviceMAC() throws DeviceInfoException {
if (mDeviceMAC == null) {
try {
mDeviceMAC = SysUtils.findDeviceMAC();
} catch (RuntimeException e) {
throw new DeviceInfoException(e.getMessage());
}
}
return mDeviceMAC;
}

/**
* Get the device type identifier
*
* @return device type string
*/
public String getDeviceType() {
return SysUtils.getDeviceType();
}

/**
* Get the unique software version identifier
*
* @return software version identifier
*/
public String getSoftwareVersion() {
return SysUtils.getBuildVersion();
}

/**
* Save the metadata of the device as a map of Strings to String values.
*
* @return device metadata in map form
*/
public Map<String, String> toMap() throws DeviceInfoException {
Map<String, String> devParams = new HashMap<>();
devParams.put("rdfm.software.version", getSoftwareVersion());
devParams.put("rdfm.hardware.macaddr", getDeviceMAC());
devParams.put("rdfm.hardware.devtype", getDeviceType());
return devParams;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,5 @@ public static String getBuildVersion() {
public static String getDeviceType() {
return Build.PRODUCT;
}

public static String getSerialNumber() {
return getSystemProperties("ro.serialno");
}


}

0 comments on commit 97904b4

Please sign in to comment.