Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower minSdkVersion to 21 #96

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion calibration-app/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ android {

defaultConfig {
applicationId "org.dpppt.android.calibration"
minSdkVersion 23
minSdkVersion 21
targetSdkVersion 29
versionCode 2
versionName "0.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private SpannableString formatStatusString(TracingStatus status) {
for (TracingStatus.ErrorState error : errors) {
builder.append("\n").append(error.getErrorString(getContext()));
}
builder.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.red, null)),
builder.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.red)),
start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Build;
import android.os.PowerManager;

public class RequirementsUtil {
Expand All @@ -25,8 +26,13 @@ public static boolean isBluetoothEnabled() {
}

public static boolean isBatteryOptimizationDeactivated(Context context) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
} else {
// this phone is too old to turn them off, so we lie and say we did.
return true;
}
}

}
2 changes: 1 addition & 1 deletion dp3t-sdk/sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ android {
compileSdkVersion 29

defaultConfig {
minSdkVersion 23
minSdkVersion 21
targetSdkVersion 29
versionCode 50
versionName "0.5.0"
Expand Down
3 changes: 3 additions & 0 deletions dp3t-sdk/sdk/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.dpppt.android.sdk">

<uses-sdk tools:overrideLibrary="androidx.security"/>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ public static Collection<ErrorState> checkTracingErrorStatus(Context context, Ap
}

PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
boolean batteryOptimizationsDeactivated =
powerManager == null || powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
boolean batteryOptimizationsDeactivated;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
batteryOptimizationsDeactivated = powerManager == null ||
powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
} else {
// This phone is too old to do it, so we lie and say they did.
batteryOptimizationsDeactivated = true;
}
if (!batteryOptimizationsDeactivated) {
errors.add(ErrorState.BATTERY_OPTIMIZER_ENABLED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

Expand All @@ -33,7 +35,7 @@ public class ExposureDayStorage {

private static ExposureDayStorage instance;

private SharedPreferences esp;
private SharedPreferences sp;

public static synchronized ExposureDayStorage getInstance(Context context) {
if (instance == null) {
Expand All @@ -44,20 +46,39 @@ public static synchronized ExposureDayStorage getInstance(Context context) {

private ExposureDayStorage(Context context) {
try {
String KEY_ALIAS = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
esp = EncryptedSharedPreferences.create("dp3t_exposuredays_store",
KEY_ALIAS,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String KEY_ALIAS = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
sp = EncryptedSharedPreferences.create("dp3t_exposuredays_store",
KEY_ALIAS,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);

// See if there's data from API < 23 to migrate to secure storage.
SharedPreferences spOld = context.getSharedPreferences("dp3t_exposuredays_store_not_encrypted", Context.MODE_PRIVATE);
boolean needClear = false;
if (spOld.contains(PREF_KEY_LAST_ID)) {
sp.edit().putString(PREF_KEY_LAST_ID, spOld.getString(PREF_KEY_LAST_ID, "")).apply();
needClear = true;
}
if (spOld.contains(PREF_KEY_EEXPOSURE_DAYS)) {
sp.edit().putString(PREF_KEY_EEXPOSURE_DAYS, spOld.getString(PREF_KEY_EEXPOSURE_DAYS, "")).apply();
needClear = true;
}
if (needClear) {
spOld.edit().clear().apply();
}
} else {
sp = context.getSharedPreferences("dp3t_exposuredays_store_not_encrypted", Context.MODE_PRIVATE);
}
} catch (GeneralSecurityException | IOException ex) {
ex.printStackTrace();
}
}

private ExposureDayList getExposureDaysInternal() {
ExposureDayList list =
Json.safeFromJson(esp.getString(PREF_KEY_EEXPOSURE_DAYS, "[]"), ExposureDayList.class, ExposureDayList::new);
Json.safeFromJson(sp.getString(PREF_KEY_EEXPOSURE_DAYS, "[]"), ExposureDayList.class, ExposureDayList::new);

DayDate maxAgeForExposureDay = new DayDate().subtractDays(NUMBER_OF_DAYS_TO_KEEP_EXPOSED_DAYS);
Iterator<ExposureDay> iterator = list.iterator();
Expand Down Expand Up @@ -91,10 +112,10 @@ public void addExposureDay(Context context, ExposureDay exposureDay) {
}
}

int id = esp.getInt(PREF_KEY_LAST_ID, 0) + 1;
int id = sp.getInt(PREF_KEY_LAST_ID, 0) + 1;
exposureDay.setId(id);
previousExposureDays.add(exposureDay);
esp.edit()
sp.edit()
.putInt(PREF_KEY_LAST_ID, id)
.putString(PREF_KEY_EEXPOSURE_DAYS, Json.toJson(previousExposureDays))
.apply();
Expand All @@ -107,13 +128,13 @@ public void resetExposureDays() {
for (ExposureDay previousExposureDay : previousExposureDays) {
previousExposureDay.setDeleted(true);
}
esp.edit()
sp.edit()
.putString(PREF_KEY_EEXPOSURE_DAYS, Json.toJson(previousExposureDays))
.apply();
}

public void clear() {
esp.edit()
sp.edit()
.putString(PREF_KEY_EEXPOSURE_DAYS, Json.toJson(new ExposureDayList()))
.apply();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

Expand All @@ -27,7 +29,7 @@ public class PendingKeyUploadStorage {

private static PendingKeyUploadStorage instance;

private SharedPreferences esp;
private SharedPreferences sp;

public static synchronized PendingKeyUploadStorage getInstance(Context context) {
if (instance == null) {
Expand All @@ -38,24 +40,35 @@ public static synchronized PendingKeyUploadStorage getInstance(Context context)

private PendingKeyUploadStorage(Context context) {
try {
String KEY_ALIAS = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
esp = EncryptedSharedPreferences.create("dp3t_pendingkeyupload_store",
KEY_ALIAS,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String KEY_ALIAS = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
sp = EncryptedSharedPreferences.create("dp3t_pendingkeyupload_store",
KEY_ALIAS,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);

// Check if there are values in old pref file that need to be migrated to secure storage.
SharedPreferences spOld = context.getSharedPreferences("dp3t_pendingkeyupload_store_not_encrypted", Context.MODE_PRIVATE);
if (spOld.contains(PREF_KEY_PENDING_KEYS)) {
sp.edit().putString(PREF_KEY_PENDING_KEYS, spOld.getString(PREF_KEY_PENDING_KEYS, "")).apply();
spOld.edit().clear().apply();
}
} else {
sp = context.getSharedPreferences("dp3t_pendingkeyupload_store_not_encrypted", Context.MODE_PRIVATE);
}
} catch (GeneralSecurityException | IOException ex) {
ex.printStackTrace();
}
}

private PendingKeyList getPendingKeys() {
return Json.fromJson(esp.getString(PREF_KEY_PENDING_KEYS, "[]"), PendingKeyList.class);
return Json.fromJson(sp.getString(PREF_KEY_PENDING_KEYS, "[]"), PendingKeyList.class);
}

private void setPendingKeys(PendingKeyList list) {
Collections.sort(list, (a, b) -> Integer.compare(a.getRollingStartNumber(), b.getRollingStartNumber()));
esp.edit().putString(PREF_KEY_PENDING_KEYS, Json.toJson(list)).apply();
sp.edit().putString(PREF_KEY_PENDING_KEYS, Json.toJson(list)).apply();
}

public int peekRollingStartNumber() {
Expand Down Expand Up @@ -89,7 +102,7 @@ public void addPendingKey(PendingKey key) {
}

public void clear() {
esp.edit().clear().apply();
sp.edit().clear().apply();
}

public static class PendingKey {
Expand Down