diff --git a/.github/workflows/bintray-develop.yml b/.github/workflows/bintray-develop.yml new file mode 100644 index 00000000..ec2fa81f --- /dev/null +++ b/.github/workflows/bintray-develop.yml @@ -0,0 +1,19 @@ +name: Upload AAR to bintray + +on: + push: + branches: [ develop ] + +jobs: + build: + name: "Upload AAR to bintray" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Upload + run: cd dp3t-sdk; ./gradlew bintrayUpload -PbintrayUser=${{secrets.BINTRAY_USER}} -PbintrayApikey=${{secrets.BINTRAY_APIKEY}} -PbintrayVersionSuffix=-dev-$GITHUB_RUN_NUMBER diff --git a/.gitignore b/.gitignore index 9ca78015..441cd6b8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +# IntelliJ files +/.idea \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c04acd..2e51e1db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog for DP3T-SDK Android +## version 1.0.5 (24.9.2020) + +- support location less scanning on Android 11 +- fix state update bug when EN are activated/deactivated outside of the app +- update targetSdk to 30, use gradle 6.6.1 and Android-Plugin 4.0.1 +- fix https://github.com/DP-3T/dp3t-sdk-android/issues/206 + ## version 1.0.4 (25.8.2020) - exposed days are now deleted 14 days after reporting the exposureDay (before they were deleted 10 days after the exposure which could be only 1 day after reporting) diff --git a/README.md b/README.md index 29f4f5bb..fc6f1548 100644 --- a/README.md +++ b/README.md @@ -156,5 +156,16 @@ DP3T.sync(getContext()); Make sure you do not call this method on the UI thread, because it will perform the sync synchronously. Due to rate limits on the provideDiagnosisKeys() the sync can be execute only in a very restricted manner. +## Apps using the DP3T-SDK for Android +Name | Country | Source code | Store | Release-Date +---- | ----------- | ------------- | ------------- | ------------- +SwissCovid | Switzerland | [Github](https://github.com/DP-3T/dp3t-app-android-ch) | [PlayStore](https://play.google.com/store/apps/details?id=ch.admin.bag.dp3t) | 25. Mai 2020 +ASI | Ecuador | [minka.gob.ec](https://minka.gob.ec/asi-ecuador/android) | [PlayStore](https://play.google.com/store/apps/details?id=ec.gob.asi.android) | 2. August 2020 +Hoia | Estonia | [koodivaramu.eesti.ee](https://koodivaramu.eesti.ee/tehik/hoia/dp3t-app-android) | [PlayStore](https://play.google.com/store/apps/details?id=ee.tehik.hoia) | 18. August 2020 +STAYAWAY COVID | Portugal | [Github](https://github.com/stayawayinesctec/stayaway-app) | [PlayStore](https://play.google.com/store/apps/details?id=fct.inesctec.stayaway) | 28. August 2020 +Radar COVID | Spain | [Github](https://github.com/RadarCOVID/radar-covid-android) | [PlayStore](https://play.google.com/store/apps/details?id=es.gob.radarcovid) | + +If your project/country is not yet listed but uses the DP3T-SDK feel free to send a pull-request to add it to the [README](README). + ## License This project is licensed under the terms of the MPL 2 license. See the [LICENSE](LICENSE) file. diff --git a/calibration-app/app/build.gradle b/calibration-app/app/build.gradle index 83cf6f24..f89dcb6a 100644 --- a/calibration-app/app/build.gradle +++ b/calibration-app/app/build.gradle @@ -23,13 +23,13 @@ ext.readProperty = { paramName -> } android { - compileSdkVersion 29 + compileSdkVersion 30 buildToolsVersion "29.0.3" defaultConfig { applicationId "org.dpppt.android.calibration" minSdkVersion 23 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 2 versionName "0.2" diff --git a/calibration-app/build.gradle b/calibration-app/build.gradle index af53a3be..c6e300c1 100644 --- a/calibration-app/build.gradle +++ b/calibration-app/build.gradle @@ -16,7 +16,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' } } diff --git a/calibration-app/gradle/wrapper/gradle-wrapper.properties b/calibration-app/gradle/wrapper/gradle-wrapper.properties index e8cdbff1..feba0ac3 100644 --- a/calibration-app/gradle/wrapper/gradle-wrapper.properties +++ b/calibration-app/gradle/wrapper/gradle-wrapper.properties @@ -8,9 +8,9 @@ # SPDX-License-Identifier: MPL-2.0 # -#Mon Apr 06 09:12:35 CEST 2020 +#Wed Sep 09 14:40:57 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip diff --git a/dp3t-sdk/build.gradle b/dp3t-sdk/build.gradle index f1c0437a..59ab7283 100644 --- a/dp3t-sdk/build.gradle +++ b/dp3t-sdk/build.gradle @@ -9,7 +9,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' } diff --git a/dp3t-sdk/gradle/wrapper/gradle-wrapper.properties b/dp3t-sdk/gradle/wrapper/gradle-wrapper.properties index 3de6ea03..c3d53aee 100644 --- a/dp3t-sdk/gradle/wrapper/gradle-wrapper.properties +++ b/dp3t-sdk/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Mar 26 09:44:37 CET 2020 +#Wed Sep 09 14:40:57 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip diff --git a/dp3t-sdk/sdk/build.gradle b/dp3t-sdk/sdk/build.gradle index c8fab7d7..919e4af9 100644 --- a/dp3t-sdk/sdk/build.gradle +++ b/dp3t-sdk/sdk/build.gradle @@ -16,13 +16,13 @@ plugins { } android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { minSdkVersion 23 - targetSdkVersion 29 - versionCode 104 - versionName "1.0.4" + targetSdkVersion 30 + versionCode 105 + versionName "1.0.5" testInstrumentationRunnerArgument 'androidx.benchmark.suppressErrors', 'EMULATOR,LOW-BATTERY,ACTIVITY-MISSING,DEBUGGABLE,UNLOCKED,UNSUSTAINED-ACTIVITY-MISSING' testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" @@ -65,21 +65,22 @@ afterEvaluate { from components.productionRelease groupId 'org.dpppt' artifactId 'dp3t-sdk-android' - version android.defaultConfig.versionName + version android.defaultConfig.versionName + readPropertyWithDefault('bintrayVersionSuffix', '') artifact androidSourcesJar } "sdkCalibration"(MavenPublication) { from components.calibrationRelease groupId 'org.dpppt' artifactId 'dp3t-sdk-android' - version android.defaultConfig.versionName + "-calibration" + version android.defaultConfig.versionName + readPropertyWithDefault('bintrayVersionSuffix', '') + "-calibration" artifact androidSourcesJar } } } } -ext.readProperty = { paramName -> +ext.readProperty = { paramName -> readPropertyWithDefault(paramName, null) } +ext.readPropertyWithDefault = { paramName, defaultValue -> if (project.hasProperty(paramName)) { return project.getProperties().get(paramName) } else { @@ -87,7 +88,11 @@ ext.readProperty = { paramName -> if (project.rootProject.file('local.properties').exists()) { properties.load(project.rootProject.file('local.properties').newDataInputStream()) } - return properties.getProperty(paramName) + if (properties.getProperty(paramName) != null) { + return properties.getProperty(paramName) + } else { + return defaultValue + } } } @@ -114,7 +119,8 @@ sonarqube { } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + compileOnly fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + androidTestImplementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation 'androidx.core:core:1.2.0' implementation 'androidx.security:security-crypto:1.0.0-rc01' @@ -123,9 +129,9 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.8.1' implementation 'com.squareup.retrofit2:converter-gson:2.8.1' - implementation 'io.jsonwebtoken:jjwt-api:0.11.1' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.1' - runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.11.1') { + implementation 'io.jsonwebtoken:jjwt-api:0.11.2' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2' + runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.11.2') { exclude group: 'org.json', module: 'json' } implementation 'org.bouncycastle:bcprov-jdk15on:1.65' diff --git a/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/backend/SignatureVerificationInterceptorTest.java b/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/backend/SignatureVerificationInterceptorTest.java new file mode 100644 index 00000000..99b87f1e --- /dev/null +++ b/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/backend/SignatureVerificationInterceptorTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ +package org.dpppt.android.sdk.internal.backend; + +import android.content.Context; +import androidx.test.platform.app.InstrumentationRegistry; + +import java.io.IOException; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; + +import org.dpppt.android.sdk.backend.SignatureException; +import org.dpppt.android.sdk.internal.logger.LogLevel; +import org.dpppt.android.sdk.internal.logger.Logger; +import org.dpppt.android.sdk.internal.util.Base64Util; +import org.dpppt.android.sdk.models.DayDate; +import org.dpppt.android.sdk.util.SignatureUtil; +import org.junit.Before; +import org.junit.Test; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import okhttp3.mockwebserver.Dispatcher; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; + +import static org.dpppt.android.sdk.util.SignatureUtil.JWS_CLAIM_CONTENT_HASH; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class SignatureVerificationInterceptorTest { + + Context context; + MockWebServer server; + BackendBucketRepository bucketRepository; + KeyPair keyPair; + + @Before + public void setup() { + context = InstrumentationRegistry.getInstrumentation().getContext(); + + Logger.init(context, LogLevel.DEBUG); + + ProxyConfig.DISABLE_SYSTEM_PROXY = true; + + server = new MockWebServer(); + keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + + bucketRepository = new BackendBucketRepository(context, server.url("/bucket/").toString(), keyPair.getPublic()); + } + + private String getJwtForContent(String content) { + HashMap claims = new HashMap<>(); + try { + MessageDigest digest = MessageDigest.getInstance(SignatureUtil.HASH_ALGO); + claims.put(JWS_CLAIM_CONTENT_HASH, Base64Util.toBase64(digest.digest(content.getBytes()))); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return Jwts.builder().addClaims(claims).signWith(keyPair.getPrivate()).compact(); + } + + @Test + public void testValidSignature() throws IOException, StatusCodeException { + String responseString = "someRandomContent"; + server.setDispatcher(new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) { + + return new MockResponse() + .setResponseCode(200) + .setBody(responseString) + .addHeader(SignatureUtil.HTTP_HEADER_JWS, getJwtForContent(responseString)); + } + }); + String response = bucketRepository.getGaenExposees(new DayDate(), null).body().string(); + assertEquals(responseString, response); + } + + @Test + public void testInvalidSignature() throws IOException, StatusCodeException { + String responseString = "someRandomContent"; + server.setDispatcher(new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) { + return new MockResponse() + .setResponseCode(200) + .setBody(responseString) + .addHeader(SignatureUtil.HTTP_HEADER_JWS, getJwtForContent("differentContent")); + } + }); + try { + bucketRepository.getGaenExposees(new DayDate(), null).body().string(); + fail(); + } catch (SignatureException e) { + assertEquals("Signature mismatch", e.getMessage()); + } + } + + @Test + public void testInvalidJwt() throws IOException, StatusCodeException { + String responseString = "someRandomContent"; + server.setDispatcher(new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) { + return new MockResponse() + .setResponseCode(200) + .setBody(responseString) + .addHeader(SignatureUtil.HTTP_HEADER_JWS, + "eyJhbGciOiJFUzI1NiJ9.eyJjb250ZW50LWhhc2giOiJsTzd3TDBkOFl5MFBSaU" + + "w5NGhUa2txMkRXNUxXVjlPNi9zRWNZVDJHZ2t3PSIsImhhc2gtYWxnIjoic2hhLTI1Ni" + + "IsImlzcyI6ImRwM3QiLCJpYXQiOjE1ODgwODk2MDAsImV4cCI6MTU4OTkwNDAwMCwiYm" + + "F0Y2gtcmVsZWFzZS10aW1lIjoiMTU4ODA4OTYwMDAwMCJ9.1uiVGBOWqD8jLKm0_EOmN" + + "MMgHr4FQOsD1ci4iWR1QMitg_MPgtbuggedbuggedbuggedbuggedbuggedbugged"); + } + }); + try { + bucketRepository.getGaenExposees(new DayDate(), null).body().string(); + fail(); + } catch (SignatureException e) { + assertEquals("JWT signature does not match locally computed signature. " + + "JWT validity cannot be asserted and should not be trusted.", e.getMessage()); + } + } + +} diff --git a/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/nearby/LocationLessScanningTest.java b/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/nearby/LocationLessScanningTest.java new file mode 100644 index 00000000..a548c2c7 --- /dev/null +++ b/dp3t-sdk/sdk/src/androidTest/java/org/dpppt/android/sdk/internal/nearby/LocationLessScanningTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package org.dpppt.android.sdk.internal.nearby; + +import android.content.Context; +import android.os.Build; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.dpppt.android.sdk.internal.ErrorHelper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; + +@RunWith(AndroidJUnit4.class) +public class LocationLessScanningTest { + + private Context context; + + @Before + public void setup() { + context = InstrumentationRegistry.getInstrumentation().getContext(); + } + + @Test + public void checkLocationLessScanningOnAndroidR(){ + assertEquals(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R, ErrorHelper.deviceSupportsLocationlessScanning(context)); + } +} diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/DP3T.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/DP3T.java index e6a57669..f8b34db5 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/DP3T.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/DP3T.java @@ -99,10 +99,12 @@ private static void executeInit(Context context, AppConfigManager appConfigManag new BluetoothStateBroadcastReceiver(), new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) ); - context.registerReceiver( - new LocationServiceBroadcastReceiver(), - new IntentFilter(LocationManager.MODE_CHANGED_ACTION) - ); + if (!ErrorHelper.deviceSupportsLocationlessScanning(context)) { + context.registerReceiver( + new LocationServiceBroadcastReceiver(), + new IntentFilter(LocationManager.MODE_CHANGED_ACTION) + ); + } context.registerReceiver( new BatteryOptimizationBroadcastReceiver(), new IntentFilter(BatteryOptimizationBroadcastReceiver.ACTION_POWER_SAVE_WHITELIST_CHANGED) @@ -205,6 +207,7 @@ public static void sync(Context context) { public static TracingStatus getStatus(Context context) { checkInit(); + GaenStateHelper.invalidateGaenEnabled(context); AppConfigManager appConfigManager = AppConfigManager.getInstance(context); Collection errorStates = ErrorHelper.checkTracingErrorStatus(context, appConfigManager); InfectionStatus infectionStatus; diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/backend/SignatureVerificationInterceptor.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/backend/SignatureVerificationInterceptor.java index 4505041d..e4632d55 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/backend/SignatureVerificationInterceptor.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/backend/SignatureVerificationInterceptor.java @@ -12,6 +12,7 @@ import androidx.annotation.NonNull; import java.io.IOException; +import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; @@ -21,11 +22,12 @@ import okhttp3.Interceptor; import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.BufferedSource; +import okio.Okio; public class SignatureVerificationInterceptor implements Interceptor { - private static final long PEEK_MEMORY_LIMIT = 64 * 1024 * 1024L; - private final PublicKey publicKey; public SignatureVerificationInterceptor(PublicKey publicKey) { @@ -56,12 +58,20 @@ public Response intercept(@NonNull Chain chain) throws IOException { byte[] signedContentHash = SignatureUtil.getVerifiedContentHash(jwsHeader, publicKey); - byte[] body = response.peekBody(PEEK_MEMORY_LIMIT).bytes(); + ResponseBody body = response.body(); + BufferedSource responseBuffer = Okio.buffer(Okio.source(body.byteStream())); byte[] actualContentHash; try { MessageDigest digest = MessageDigest.getInstance(SignatureUtil.HASH_ALGO); - actualContentHash = digest.digest(body); + try (InputStream bodyStream = responseBuffer.peek().inputStream()) { + byte[] buffer = new byte[1024]; + int len; + while ((len = bodyStream.read(buffer)) != -1) { + digest.update(buffer, 0, len); + } + } + actualContentHash = digest.digest(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } @@ -70,7 +80,12 @@ public Response intercept(@NonNull Chain chain) throws IOException { throw new SignatureException("Signature mismatch"); } - return response; + return response.newBuilder() + .body(ResponseBody.create( + body.contentType(), + body.contentLength(), + responseBuffer) + ).build(); } } diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/ErrorHelper.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/ErrorHelper.java index 7bdc5546..4aa2a3c8 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/ErrorHelper.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/ErrorHelper.java @@ -13,6 +13,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.PowerManager; +import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; @@ -21,7 +22,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; - import javax.net.ssl.SSLException; import com.google.android.gms.common.api.ApiException; @@ -62,7 +62,7 @@ public static Collection checkTracingErrorStatus(Context context, Ap } } - if (!LocationServiceUtil.isLocationEnabled(context)) { + if (!deviceSupportsLocationlessScanning(context) && !LocationServiceUtil.isLocationEnabled(context)) { errors.add(ErrorState.LOCATION_SERVICE_DISABLED); } @@ -105,6 +105,11 @@ public static Collection checkTracingErrorStatus(Context context, Ap return errors; } + public static boolean deviceSupportsLocationlessScanning(Context context) { + return Settings.Global.getInt(context.getApplicationContext().getContentResolver(), + "bluetooth_sanitized_exposure_notification_supported", 0) == 1; + } + public static Collection getDelayableSyncErrors() { return new HashSet<>(DELAYABLE_SYNC_ERRORS); } diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/SyncWorker.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/SyncWorker.java index 8402eaf9..96dcf415 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/SyncWorker.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/SyncWorker.java @@ -344,6 +344,8 @@ private void uploadPendingKeys(Context context) { } if (gaenKey == null) { //key for specified rollingStartNumber was not found, user must have cleared data + DP3T.stop(context); + appConfigManager.setIAmInfectedIsResettable(true); continue; } } else { diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/util/LocationServiceUtil.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/util/LocationServiceUtil.java index f488c38a..3a339ac6 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/util/LocationServiceUtil.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/internal/util/LocationServiceUtil.java @@ -7,7 +7,6 @@ * * SPDX-License-Identifier: MPL-2.0 */ - package org.dpppt.android.sdk.internal.util; import android.content.Context; @@ -17,7 +16,7 @@ public class LocationServiceUtil { - public static Boolean isLocationEnabled(Context context) { + public static boolean isLocationEnabled(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); return lm != null && lm.isLocationEnabled(); diff --git a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/util/SignatureUtil.java b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/util/SignatureUtil.java index 303b4d7b..256fecf9 100644 --- a/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/util/SignatureUtil.java +++ b/dp3t-sdk/sdk/src/main/java/org/dpppt/android/sdk/util/SignatureUtil.java @@ -7,7 +7,6 @@ * * SPDX-License-Identifier: MPL-2.0 */ - package org.dpppt.android.sdk.util; import android.util.Base64; @@ -35,7 +34,7 @@ public class SignatureUtil { public static final String HTTP_HEADER_JWS = "signature"; public static final String HASH_ALGO = "SHA-256"; - private static final String JWS_CLAIM_CONTENT_HASH = "content-hash"; + public static final String JWS_CLAIM_CONTENT_HASH = "content-hash"; public static PublicKey getPublicKeyFromBase64(String publicKeyBase64) throws NoSuchAlgorithmException, InvalidKeySpecException {