Giter VIP home page Giter VIP logo

corona-warn-companion-android's Introduction

corona-warn-companion-android

Android App Which Shows Details about CWA Exposures (Requires Root)

© 2020-2022 Michael Huebler and other contributors. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.


Deutsche Anleitungen z.B. hier:


How to install the app

There are 3 options:

1. Get the app from the Play Store

  1. Download from https://play.google.com/store/apps/details?id=org.tosl.warnappcompanion
  2. Write a short review

2. Install a release from GitHub

  1. Download the latest released APK from the Assets at https://github.com/mh-/corona-warn-companion-android/releases
  2. Install via adb tool and USB cable: adb install corona-warn-companion-github-release.apk

3. Build the app from source code, using Android Studio

  1. git clone https://github.com/mh-/corona-warn-companion-android.git
  2. In Android Studio, select a 'flavor': github is the normal version, called "Corona-Warn-Companion". playstore is a version that was renamed to "Warn-App-Companion" because of the Play Store requirements for COVID-19 apps; this is not a category 1 or 2 app and must therefore not use COVID-19 related terms in its Play Store listing.
  3. Build the debug build variant, and install it on your device. The release build variant will probably build out-of-the box only on macOS because of the way how the keystore for app signing is accessed.

How to use the app

After a lot of user feedback and many iterations, the app meanwhile has several modes. The best user experience is available if the device is rooted and the app gets root permissions: With root permissions, the app can directly access the database from a framework where the recorded Rolling Proximity IDs (RPIs) are stored.

However, since many users cannot or do not wish to root their device, other options (RaMBLE and CCTG) are also available, where another app can export their recorded RPIs, so that this app can read them without root rights, and work with them.

The currently available modes are:

Modes that require root permissions:

Normal mode (root):

This app reads RPIs from the Google Exposure Notifications service / framework. Works together with the official Corona-Warn-App.

microG mode (root):

This app reads RPIs from the microG ENF framework. This works if you have installed microG and an app that activates microG ENF RPI recording, and give root access to this app.

Modes that work without root:

CCTG Export (this is not a special mode within this app, use 'sharing' from CCTG to activate this):

This requires the installation of the Corona Contact Tracing Germany app. On the next day, export the tracing information from CCTG and share with this app as described in the CCTG FAQ. If you tap "export" on the microG ENF screen, and select to share with this app (tap on the Friendly Dog icon), this app is called and automatically reads the data, and also automatically selects "microG mode" in the process.

Note that the next time you want to use this app, you need to follow the same steps again (export and share from CCTG / microG ENF).

CCTG Import:

NOTE: It's easier to use the CCTG Export (as explained above) instead

This app can read RPIs from a file created by the Corona Contact Tracing Germany app (which brings its own microG framework that stores the RPIs in its own location: /data/data/de.corona.tracing/databases/exposure.db). Works if you have installed CCTG and if you can copy the database file to a location where you can select it from within this app - e.g. by doing adb shell su -c cp /data/data/de.corona.tracing/databases/exposure.db /storage/emulated/0/Download/. One thing you can also do using this mode: Use a copy of a database file that was copied from a slow device, where analysis takes very long, on another more capable device, where analysis runs faster.

RaMBLE Import:

This mode requires the installation of the RamBLE - Bluetooth LE Mapper app.

You need to record with the RaMBLE app (to record, tap the "▶" button). And then on the next day, export the database (tap the "⋮" button in the top right corner, select "Export Database"). Then set this app to RaMBLE Mode (tap the "⋮" menu button in the top right corner, select "RaMBLE Mode"). You then need to select the newest "RaMBLE_..." file from the "Downloads" directory, where RaMBLE has stored its exported database.

Note that the next time you want to use this app, you need to follow the same steps again (export from RaMBLE, select the file in this app).

Note that the Exposure Notifications database contains calibrated_rssi (see here). RaMBLE however stores only raw_rssi, which means that the colors shown on the details screen are probably different from the case when the app reads the Exposure Notifications database.


(BTW, if you wonder why this explanation is not part of the Play Store text: This is because of the Play Store requirements for COVID-19 apps; this is not a category 1 or 2 app and must therefore not use COVID-19 related terms in its Play Store listing.)


Features

This app helps you to better understand warnings of the official Corona-Warn-App (or its CCTG fork).

ATTENTION: To access the same recorded encounters as the official Corona-Warn-App, this app requires ROOT permissions. Without root permissions, the app can only be used together with the RaMBLE app, or with the CCTG app / microG. Please read the "How to use the app" section above.

What the app does:

  1. The app reads the Rolling Proximity IDs recorded by your device from the Exposure Notifications database (this is only possible with root permissions, which is why official Exposure Notifications apps, such as Corona-Warn-App, cannot display these details).
    -Example Recorded Encounters- Alternatively, without root permissions, the app can also read a database exported from the RaMBLE - Bluetooth LE Mapper app, or from the CCTG Corona Contact Tracing Germany app / microG.
  2. The app downloads the Diagnosis Keys from the official German Corona-Warn-Server and other countries' servers, as selected by you. For Germany, it downloads the keys published daily for the last few days, and the keys published every hour for today. Only keys for the days found in step 1 are shown and counted.
    -Example Diagnosis Keys-
  3. The app compares both in order to find matches (risk encounters).
    -Example Matches-

If risk encounters are found, it shows the details: At which times and with which radio attenuation (roughly corresponds to the distance) did the encounters take place, and what level of transmission risk did the encounters have. For encounters that were recorded by RaMBLE, it can also display the location.

-Example Details-

Note that 1 means a low and 8 means a high transmission risk.

What the app does not do:

  • The app does not process any personal data.
  • The app only accesses the internet for the purpose 2 (see above), i.e. it only downloads data from the official warning servers and does not send any data to other servers (unless you ask it to show the location of an encounter, in which case it will contact OpenStreetMap servers).
  • The app does not show any advertising.

Open Source

The source code of the app is published at https://github.com/mh-/corona-warn-companion-android, so you can check the source code, build the app yourself, and you are also welcome to contribute to improvements.

Countries covered

Download from the German server: 🇩🇪 Germany, 🇧🇪 Belgium, 🇩🇰 Denmark, 🇪🇪 Estonia, 🇫🇮 Finland, 🇮🇪 Ireland, 🇮🇹 Italy, 🇭🇷 Croatia, 🇱🇻 Latvia, 🇱🇹 Lithuania, 🇲🇹 Malta, 🇳🇱 Netherlands, 🇳🇴 Norway, 🇵🇱 Poland, 🇸🇮 Slovenia, 🇨🇭 Switzerland, 🇪🇸 Spain

Download from the respective country's server:

  • Belgium
  • Canada
  • Netherlands
  • Poland
  • Switzerland
  • England and Wales

In the top right hand corner of the app is a menu button, please use this to select the countries from which you want to download Diagnosis Keys.

Please note that we mainly follow changes that happen in the German CWA setup; if you experience problems with another country, please let us know via a GitHub issue.

Other

  • The app is used for private purposes only, it is not used for any business purposes.
  • The app is not a "hacking tool". It only reads data from the memory of your own device, which is stored there without additional encryption.

corona-warn-companion-android's People

Contributors

ginkel avatar izzysoft avatar karatekhd avatar kbobrowski avatar kerel-fs avatar mh- avatar pdehaye avatar thekerbycz avatar tlambertz avatar uhengart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

corona-warn-companion-android's Issues

Non root - use ramble log for calculations

It would be nice to use ramble Bluetooth scanner Logfiles for users that don't have root. But i can log only the discovery uid andb8t would be nice to use your tool to compare the ids in the log to that on the warn app servers

LevelDB unmap() has been disabled

In order to achieve Android 6 compatibility (see #1) I disabled the unmap() method in LevelDB, see mh-/leveldb@af5a31d
because of this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.tosl.coronawarncompanion, PID: 4872
    java.lang.AssertionError: java.lang.NoSuchMethodException: cleaner []
        at org.iq80.leveldb.fileenv.ByteBufferSupport.<clinit>(ByteBufferSupport.java:36)
        at org.iq80.leveldb.fileenv.MMWritableFile.unmap(MMWritableFile.java:98)
        at org.iq80.leveldb.fileenv.MMWritableFile.destroyMappedByteBuffer(MMWritableFile.java:64)
        at org.iq80.leveldb.fileenv.MMWritableFile.close(MMWritableFile.java:112)
        at org.iq80.leveldb.fileenv.EnvImpl$DelegateWritableFile.close(EnvImpl.java:215)
        at org.iq80.leveldb.impl.DbImpl.buildTable(DbImpl.java:1352)

This will however most probably lead to memory leaks, and I should try to find a better solution than fully disabling the method.

Remember which keys have been already checked, and download only new keys

(user request; intention is to save time)
This would have to be an option of some sort.
We also need to find a solution for RaMBLE, where the user might not have exported the latest database; in this case, matching with the same keys would make sense again when a newer RaMBLE database has been exported.

Add other country-specific Diagnosis Key download mechanisms

It should be possible to adapt this to work with any exposure notification apps, not just CWA. That would involve adding different servers and logics to retrieve/use the keys. These logics are known, would you be interested to work on this?

Show TX Power on Details Screen

Request: "perhaps it would be a good idea to implement information about tx power, as it may detect some modes of attack (e.g. transmitting with very low declared power which would result in everyone in large radius inferring strong signal when matching)"

App start-loops when enabling microg without having su

First, let me thank you for this amazing app!

I am on an unrooted phone. When I open the app and select microg, the app does not open, and logcat shows an endless loop of the app opening, doing su, requesting the database, crashing, opening, ....

The only way out is to delete all app-data in android settings.

Logcat output

10-20 14:41:21.152  8077  8077 D MicroGDbOnDisk: Trying to copy microG database
10-20 14:41:21.156  8077  8077 W System.err: java.io.IOException: Cannot run program "su": error=2, No such file or directory
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.Runtime.exec(Runtime.java:699)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.Runtime.exec(Runtime.java:529)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.Runtime.exec(Runtime.java:426)
10-20 14:41:21.158  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.gmsreadout.Sudo.sudo(Sudo.java:45)
10-20 14:41:21.158  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.microgreadout.MicroGDbOnDisk.copyFromGMS(MicroGDbOnDisk.java:70)
10-20 14:41:21.158  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.microgreadout.MicroGDbOnDisk.getRpisFromContactDB(MicroGDbOnDisk.java:94)
10-20 14:41:21.158  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:318)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.Activity.performCreate(Activity.java:8000)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.Activity.performCreate(Activity.java:7984)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.os.Handler.dispatchMessage(Handler.java:106)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.os.Looper.loop(Looper.java:223)
10-20 14:41:21.158  8077  8077 W System.err: 	at android.app.ActivityThread.main(ActivityThread.java:7656)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.reflect.Method.invoke(Native Method)
10-20 14:41:21.158  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
10-20 14:41:21.158  8077  8077 W System.err: 	at com.android.internal.os.ExecInit.main(ExecInit.java:43)
10-20 14:41:21.158  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
10-20 14:41:21.158  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)
10-20 14:41:21.158  8077  8077 W System.err: Caused by: java.io.IOException: error=2, No such file or directory
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.UNIXProcess.forkAndExec(Native Method)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.UNIXProcess.<init>(UNIXProcess.java:133)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.ProcessImpl.start(ProcessImpl.java:141)
10-20 14:41:21.158  8077  8077 W System.err: 	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
10-20 14:41:21.158  8077  8077 W System.err: 	... 24 more
10-20 14:41:21.158  8077  8077 D MicroGDbOnDisk: Result from trying to copy LevelDB: 
10-20 14:41:21.158  8077  8077 E MicroGDbOnDisk: ERROR: Super User rights not granted!
10-20 14:41:21.160  8077  8077 E SQLiteLog: (14) cannot open file at line 38589 of [b2325a6e1c]
10-20 14:41:21.160  8077  8077 E SQLiteLog: (14) os_unix.c:38589: (2) open(/storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_) - 
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: Failed to open database '/storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_'.
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_': File /storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_ doesn't exist
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:252)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:205)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:505)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:198)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:918)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:898)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:789)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:736)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at org.tosl.coronawarncompanion.microgreadout.MicroGDbOnDisk.getRpisFromContactDB(MicroGDbOnDisk.java:96)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:318)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.Activity.performCreate(Activity.java:8000)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.Activity.performCreate(Activity.java:7984)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.os.Handler.dispatchMessage(Handler.java:106)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.os.Looper.loop(Looper.java:223)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.app.ActivityThread.main(ActivityThread.java:7656)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at java.lang.reflect.Method.invoke(Native Method)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at com.android.internal.os.ExecInit.main(ExecInit.java:43)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:224)
10-20 14:41:21.166  8077  8077 E SQLiteDatabase: 	... 27 more
10-20 14:41:21.166  8077  8077 W System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_': File /storage/emulated/10/Android/data/org.tosl.warnappcompanion/cache/exposure.db_ doesn't exist
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:252)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:205)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:505)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:198)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:918)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:898)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:789)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:736)
10-20 14:41:21.166  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.microgreadout.MicroGDbOnDisk.getRpisFromContactDB(MicroGDbOnDisk.java:96)
10-20 14:41:21.166  8077  8077 W System.err: 	at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:318)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.app.Activity.performCreate(Activity.java:8000)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.app.Activity.performCreate(Activity.java:7984)
10-20 14:41:21.166  8077  8077 W System.err: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.os.Handler.dispatchMessage(Handler.java:106)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.os.Looper.loop(Looper.java:223)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.app.ActivityThread.main(ActivityThread.java:7656)
10-20 14:41:21.167  8077  8077 W System.err: 	at java.lang.reflect.Method.invoke(Native Method)
10-20 14:41:21.167  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
10-20 14:41:21.167  8077  8077 W System.err: 	at com.android.internal.os.ExecInit.main(ExecInit.java:43)
10-20 14:41:21.167  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
10-20 14:41:21.167  8077  8077 W System.err: 	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)
10-20 14:41:21.167  8077  8077 W System.err: Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
10-20 14:41:21.167  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
10-20 14:41:21.167  8077  8077 W System.err: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:224)
10-20 14:41:21.167  8077  8077 W System.err: 	... 27 more
10-20 14:41:21.175  8077  8077 D AndroidRuntime: Shutting down VM
10-20 14:41:21.176  8077  8077 E AndroidRuntime: FATAL EXCEPTION: main
10-20 14:41:21.176  8077  8077 E AndroidRuntime: Process: org.tosl.warnappcompanion, PID: 8077
10-20 14:41:21.176  8077  8077 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{org.tosl.warnappcompanion/org.tosl.coronawarncompanion.MainActivity}: java.lang.IllegalStateException
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
10-20 14:41:21.176  8077  80710-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at org.tosl.coronawarncompanion.MainActivity.showExtractionError(MainActivity.java:410)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:361)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8000)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:7984)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	... 13 more
10-20 14:41:21.176  8077  8077 E AndroidRuntime: Error reporting crash
10-20 14:41:21.176  8077  8077 E AndroidRuntime: java.lang.RuntimeException: Bad file descriptor
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.BinderProxy.transactNative(Native Method)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.BinderProxy.transact(BinderProxy.java:540)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.IActivityManager$Stub$Proxy.handleApplicationCrash(IActivityManager.java:5182)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:158)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.Thread.dispatchUncaughtException(Thread.java:2203)
10-20 14:41:21.176  8077  8077 I Process : Sending signal. PID: 8077 SIG: 9
10-20 14:41:21.219  1016 10400 I ActivityManager: Process org.tosl.warnappcompanion (pid 8077) has died: fg  TOP 
7 E AndroidRuntime: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:223)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7656)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.ExecInit.main(ExecInit.java:43)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: Caused by: java.lang.IllegalStateException
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at org.tosl.coronawarncompanion.MainActivity.showExtractionError(MainActivity.java:410)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:361)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8000)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:7984)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	... 13 more
10-20 14:41:21.176  8077  8077 E AndroidRuntime: Error reporting crash
10-20 14:41:21.176  8077  8077 E AndroidRuntime: java.lang.RuntimeException: Bad file descriptor
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.BinderProxy.transactNative(Native Method)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.os.BinderProxy.transact(BinderProxy.java:540)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at android.app.IActivityManager$Stub$Proxy.handleApplicationCrash(IActivityManager.java:5182)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:158)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
10-20 14:41:21.176  8077  8077 E AndroidRuntime: 	at java.lang.Thread.dispatchUncaughtException(Thread.java:2203)
10-20 14:41:21.176  8077  8077 I Process : Sending signal. PID: 8077 SIG: 9
10-20 14:41:21.219  1016 10400 I ActivityManager: Process org.tosl.warnappcompanion (pid 8077) has died: fg  TOP 

java.lang.NullPointerException: MainActivity.java:531

4 occurrences, app version 1.2.1, Android 10 (SDK 29), Huawei Honor 10

java.lang.NullPointerException:
at org.tosl.coronawarncompanion.MainActivity.presentMatchResults (MainActivity.java:531)
at org.tosl.coronawarncompanion.MainActivity.access$900 (MainActivity.java:88)
at org.tosl.coronawarncompanion.MainActivity$1.handleMessage (MainActivity.java:490)
at android.os.Handler.dispatchMessage (Handler.java:107)
at android.os.Looper.loop (Looper.java:213)
at android.app.ActivityThread.main (ActivityThread.java:8178)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1101)

Small question about the proto buffer export.bin diagnosis key download and the count displayed in graph (Belgium)

Hello,

I'm a bit confused.

The latest graph from yesterday displayed 81 diagnosis keys downloaded on 19-10 when the file itself (linked below) contained 655 diagnosis keys. Similar discrepancies for the previous days where the number in the graph is substantially lower than the download file.

https://c19distcdn-prd.ixor.be/version/v1/diagnosis-keys/country/BE/date/2020-10-19
https://c19distcdn-prd.ixor.be/version/v1/diagnosis-keys/country/BE/date/2020-10-18
https://c19distcdn-prd.ixor.be/version/v1/diagnosis-keys/country/BE/date/2020-10-17

Am I missing something obvious?

temp

Then debugging of the app itselfs shows:

D/org.tosl.coronawarncompanion.dkdownload.DKDownloadBelgium: Downloaded day: 2020-10-19
D/Unzip: Unzipped file. Length: 19751
D/DKDownloadUtils: Number of keys in this file: 655

Shouldn't the graph display 655 keys for 2020-10-19 but yet only displays 81?

Thanks to anyone helping :)

support for microg Database

Hello

Since the latest Release microg now also offers an Exposure Notifications API for COVID-19 apps. But this seems to be incompatible with this app.

As you can see on the pictures here, there is something wrong with the access. A smart person told me that microg uses a different database for this.

Is there a chance that this app will be extended with the microg database?
.../ExposureDatabase.kt

Thanks ❤️

Incomplete time range in RaMBLE mode

I am using this app (v1.3.4) in RaMBLE mode. Despite exporting a current database from RaMBLE, the time range displayed in Warn Companion ends at 2020-10-12:

image

Any ideas?

P.S.: If that helps I could share the RaMBLE SQLite database, but would prefer to do so privately.

java.lang.NoClassDefFoundError on Android 6

Hi, looks very interesting but unfortunately cannot run it on Android 6, it fails right after launch on both device and emulator at this line.

On Android >= 7 seems to work fine, but don't have rooted device running this version of Android at the moment.

Maybe this stackoverflow answer has something to do with it - leveldb depends on guava, maybe it should depend on "*-android" artifact.

In the worst case I can try with C bindings for reading leveldb

$ adb shell am start -n "org.tosl.coronawarncompanion/org.tosl.coronawarncompanion.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 4402 on device 'emulator-5554'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/art: Rejecting re-init on previously-failed class java.lang.Class<androidx.core.view.ViewCompat$2>
I/MainActivity: --- DEMO MODE ---
D/MainActivity: Local TimeZone Offset in seconds: 7200
D/ContactDbOnDisk: Trying to copy LevelDB from Assets
D/ContactDbOnDisk: Copied LevelDB.
I/art: Rejecting re-init on previously-failed class java.lang.Class<org.iq80.leveldb.impl.-$$Lambda$h1Ue1jla2_tk3yRwBjksN2-EIPE>
    Rejecting re-init on previously-failed class java.lang.Class<org.iq80.leveldb.impl.-$$Lambda$h1Ue1jla2_tk3yRwBjksN2-EIPE>
I/art: Rejecting re-init on previously-failed class java.lang.Class<org.iq80.leveldb.fileenv.-$$Lambda$JavaFile$Ynx4pR_fGz1gSUlPpg_Y1_9KF6s>
    Rejecting re-init on previously-failed class java.lang.Class<org.iq80.leveldb.fileenv.-$$Lambda$JavaFile$Ynx4pR_fGz1gSUlPpg_Y1_9KF6s>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.CacheBuilder$2>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.CacheBuilder$2>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.LoadingCache>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.LoadingCache>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.LocalCache$LocalLoadingCache>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.cache.LocalCache$LocalLoadingCache>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Equivalence>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierComposition>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierComposition>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$NonSerializableMemoizingSupplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$NonSerializableMemoizingSupplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$MemoizingSupplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$MemoizingSupplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$ExpiringMemoizingSupplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$ExpiringMemoizingSupplier>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierOfInstance>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierOfInstance>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierFunction>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierFunction>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierFunctionImpl>
I/art: Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierFunctionImpl>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Function>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Supplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$ThreadSafeSupplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$ThreadSafeSupplier>
    Rejecting re-init on previously-failed class java.lang.Class<com.google.common.base.Suppliers$SupplierOfInstance>
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.tosl.coronawarncompanion, PID: 4402
    java.lang.NoClassDefFoundError: com.google.common.base.Suppliers$SupplierOfInstance
        at com.google.common.base.Suppliers.ofInstance(Suppliers.java:268)
        at com.google.common.cache.CacheBuilder.<clinit>(CacheBuilder.java:165)
        at org.iq80.leveldb.util.LRUCache.<init>(LRUCache.java:41)
        at org.iq80.leveldb.util.LRUCache.createCache(LRUCache.java:51)
        at org.iq80.leveldb.impl.TableCache.<init>(TableCache.java:58)
        at org.iq80.leveldb.impl.DbImpl.<init>(DbImpl.java:186)
        at org.iq80.leveldb.impl.Iq80DBFactory.open(Iq80DBFactory.java:68)
        at org.tosl.coronawarncompanion.gmsreadout.ContactDbOnDisk.open(ContactDbOnDisk.java:139)
        at org.tosl.coronawarncompanion.gmsreadout.ContactDbOnDisk.getRpisFromContactDB(ContactDbOnDisk.java:198)
        at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:135)
        at android.app.Activity.performCreate(Activity.java:6237)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Crash on API 30 (Android R)

App version 1.0.6 crashes:

D/ContactDbOnDisk: Trying to copy LevelDB
W/ContextImpl: Failed to ensure /storage/emulated/0/Android/data/org.tosl.warnappcompanion/cache: android.os.ServiceSpecificException:  (code -1)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.tosl.warnappcompanion, PID: 5266
    java.lang.RuntimeException: Unable to start activity ComponentInfo{org.tosl.warnappcompanion/org.tosl.coronawarncompanion.MainActivity}: java.lang.NullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.NullPointerException
        at java.util.Objects.requireNonNull(Objects.java:220)
        at org.tosl.coronawarncompanion.gmsreadout.ContactDbOnDisk.copyFromGMS(ContactDbOnDisk.java:65)
        at org.tosl.coronawarncompanion.gmsreadout.ContactDbOnDisk.getRpisFromContactDB(ContactDbOnDisk.java:218)
        at org.tosl.coronawarncompanion.MainActivity.onCreate(MainActivity.java:205)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

Code:

        Log.d(TAG, "Trying to copy LevelDB");
        String cachePathStr = Objects.requireNonNull(context.getExternalCacheDir()).getPath();

0 diagnosis keys downloaded

I installed WAC 1.3.0 on a device today, and initially did not have root access.

Initially, WAC downloaded the diagnosis keys based on the country selection, and showed the statistics of the downloaded keys in the second graph.

I fiddled around with the Android system to get root access (using Magisk), and after that, WAC does not complain about missing root access anymore, but now, it doesn't show any diagnosis key downloads:

image

This is on a Samsung Galaxy A3 running Android 6.0.1. CWA has also been installed only today (i.e. does not yet have a risk assessment).

Alternatives for non-rooted devices

Are there any possibilities for non-rooted devices to use the app with already existing records?

I know about the RaMBLE mode but this seems to work only on newly recorded data, not on old already traced contacts.

In the Android location settings it is possible to switch to the "COVID-19-Benachrichtigungen" and export information about the "Überprüfung auf mögliche Begegnungen". I know that these export doesn't include information about the attenuation in dB but perhaps in can be used to display some more insights than the official apps do!?

ConcurrentModificationException when switching from Normal Mode to Demo Mode while DKs are still being downloaded

D/MainActivity: Downloads left: 0
    Number of keys that have been downloaded: 42642
D/Matcher: Started matching...
E/AndroidRuntime: FATAL EXCEPTION: BackgroundMatcher
    Process: org.tosl.coronawarncompanion, PID: 12633
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:831)
        at org.tosl.coronawarncompanion.matcher.Matcher.findMatches(Matcher.java:96)
        at org.tosl.coronawarncompanion.MainActivity$BackgroundMatching.run(MainActivity.java:523)
        at android.os.Handler.handleCallback(Handler.java:836)
        at android.os.Handler.dispatchMessage(Handler.java:103)
        at android.os.Looper.loop(Looper.java:203)
        at android.os.HandlerThread.run(HandlerThread.java:61)

Matcher.java:96:

            for (Crypto.RpiWithInterval dkRpiWithInterval : dkRpisWithIntervals) {

io.reactivex.rxjava3.exceptions.UndeliverableException

Play Store Release 1.3.2
Android 10, Samsung Galaxy S9+

io.reactivex.rxjava3.exceptions.UndeliverableException: 
  at io.reactivex.rxjava3.plugins.RxJavaPlugins.onError (RxJavaPlugins.java:367)
  at io.reactivex.rxjava3.subjects.ReplaySubject.onError (ReplaySubject.java:373)
  at org.tosl.coronawarncompanion.dkdownload.-$$Lambda$H3l_4TOAnevR-vcMNir9nCKfoFA.onErrorResponse (Unknown Source:2)
  at com.android.volley.Request.deliverError (Request.java:617)
  at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run (ExecutorDelivery.java:104)
  at android.os.Handler.handleCallback (Handler.java:883)
  at android.os.Handler.dispatchMessage (Handler.java:100)
  at android.os.Looper.loop (Looper.java:237)
  at android.app.ActivityThread.main (ActivityThread.java:8125)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:496)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1100)
Caused by: com.android.volley.TimeoutError: 
  at com.android.volley.toolbox.BasicNetwork.performRequest (BasicNetwork.java:173)
  at com.android.volley.NetworkDispatcher.processRequest (NetworkDispatcher.java:131)
  at com.android.volley.NetworkDispatcher.processRequest (NetworkDispatcher.java:111)
  at com.android.volley.NetworkDispatcher.run (NetworkDispatcher.java:90)

@kbobrowski Any idea on this one?

Handle BDADDR collisions (RaMBLE)

RaMBLE uses the BDADDR of the beacon to determine whether the beacon has been seen before, and places all information with the same BDADDR into the same table row.
Random BDADDR are shorter and can therefore collide more often than RPIs.

A corresponding problem was reported by @uhengart in PR #56.

Own experiments show that RaMBLE updates the database table row when other service data (RPI) is received. So the RaMBLE database only contains the last seen RPI, but the first_seen field might correspond to an earlier sighting of a completely different device, that randomly chose the same BDADDR.
Therefore we should handle the first_seen field with caution, maybe limit the duration to 30 minutes (backwards from last_seen), which would be slightly more than the maximum time between to BDADDR / RPI rotations.

Crash in /system/lib64/libcrypto.so (SHA256_Update+36): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) (single event)

Info from Play Console:

Oukitel C16 Pro <-- This was actually my own device
Android 9 (SDK 28)
1003003.aab

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 0 >>> org.tosl.warnappcompanion <<<

backtrace:
  #00  pc 000000000009d46c  /system/lib64/libcrypto.so (SHA256_Update+36)
  #00  pc 000000000009088c  /system/lib64/libcrypto.so (HMAC_Final+124)
  #00  pc 000000000001a2c0  /system/lib64/libjavacrypto.so (NativeCrypto_HMAC_Final(_JNIEnv*, _jclass*, _jobject*)+256)
  #00  pc 000000000001423c  /system/framework/arm64/boot-conscrypt.oat (offset 0x14000) (com.android.org.conscrypt.NativeCrypto.ASN1_seq_pack_X509 [DEDUPED]+172)
  #00  pc 000000000002aa0c  /system/framework/arm64/boot-conscrypt.oat (offset 0x14000) (com.android.org.conscrypt.OpenSSLMac.engineDoFinal+76)
  #00  pc 00000000003043f4  /system/framework/arm64/boot.oat (offset 0x11d000) (javax.crypto.Mac.doFinal+724)
  #00  pc 0000000000220858  /data/app/org.tosl.warnappcompanion-xebuKxxerjceLIWGFnuHww==/oat/arm64/base.odex (offset 0xcb000) (org.tosl.coronawarncompanion.crypto.KeyDerivation.hkdfSha256+312)
  #00  pc 0000000000225cc0  /data/app/org.tosl.warnappcompanion-xebuKxxerjceLIWGFnuHww==/oat/arm64/base.odex (offset 0xcb000) (org.tosl.coronawarncompanion.matcher.Crypto.deriveRpiKey+192)
  #00  pc 00000000002264e8  /data/app/org.tosl.warnappcompanion-xebuKxxerjceLIWGFnuHww==/oat/arm64/base.odex (offset 0xcb000) (org.tosl.coronawarncompanion.matcher.Matcher.findMatches+1080)
  #00  pc 000000000021eef8  /data/app/org.tosl.warnappcompanion-xebuKxxerjceLIWGFnuHww==/oat/arm64/base.odex (offset 0xcb000) (org.tosl.coronawarncompanion.MainActivity$BackgroundMatching.run+536)
  #00  pc 0000000000b1e4ec  /system/framework/arm64/boot-framework.oat (offset 0x3f9000) (android.os.Handler.dispatchMessage+76)
  #00  pc 0000000000b21650  /system/framework/arm64/boot-framework.oat (offset 0x3f9000) (android.os.Looper.loop+1264)
  #00  pc 0000000000b204f0  /system/framework/arm64/boot-framework.oat (offset 0x3f9000) (android.os.HandlerThread.run+544)
  #00  pc 000000000055cd88  /system/lib64/libart.so (art_quick_invoke_stub+584)
  #00  pc 00000000000cf740  /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200)
  #00  pc 00000000004633b8  /system/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
  #00  pc 0000000000464480  /system/lib64/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+424)
  #00  pc 000000000048f7f0  /system/lib64/libart.so (art::Thread::CreateCallback(void*)+1120)
  #00  pc 0000000000083114  /system/lib64/libc.so (__pthread_start(void*)+36)
  #00  pc 00000000000233bc  /system/lib64/libc.so (__start_thread+68)

Possibility to export Rolling Proximity IDs

It would be great to be able to export the rolling proximity ID. Espacially in the case you need to install a new ROM it would be great to still be warned in the case of a contact. Maybe it would be possible to export it and later import it in Ramble.

No match found in app, but match found with diagnosis-keys project

I run into an interesting problem, was feeding RPIs over BLE like in https://github.com/corona-warn-app/cwa-backlog/issues/23#issuecomment-678644207 (which was successful twice), but third time neither CWA (was running fork with en-i13n this time), nor Warn-App-Companion detected any exposure. When I copied DB from the device and run with https://github.com/mh-/diagnosis-keys against Diagnosis Keys from 2020-08-20 bundle, it found a match with exactly those RPIs I was transmitting:

FOUND MATCH!
RPI Validity: 2020-08-19 19:40:00 CEST - 2020-08-19 19:50:00 CEST (Interval number: 2663098, RPI: 29ea528037d3d5a055480ae9d2f540ba)
2020-08-19 10:46:33 CEST Attenuation: 36dB (RSSI: -24dBm, AEM: da5e2e3f, Metadata: 400c0000)
(...)
FOUND MATCH!
RPI Validity: 2020-08-19 19:50:00 CEST - 2020-08-19 20:00:00 CEST (Interval number: 2663099, RPI: 581b3a5e24d7428928a72758a52584a6)
2020-08-19 10:53:49 CEST Attenuation: 46dB (RSSI: -34dBm, AEM: 95db0c41, Metadata: 400c0000)
(...)
FOUND MATCH!
RPI Validity: 2020-08-19 20:00:00 CEST - 2020-08-19 20:10:00 CEST (Interval number: 2663100, RPI: eec6a89090b6426f2bcf41aa47ec5001)
2020-08-19 11:00:44 CEST Attenuation: 41dB (RSSI: -29dBm, AEM: 8e8eccf3, Metadata: 400c0000)
(...)
FOUND MATCH!
RPI Validity: 2020-08-19 20:10:00 CEST - 2020-08-19 20:20:00 CEST (Interval number: 2663101, RPI: 668fa0ccb0a2d26cc20312b25febd7c5)
2020-08-19 11:10:22 CEST Attenuation: 46dB (RSSI: -34dBm, AEM: 91a4d8fa, Metadata: 400c0000)
(...)
FOUND MATCH!
RPI Validity: 2020-08-19 20:20:00 CEST - 2020-08-19 20:30:00 CEST (Interval number: 2663102, RPI: 5ac750ade60359c8fabcbd72c4bc7385)
2020-08-22 11:22:08 CEST Attenuation: 49dB (RSSI: -37dBm, AEM: ba2f3a0a, Metadata: 400c0000)

Attached dump of internal GMS database, will look into it but have no idea at the moment what may be going on here

debug-nomatch.tar.gz

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.