Compare commits

...

116 Commits

Author SHA1 Message Date
akwizgran
fb7d4076ab Use magic wake lock tag for Huawei devices. 2018-09-07 13:32:22 +01:00
akwizgran
a3083a6e73 Use a constant to enable the control condition. 2018-08-30 18:10:18 +01:00
akwizgran
c1fcae7de3 Add more logging for sleep and alarms. 2018-08-30 17:43:22 +01:00
Shannon Stork
35c1f50650 Added sleep and power status logging 2018-08-08 21:27:50 -04:00
Shannon Stork
f2c50b500e Acquire wakelock when alarm goes off 2018-08-07 10:38:57 -04:00
akwizgran
0776ab85b6 Use elapsed real time, postDelayed() instead of sleep(). 2018-07-26 10:51:00 +01:00
Shannon Stork
f77bde4edf Attempt to acquire wakelock when alarm goes off (DOES NOT WORK) 2018-07-25 19:20:54 -04:00
Torsten Grote
afa9b6193a Merge branch 'remove-reference-manager' into 'master'
Removed unused ReferenceManager

See merge request briar/briar!856
2018-07-16 15:44:29 +00:00
akwizgran
1bcedea34a Removed unused ReferenceManager. 2018-07-16 16:21:25 +01:00
akwizgran
0f16ac57f3 Merge branch '1267-tor-bridges' into 'master'
Tor Bridge Support

See merge request briar/briar!847
2018-07-05 14:22:39 +00:00
Torsten Grote
7ecac1867e Address review comments for Tor bridge support 2018-07-05 11:14:11 -03:00
Torsten Grote
331c09a02a Load bridges from file res/raw/bridges 2018-07-04 16:21:49 -03:00
Torsten Grote
7e05a49bda Add Android integration tests that checks if included bridges work
This also changes the way bridges are used.
Instead of using the torrc config file,
bridges are now activated via Tor's control port.
2018-07-04 15:17:28 -03:00
Torsten Grote
eac1f9ed74 MVP for bridge support 2018-07-04 15:17:28 -03:00
Torsten Grote
d16aa9e2a4 Merge branch '1334-disable-resource-shrinking' into 'master'
Disable resource shrinking for release builds

Closes #1334

See merge request briar/briar!854
2018-07-04 17:20:40 +00:00
akwizgran
cc72d146a0 Disable resource shrinking for release builds. 2018-07-04 17:02:39 +01:00
Torsten Grote
bff23480d7 Trigger external pipeline to check release builds 2018-07-04 12:47:22 -03:00
akwizgran
e435578f3b Merge branch 'gui-minor-padding-corrections' into 'master'
Fixed padding in rss_feed_import, list_item_crash, power_view

See merge request briar/briar!831
2018-07-04 13:21:18 +00:00
jRustig
33b9539a72 correction of crash report alignment 2018-07-04 14:59:34 +02:00
akwizgran
a114d4db15 Bump version numbers for 1.0.11 release. 2018-07-04 08:45:03 +01:00
akwizgran
73b7879c64 Update translations. 2018-07-04 08:44:00 +01:00
akwizgran
e622a518ac Merge branch 'fix_npe_keyfrag' into 'master'
Fix a possible null reference bug

See merge request briar/briar!853
2018-07-03 17:20:59 +00:00
goapunk
28ea3d014a Fix a possible null reference bug 2018-07-03 11:33:13 +02:00
akwizgran
457d77ca51 Bump version numbers for 1.0.10 release. 2018-07-02 14:06:49 +01:00
akwizgran
581c67f5fd Update translations. 2018-07-02 14:04:51 +01:00
Torsten Grote
1dcb9aa1d0 Merge branch '1329-auth-cookie' into 'master'
Delete old auth cookie before starting Tor

Closes #1329

See merge request briar/briar!852
2018-06-29 15:38:23 +00:00
akwizgran
d97dcfff30 Merge branch 'no_screenfilter_warning_splash' into 'master'
Don't show screenfilter warning in SplashScreenActivity

See merge request briar/briar!832
2018-06-29 14:41:09 +00:00
akwizgran
e166d9dd15 Merge branch '1327-setup-crash' into 'master'
Ensure that pressing back after setup will always return the user to home

Closes #1327

See merge request briar/briar!849
2018-06-29 14:40:43 +00:00
akwizgran
2e002d132c Delete old auth cookie before starting Tor. 2018-06-29 15:28:50 +01:00
Torsten Grote
da629df630 Ensure that pressing back after setup will always return the user to home 2018-06-26 11:42:54 -03:00
Nico Alt
135372ebee Use consistent language for forum posts
Fixes #888.
2018-06-26 14:25:24 +02:00
akwizgran
b083122d72 Merge branch '47-sign-in-reminder' into 'master'
Remind the user to sign in

See merge request briar/briar!841
2018-06-22 14:49:09 +00:00
akwizgran
649433a506 Merge branch '1032-message-icon' into 'master'
Use message icon rather than mail icon for private messages

Closes #1032

See merge request briar/briar!846
2018-06-22 14:18:20 +00:00
Torsten Grote
eff3a69734 Disable sign-in reminder with a feature flag in release builds 2018-06-22 10:59:27 -03:00
Torsten Grote
62de50af76 Remind the user to sign in only when an account has been created 2018-06-22 10:46:27 -03:00
Torsten Grote
1f9def8418 Minimal Sign-in reminder 2018-06-22 10:46:27 -03:00
Torsten Grote
1e80069980 Merge branch 'feature-flags' into 'master'
Add feature flag for dark theme

See merge request briar/briar!843
2018-06-22 13:43:56 +00:00
Torsten Grote
bfde71c151 Merge branch '1307-readable-log' into 'master'
Display log file in a reader-friendly way

Closes #1307

See merge request briar/briar!845
2018-06-22 13:42:40 +00:00
akwizgran
bce0a3150b Use message icon rather than mail icon. 2018-06-22 13:48:52 +01:00
akwizgran
ee59b9b3ad Unescape newlines when showing log. 2018-06-22 11:17:54 +01:00
akwizgran
55918a88b2 Merge branch '1251-dark-theme-fixes' into 'master'
Dark Theme Fixes

See merge request briar/briar!844
2018-06-21 12:49:15 +00:00
Torsten Grote
679c1c3719 Fix RSS feed delete button and disabled button text 2018-06-21 09:40:55 -03:00
akwizgran
21f33d6cfb Add feature flag for dark theme. 2018-06-21 13:28:32 +01:00
akwizgran
912b1b5b1d Merge branch 'factor_out_keyagreement_ui-theme' into 'master'
Factor out keyagreement ui theme

See merge request briar/briar!835
2018-06-21 11:38:49 +00:00
goapunk
0ad20037ae Pass String instead of the TextView 2018-06-20 18:36:39 +02:00
akwizgran
62d893f7b1 Merge branch 'android-gradle-3.1.3' into 'master'
Upgrade Android Gradle Plugin to 3.1.3

See merge request briar/briar!842
2018-06-20 15:45:55 +00:00
goapunk
497213e56d add KeyAgreementEventListener interface 2018-06-20 15:44:42 +02:00
akwizgran
f5c0d0b2cb Merge branch '1251-dark-theme' into 'master'
Implement Dark Theme (DayNight with automatic option)

See merge request akwizgran/briar!818
2018-06-20 13:43:04 +00:00
goapunk
f4131d6f32 address reviews 2018-06-20 15:32:51 +02:00
goapunk
06deba4bd4 Create a dedicated qrCodeView 2018-06-20 15:32:42 +02:00
goapunk
26643e491b Add some abstraction to the keyagreement ui 2018-06-20 15:32:23 +02:00
Torsten Grote
6ef4130f8f Upgrade Android Gradle Plugin to 3.1.3 2018-06-19 17:36:35 -03:00
Torsten Grote
ba5b2f601b Applying night mode to DevReportActivity 2018-06-19 14:19:15 -03:00
Torsten Grote
5be672f0e7 Remove unused resources 2018-06-19 13:30:01 -03:00
Torsten Grote
fa525564c0 Hide Theme Settings in release builds for now 2018-06-19 13:30:01 -03:00
Torsten Grote
dee0ca238b Address first round of review comments 2018-06-19 13:30:00 -03:00
Torsten Grote
3c6b43b2bd Implement Dark Theme (DayNight with automatic option)
This is just a first rough implementation.
A real UI designer should look over this.
2018-06-19 13:29:13 -03:00
Administrator
dcacae0729 Merge branch 'language_improvements' into 'master'
Language improvements

See merge request akwizgran/briar!829
2018-06-19 16:27:50 +00:00
akwizgran
aefc5c519e Merge branch '1297-opendb-gui' into 'master'
Resolve ""Decrypting database" label needs some padding"

Closes #1297

See merge request akwizgran/briar!830
2018-06-18 14:19:34 +00:00
akwizgran
7225adf24e Merge branch 'fix_translation_verification' into 'master'
Use project path for translation verification

See merge request akwizgran/briar!840
2018-06-18 14:18:49 +00:00
goapunk
30228cf025 Use project path for translation verification 2018-06-17 16:11:22 +02:00
Torsten Grote
99e2b7eaab Merge branch 'exception-logging-method' into 'master'
Add utility method for logging exceptions

See merge request akwizgran/briar!838
2018-06-16 13:38:25 +00:00
Torsten Grote
2f7d5b869c Merge branch 'hide-ui-if-not-in-foreground' into 'master'
Don't hide UI on low memory if we're in the foreground

See merge request akwizgran/briar!839
2018-06-15 20:19:05 +00:00
akwizgran
d5d6db6723 Add utility method for logging exceptions. 2018-06-15 17:09:34 +01:00
Torsten Grote
b026031d66 Merge branch 'fine-logging' into 'master'
Replace logging boilerplate with a static method

See merge request akwizgran/briar!837
2018-06-15 15:30:31 +00:00
akwizgran
abe14f19e6 Replace boilerplate with static method. 2018-06-15 16:17:08 +01:00
Torsten Grote
fa17549972 Merge branch 'fine-logging' into 'master'
Move logging of time measurements to FINE level

See merge request akwizgran/briar!836
2018-06-15 15:00:25 +00:00
akwizgran
0d2a91289f Don't calculate duration unless needed. 2018-06-15 15:52:05 +01:00
Torsten Grote
2e22318b27 Merge branch '1291-huawei-protected-apps' into 'master'
Don't show Huawei protected apps button on API 24+

Closes #1291

See merge request akwizgran/briar!823
2018-06-15 14:35:46 +00:00
akwizgran
11f0bd1ae0 Merge branch '1288-placeholder-texts' into 'master'
Use placeholder text for text fields and add show password button

Closes #1096 and #1288

See merge request akwizgran/briar!834
2018-06-15 14:22:21 +00:00
akwizgran
e2d636e274 Don't hide UI on low memory if we're in the foreground. 2018-06-15 15:14:13 +01:00
Torsten Grote
f41b76c567 Shorten password hints 2018-06-15 11:13:38 -03:00
akwizgran
08931e64cb Use System.nanoTime() for timing measurements. 2018-06-15 13:01:48 +01:00
akwizgran
ccee1febbc Move timing measurements down to FINE log level. 2018-06-15 13:01:48 +01:00
Torsten Grote
7bfc1c3579 Add buttons to show passwords wherever they can be entered
Closes #1096
2018-06-14 15:40:17 -03:00
Torsten Grote
2dc94a95ed Use placeholder texts for text fields
Closes #1288
2018-06-14 15:36:08 -03:00
Torsten Grote
a47a1cf442 Merge branch '1316-make-introduction-string' into 'master'
Use separate strings for introduction menu item and button

Closes #1316

See merge request akwizgran/briar!833
2018-06-13 20:16:34 +00:00
akwizgran
4adb27a1ce Use separate strings for introduction menu item and button. 2018-06-13 16:50:24 +01:00
akwizgran
841c31ebce Bump version numbers for 1.0.9 release. 2018-06-13 15:38:49 +01:00
akwizgran
d6810cf87f Update translations. 2018-06-13 15:36:57 +01:00
goapunk
7a2df3d6cb simplify 2018-06-13 13:38:15 +02:00
goapunk
0c65ff4783 remove the unncessary synchronization from reset 2018-06-13 12:42:03 +02:00
goapunk
8b10b7ed23 Don't show screenfilter warning here 2018-06-13 12:36:43 +02:00
goapunk
9743255ce9 immutable version 2018-06-13 12:32:38 +02:00
jRustig
8c64734ff1 Fixed padding in rss_feed_import, list_item_crash, power_view 2018-06-13 10:34:10 +02:00
jRustig
c845dfc7f4 Fix padding in activity_open_database
Closes #1297
2018-06-13 10:00:42 +02:00
akwizgran
a8a02b9e45 Merge branch '992-refresh-wake-lock' into 'master'
Renew the wake lock every minute to avoid wake lock killers

See merge request akwizgran/briar!827
2018-06-12 16:59:32 +00:00
akwizgran
6703be1c32 Add thread safety, null safety annotations. 2018-06-12 17:50:58 +01:00
goapunk
fc99dedb53 Detect if system language changed 2018-06-12 16:23:32 +02:00
goapunk
65a461a0db Reset Localizer on account deletion 2018-06-12 12:15:47 +02:00
akwizgran
a44a68f231 Bump version numbers for 1.0.8 release. 2018-06-08 13:00:39 +01:00
akwizgran
4ac6baa23d Update translations. 2018-06-08 13:00:39 +01:00
akwizgran
4cde50b7f5 Merge branch '1293-cookie-file-polling' into 'master'
Poll for creation of Tor auth cookie file

Closes #1293

See merge request akwizgran/briar!828
2018-06-08 11:30:12 +00:00
akwizgran
da40eca80b Merge branch '1160-language-setting' into 'master'
Add language setting

Closes #1160 and #1222

See merge request akwizgran/briar!679
2018-06-08 11:20:39 +00:00
akwizgran
fa267d38af Filter out RTL languages on API < 17. 2018-06-08 13:07:30 +02:00
akwizgran
ba20fbeb47 Poll for creation of cookie file. 2018-06-08 10:40:38 +01:00
akwizgran
196df05df9 Bump version numbers for 1.0.7 release. 2018-06-07 12:12:39 +01:00
akwizgran
44f07c8d76 Merge branch '1293-tor-cookie-file' into 'master'
Watch for creation rather than updating of Tor cookie file

See merge request akwizgran/briar!825
2018-06-07 11:07:30 +00:00
akwizgran
d7f39af6d1 Reduce wake lock refresh interval to 1 minute. 2018-06-07 10:46:16 +01:00
akwizgran
4f732c3997 Acquire wake lock with a timeout. 2018-06-07 10:46:16 +01:00
akwizgran
74cfd313ab Code cleanup. 2018-06-07 10:46:16 +01:00
akwizgran
c089a099f0 Refactor wake lock to use existing ScheduledExecutorService. 2018-06-07 10:46:15 +01:00
goapunk
98a0d09899 Renew the wake lock every 30min
Signed-off-by: goapunk <noobie@goapunks.net>
2018-06-07 10:46:15 +01:00
goapunk
18c4195115 fix region and title 2018-06-07 11:42:31 +02:00
akwizgran
d4a9c41cf5 Watch for creation rather than updating of Tor cookie file.
Tor writes to a temporary file and then renames it over the old
file, if any, so CLOSE_WRITE never occurs. The old code was
working in most cases because it received IGNORED when the old
file was unlinked and didn't check the event type.
2018-06-07 09:19:52 +01:00
goapunk
8bc28f99c1 Improvements:
* Force LTR by prefixing language names with the LRM marker
* Add Polish
* Cleanup
2018-06-07 10:19:17 +02:00
goapunk
1834146ad0 fix hebrew 2018-06-07 10:19:17 +02:00
akwizgran
624e03a2c9 Merge branch 'default-build-timestamp' into 'master'
Add default build timestamp in case Git command fails

See merge request akwizgran/briar!826
2018-06-07 08:15:08 +00:00
akwizgran
a24e0482c9 Add default build timestamp in case Git command fails. 2018-06-06 14:34:40 +01:00
goapunk
695b543ba9 fix review 2018-06-06 11:16:24 +02:00
goapunk
75e910e1d9 Add a language setting 2018-06-06 11:16:21 +02:00
Torsten Grote
8fc8333451 Merge branch '1294-log-stack-traces' into 'master'
Log exception stacktraces

Closes #1294

See merge request akwizgran/briar!824
2018-06-03 02:28:17 +00:00
akwizgran
c2154c81f4 Log exception stacktraces. 2018-06-01 16:43:10 +01:00
akwizgran
5cd5fc7e43 Bump version numbers for 1.0.6 release. 2018-06-01 10:20:32 +01:00
akwizgran
abd9db70b9 Update translations, add Polish translation. 2018-06-01 10:18:42 +01:00
akwizgran
5e679e7a10 Don't show Huawei protected apps button on API 24+. 2018-05-31 09:48:38 +01:00
290 changed files with 4403 additions and 2133 deletions

View File

@@ -21,11 +21,7 @@ test:
test_reproducible: test_reproducible:
image: briar/reproducer:latest
script: script:
- cd /opt/briar-reproducer - "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
- ./reproduce.py ${CI_COMMIT_REF_NAME}
only: only:
- tags - tags

View File

@@ -8,9 +8,11 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 26 targetSdkVersion 26
versionCode 10005 versionCode 10011
versionName "1.0.5" versionName "1.0.11"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
compileOptions { compileOptions {
@@ -31,36 +33,42 @@ dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')
androidTestImplementation project(path: ':bramble-core', configuration: 'testOutput')
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
} }
dependencyVerification { dependencyVerification {
verify = [ verify = [
'com.android.tools.analytics-library:protos:26.1.2:protos-26.1.2.jar:52672a0b42b572a06aecc3535d5068eb46c0e15d129b9f1085d3c16a1da5cdbb', 'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.2:shared-26.1.2.jar:5c7e0eda18c6f87feeb83628c707e8aaa3298b41fb72e38efe31ad1675f9e8e9', 'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.2:tracker-26.1.2.jar:06f97aa0adf44ffb06f8681c6a79d9be153a08f61d21eddc42b8d3db96df4282', 'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.2:apksig-3.1.2.jar:40696a4559124d1d57873d208857eee059d48859239d569c7d18374ac644a8be', 'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.2:builder-model-3.1.2.jar:d49bfa2a135c9562b6ca7aa4342036cfa1582c7074c2d1d93d1dae8b3a134e17', 'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.2:builder-test-api-3.1.2.jar:dfe2a50b740d41b11189101062434d4283d18647e89a492ad51710c719363e9f', 'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.2:builder-3.1.2.jar:b60f825a42e2efe8433619fbc759f3d9effecab718279048d36881188ceb1d14', 'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.2:gradle-api-3.1.2.jar:e58bcc5b893e4583ab0f5c8ef89c4dbcce202b405a9d7fcc116d21e5357d4893', 'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.2:manifest-merger-26.1.2.jar:9c61c27ea5266573107b954acf1216d398f4d7e7ae6fad6409d6b2b767eb091c', 'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.2:ddmlib-26.1.2.jar:18a2a5fbef36882f07d03c2b9e59eba05cf8248177bf5cbff736e4b582804c44', 'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.2:intellij-core-26.1.2.jar:37c5acf279f1ae3e85b1a5be3c9f15f43bde7b08f978eefefffb9c4035760c52', 'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.2:kotlin-compiler-26.1.2.jar:152df0bee7580326c77316b669a9d96e3b09efb1d45f545dce4147271b0b8944', 'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.2:uast-26.1.2.jar:02d39582206d3f5fc0a6cb18bfd9e8b9f9c1acb805ec6dac08b4e3a56849d279', 'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.2:layoutlib-api-26.1.2.jar:20220039fcc7d799f928153beff862e704457c0f55ab44258f3745ebeb662b4f', 'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.2:lint-api-26.1.2.jar:e1d5b62b870a7c566e9877a6b96b27784a4d713f8caa07fdcb4705d47a40a1d9', 'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.2:lint-checks-26.1.2.jar:211e2afd58504372385d71b1e5be982c2b5121ab6fee1c04ddabeb75a8729e07', 'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.2:lint-gradle-api-26.1.2.jar:71284f2a8b03c3e55c94511c9eb36f8184fbb85324325fc6b78abf5183f03d90', 'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.2:lint-gradle-26.1.2.jar:855f0c82b7fc690df1b7319c0774f7517f7f8f5dd4eee1f6077dcf50e07c6240', 'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.2:lint-kotlin-26.1.2.jar:1e591f70bcbbc11569720a9bbcca2bc1f3d4f789f01f40f642848d920643d484', 'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.2:lint-26.1.2.jar:93736c62e9f1976998c2b4aa716aea0734cdb162d05502f4af7292654aedb182', 'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.2:annotations-26.1.2.jar:72773dcaf5c4ccca828e3c8467f1b78a8a00b3cc5f8ad1aab88fcf9379928018', 'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.2:common-26.1.2.jar:ea4320f0c17dcbc4491896bb705c4d25ec08bd62ef02ab0579fe154e75e788e6', 'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.2:dvlib-26.1.2.jar:1187aa4fb666595c96c4deb6bc0e0f4b7e396bde9f6243330b49a232946130ea', 'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.2:repository-26.1.2.jar:8b86e512ad6d32bd76989451eefe2b271f5efce6d4d65ecb173afaf14606e01a', 'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.2:sdk-common-26.1.2.jar:23584720a60a21cdcb5b1ec10269e3013789d6805d153cc696c39ec7ce251896', 'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.2:sdklib-26.1.2.jar:d3870fafc59ab8efa70d3f9649f40ee299c8ec5b58377b06e8853d7272a5bf4e', 'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed', 'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32', 'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3', 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',

View File

@@ -0,0 +1,23 @@
package org.briarproject.bramble;
import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.plugin.tor.BridgeTest;
import org.briarproject.bramble.system.SystemModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
BrambleAndroidModule.class,
PluginModule.class, // needed for BackoffFactory
EventModule.class,
SystemModule.class,
})
public interface IntegrationTestComponent {
void inject(BridgeTest init);
}

View File

@@ -0,0 +1,126 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.support.test.runner.AndroidJUnit4;
import org.briarproject.bramble.DaggerIntegrationTestComponent;
import org.briarproject.bramble.IntegrationTestComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.net.SocketFactory;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class BridgeTest extends BrambleTestCase {
private final static long TIMEOUT = SECONDS.toMillis(23);
private final static Logger LOG =
Logger.getLogger(BridgeTest.class.getSimpleName());
@Inject
EventBus eventBus;
@Inject
BackoffFactory backoffFactory;
@Inject
Clock clock;
private final Context appContext = getTargetContext();
private final CircumventionProvider circumventionProvider;
private final List<String> bridges;
private TorPluginFactory factory;
private volatile int currentBridge = 0;
public BridgeTest() {
super();
circumventionProvider = new CircumventionProvider() {
@Override
public boolean isTorProbablyBlocked(String countryCode) {
return true;
}
@Override
public boolean doBridgesWork(String countryCode) {
return true;
}
@Override
public List<String> getBridges() {
return singletonList(bridges.get(currentBridge));
}
};
bridges = new CircumventionProviderImpl(appContext).getBridges();
}
@Before
public void setUp() {
IntegrationTestComponent component =
DaggerIntegrationTestComponent.builder().build();
component.inject(this);
Executor ioExecutor = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
LocationUtils locationUtils = () -> "US";
SocketFactory torSocketFactory = SocketFactory.getDefault();
factory = new TorPluginFactory(ioExecutor, scheduler, appContext,
locationUtils, eventBus, torSocketFactory,
backoffFactory, circumventionProvider, clock);
}
@Test
public void testBridges() throws Exception {
assertTrue(bridges.size() > 0);
for (int i = 0; i < bridges.size(); i++) {
testBridge(i);
}
}
private void testBridge(int bridge) throws Exception {
DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack());
assertNotNull(duplexPlugin);
TorPlugin plugin = (TorPlugin) duplexPlugin;
currentBridge = bridge;
LOG.warning("Testing " + bridges.get(currentBridge));
try {
plugin.start();
long start = clock.currentTimeMillis();
while (clock.currentTimeMillis() - start < TIMEOUT) {
if (plugin.isRunning()) return;
clock.sleep(500);
}
if (!plugin.isRunning()) {
fail("Could not connect to Tor within timeout.");
}
} finally {
plugin.stop();
}
}
}

View File

@@ -0,0 +1,54 @@
package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
@NotNullByDefault
public class TorPluginCallBack implements DuplexPluginCallback {
@Override
public void incomingConnectionCreated(DuplexTransportConnection d) {
}
@Override
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {
}
@Override
public Settings getSettings() {
return new Settings();
}
@Override
public TransportProperties getLocalProperties() {
return new TransportProperties();
}
@Override
public void mergeSettings(Settings s) {
}
@Override
public void mergeLocalProperties(TransportProperties p) {
}
@Override
public void transportEnabled() {
}
@Override
public void transportDisabled() {
}
}

View File

@@ -1,11 +1,25 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import android.app.Application;
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.plugin.tor.CircumventionProviderImpl;
import org.briarproject.bramble.system.AndroidSystemModule; import org.briarproject.bramble.system.AndroidSystemModule;
import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides;
@Module(includes = { @Module(includes = {
AndroidSystemModule.class AndroidSystemModule.class
}) })
public class BrambleAndroidModule { public class BrambleAndroidModule {
@Provides
@Singleton
CircumventionProvider provideCircumventionProvider(Application app) {
return new CircumventionProviderImpl(app.getApplicationContext());
}
} }

View File

@@ -0,0 +1,8 @@
package org.briarproject.bramble;
public interface PowerTestingConstants {
int WAKE_LOCK_DURATION = 5000;
int ALARM_DELAY = 5000;
boolean USE_TOR_WAKE_LOCK = true;
}

View File

@@ -38,6 +38,7 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF; import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -145,7 +146,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
try { try {
if (ss != null) ss.close(); if (ss != null) ss.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -185,7 +186,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
try { try {
if (c != null) c.close(); if (c != null) c.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -0,0 +1,30 @@
package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import java.util.List;
public interface CircumventionProvider {
/**
* Countries where Tor is blocked, i.e. vanilla Tor connection won't work.
*
* See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
* and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
*/
String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"};
/**
* Countries where vanilla bridge connection are likely to work.
* Should be a subset of {@link #BLOCKED}.
*/
String[] BRIDGES = { "EG", "BY", "TR", "SY", "VE" };
boolean isTorProbablyBlocked(String countryCode);
boolean doBridgesWork(String countryCode);
@IoExecutor
List<String> getBridges();
}

View File

@@ -0,0 +1,68 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.content.res.Resources;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
public class CircumventionProviderImpl implements CircumventionProvider {
private final static String BRIDGE_FILE_NAME = "bridges";
private final Context ctx;
@Nullable
private volatile List<String> bridges = null;
@Inject
public CircumventionProviderImpl(Context ctx) {
this.ctx = ctx;
}
private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<>(Arrays.asList(BLOCKED));
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(Arrays.asList(BRIDGES));
@Override
public boolean isTorProbablyBlocked(String countryCode) {
return BLOCKED_IN_COUNTRIES.contains(countryCode);
}
@Override
public boolean doBridgesWork(String countryCode) {
return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode);
}
@Override
@IoExecutor
public List<String> getBridges() {
if (this.bridges != null) return this.bridges;
Resources res = ctx.getResources();
int resId = res.getIdentifier(BRIDGE_FILE_NAME, "raw",
ctx.getPackageName());
InputStream is = ctx.getResources().openRawResource(resId);
Scanner scanner = new Scanner(is);
List<String> bridges = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (!line.startsWith("#")) bridges.add(line);
}
scanner.close();
this.bridges = bridges;
return bridges;
}
}

View File

@@ -1,18 +0,0 @@
package org.briarproject.bramble.plugin.tor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
class TorNetworkMetadata {
// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
// and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
// TODO: get a more complete list
private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<>(Arrays.asList("CN", "IR", "SY", "ZZ"));
static boolean isTorProbablyBlocked(String countryCode) {
return BLOCKED_IN_COUNTRIES.contains(countryCode);
}
}

View File

@@ -10,7 +10,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.FileObserver;
import android.os.PowerManager; import android.os.PowerManager;
import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.EventHandler;
@@ -34,8 +33,10 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent; import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.RenewableWakeLock;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable; import java.io.Closeable;
@@ -49,13 +50,14 @@ import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@@ -78,12 +80,12 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK; import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY; import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.bramble.PowerTestingConstants.USE_TOR_WAKE_LOCK;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.ID; import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
@@ -92,6 +94,7 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION; import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion; import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -102,8 +105,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR" "CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
}; };
private static final String OWNER = "__OwningControllerProcess"; private static final String OWNER = "__OwningControllerProcess";
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds private static final int COOKIE_TIMEOUT_MS = 3000;
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
// This tag may prevent Huawei's power manager from killing us
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName()); Logger.getLogger(TorPlugin.class.getName());
@@ -112,14 +118,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Context appContext; private final Context appContext;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final Clock clock;
private final Backoff backoff; private final Backoff backoff;
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
private final String architecture; private final String architecture;
private final CircumventionProvider circumventionProvider;
private final int maxLatency, maxIdleTime, socketTimeout; private final int maxLatency, maxIdleTime, socketTimeout;
private final ConnectionStatus connectionStatus; private final ConnectionStatus connectionStatus;
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
private final PowerManager.WakeLock wakeLock; private final RenewableWakeLock wakeLock;
private final AtomicReference<Future<?>> connectivityCheck = private final AtomicReference<Future<?>> connectivityCheck =
new AtomicReference<>(); new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -132,17 +140,19 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler, TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, LocationUtils locationUtils, Context appContext, LocationUtils locationUtils,
SocketFactory torSocketFactory, Backoff backoff, SocketFactory torSocketFactory, Clock clock, Backoff backoff,
DuplexPluginCallback callback, String architecture, DuplexPluginCallback callback, String architecture,
int maxLatency, int maxIdleTime) { CircumventionProvider circumventionProvider, int maxLatency, int maxIdleTime) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler; this.scheduler = scheduler;
this.appContext = appContext; this.appContext = appContext;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.clock = clock;
this.backoff = backoff; this.backoff = backoff;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
this.circumventionProvider = circumventionProvider;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
if (maxIdleTime > Integer.MAX_VALUE / 2) if (maxIdleTime > Integer.MAX_VALUE / 2)
@@ -155,14 +165,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
configFile = new File(torDirectory, "torrc"); configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done"); doneFile = new File(torDirectory, "done");
cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
Object o = appContext.getSystemService(POWER_SERVICE);
PowerManager pm = (PowerManager) o;
// This tag will prevent Huawei's powermanager from killing us.
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
wakeLock.setReferenceCounted(false);
// Don't execute more than one connection status check at a time // Don't execute more than one connection status check at a time
connectionStatusExecutor = new PoliteExecutor("TorPlugin", connectionStatusExecutor = new PoliteExecutor("TorPlugin",
ioExecutor, 1); ioExecutor, 1);
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
} }
@Override @Override
@@ -185,18 +194,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (used.getAndSet(true)) throw new IllegalStateException(); if (used.getAndSet(true)) throw new IllegalStateException();
// Install or update the assets if necessary // Install or update the assets if necessary
if (!assetsAreUpToDate()) installAssets(); if (!assetsAreUpToDate()) installAssets();
LOG.info("Starting Tor"); if (cookieFile.exists() && !cookieFile.delete())
// Watch for the auth cookie file being updated LOG.warning("Old auth cookie not deleted");
try {
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
} catch (IOException e) {
throw new PluginException(e);
}
CountDownLatch latch = new CountDownLatch(1);
FileObserver obs = new WriteObserver(cookieFile, latch);
obs.startWatching();
// Start a new Tor process // Start a new Tor process
LOG.info("Starting Tor");
String torPath = torFile.getAbsolutePath(); String torPath = torFile.getAbsolutePath();
String configPath = configFile.getAbsolutePath(); String configPath = configFile.getAbsolutePath();
String pid = String.valueOf(android.os.Process.myPid()); String pid = String.valueOf(android.os.Process.myPid());
@@ -235,11 +236,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
throw new PluginException(); throw new PluginException();
} }
// Wait for the auth cookie file to be created/updated // Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) { long start = clock.currentTimeMillis();
LOG.warning("Auth cookie not created"); while (cookieFile.length() < 32) {
if (LOG.isLoggable(INFO)) listFiles(torDirectory); if (clock.currentTimeMillis() - start > COOKIE_TIMEOUT_MS) {
throw new PluginException(); LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException();
}
Thread.sleep(COOKIE_POLLING_INTERVAL_MS);
} }
LOG.info("Auth cookie created");
} catch (InterruptedException e) { } catch (InterruptedException e) {
LOG.warning("Interrupted while starting Tor"); LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@@ -347,7 +353,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try { try {
if (c != null) c.close(); if (c != null) c.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -355,7 +361,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try { try {
if (s != null) s.close(); if (s != null) s.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -364,7 +370,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
File[] children = f.listFiles(); File[] children = f.listFiles();
if (children != null) for (File child : children) listFiles(child); if (children != null) for (File child : children) listFiles(child);
} else { } else {
LOG.info(f.getAbsolutePath()); LOG.info(f.getAbsolutePath() + " " + f.length());
} }
} }
@@ -397,7 +403,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
ss = new ServerSocket(); ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", port)); ss.bind(new InetSocketAddress("127.0.0.1", port));
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
tryToClose(ss); tryToClose(ss);
return; return;
} }
@@ -423,7 +429,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try { try {
if (ss != null) ss.close(); if (ss != null) ss.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} finally { } finally {
callback.transportDisabled(); callback.transportDisabled();
} }
@@ -442,7 +448,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
response = controlConnection.addOnion(portLines); response = controlConnection.addOnion(portLines);
else response = controlConnection.addOnion(privKey, portLines); else response = controlConnection.addOnion(privKey, portLines);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return; return;
} }
if (!response.containsKey(HS_ADDRESS)) { if (!response.containsKey(HS_ADDRESS)) {
@@ -488,12 +494,23 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void enableNetwork(boolean enable) throws IOException { private void enableNetwork(boolean enable) throws IOException {
if (!running) return; if (!running) return;
if (enable) wakeLock.acquire(); if (enable && USE_TOR_WAKE_LOCK) wakeLock.acquire();
connectionStatus.enableNetwork(enable); connectionStatus.enableNetwork(enable);
controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
if (!enable) { if (!enable) {
callback.transportDisabled(); callback.transportDisabled();
wakeLock.release(); if (USE_TOR_WAKE_LOCK) wakeLock.release();
}
}
private void enableBridges(boolean enable) throws IOException {
if (enable) {
Collection<String> conf = new ArrayList<>();
conf.add("UseBridges 1");
conf.addAll(circumventionProvider.getBridges());
controlConnection.setConf(conf);
} else {
controlConnection.setConf("UseBridges", "0");
} }
} }
@@ -510,10 +527,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
controlConnection.shutdownTor("TERM"); controlConnection.shutdownTor("TERM");
controlSocket.close(); controlSocket.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
wakeLock.release(); if (USE_TOR_WAKE_LOCK) wakeLock.release();
} }
@Override @Override
@@ -641,22 +658,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info("Descriptor uploaded"); LOG.info("Descriptor uploaded");
} }
private static class WriteObserver extends FileObserver {
private final CountDownLatch latch;
private WriteObserver(File file, CountDownLatch latch) {
super(file.getAbsolutePath(), CLOSE_WRITE);
this.latch = latch;
}
@Override
public void onEvent(int event, @Nullable String path) {
stopWatching();
latch.countDown();
}
}
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) { if (e instanceof SettingsUpdatedEvent) {
@@ -677,8 +678,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
boolean online = net != null && net.isConnected(); boolean online = net != null && net.isConnected();
boolean wifi = online && net.getType() == TYPE_WIFI; boolean wifi = online && net.getType() == TYPE_WIFI;
String country = locationUtils.getCurrentCountry(); String country = locationUtils.getCurrentCountry();
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked( boolean blocked =
country); circumventionProvider.isTorProbablyBlocked(country);
Settings s = callback.getSettings(); Settings s = callback.getSettings();
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS); int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
@@ -692,19 +693,26 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (!online) { if (!online) {
LOG.info("Disabling network, device is offline"); LOG.info("Disabling network, device is offline");
enableNetwork(false); enableNetwork(false);
} else if (blocked) {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER } else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) { || (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting"); LOG.info("Disabling network due to data setting");
enableNetwork(false); enableNetwork(false);
} else if (blocked) {
if (circumventionProvider.doBridgesWork(country)) {
LOG.info("Enabling network, using bridges");
enableBridges(true);
enableNetwork(true);
} else {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
}
} else { } else {
LOG.info("Enabling network"); LOG.info("Enabling network");
enableBridges(false);
enableNetwork(true); enableNetwork(true);
} }
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -12,6 +12,7 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
@@ -42,11 +43,15 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final EventBus eventBus; private final EventBus eventBus;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
private final CircumventionProvider circumventionProvider;
private final Clock clock;
public TorPluginFactory(Executor ioExecutor, public TorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext, ScheduledExecutorService scheduler, Context appContext,
LocationUtils locationUtils, EventBus eventBus, LocationUtils locationUtils, EventBus eventBus,
SocketFactory torSocketFactory, BackoffFactory backoffFactory) { SocketFactory torSocketFactory, BackoffFactory backoffFactory,
CircumventionProvider circumventionProvider,
Clock clock) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler; this.scheduler = scheduler;
this.appContext = appContext; this.appContext = appContext;
@@ -54,6 +59,8 @@ public class TorPluginFactory implements DuplexPluginFactory {
this.eventBus = eventBus; this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
this.circumventionProvider = circumventionProvider;
this.clock = clock;
} }
@Override @Override
@@ -90,8 +97,8 @@ public class TorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext, TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext,
locationUtils, torSocketFactory, backoff, callback, locationUtils, torSocketFactory, clock, backoff, callback,
architecture, MAX_LATENCY, MAX_IDLE_TIME); architecture, circumventionProvider, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -0,0 +1,100 @@
package org.briarproject.bramble.util;
import android.os.PowerManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
@ThreadSafe
@NotNullByDefault
public class RenewableWakeLock {
private static final Logger LOG =
Logger.getLogger(RenewableWakeLock.class.getName());
/**
* Automatically release the lock this many milliseconds after it's due
* to have been replaced and released.
*/
private static final int SAFETY_MARGIN_MS = 10_000;
private final PowerManager powerManager;
private final ScheduledExecutorService scheduler;
private final int levelAndFlags;
private final String tag;
private final long durationMs;
private final Runnable renewTask;
private final Object lock = new Object();
@Nullable
private PowerManager.WakeLock wakeLock; // Locking: lock
@Nullable
private ScheduledFuture future; // Locking: lock
public RenewableWakeLock(PowerManager powerManager,
ScheduledExecutorService scheduler, int levelAndFlags, String tag,
long duration, TimeUnit timeUnit) {
this.powerManager = powerManager;
this.scheduler = scheduler;
this.levelAndFlags = levelAndFlags;
this.tag = tag;
durationMs = MILLISECONDS.convert(duration, timeUnit);
renewTask = this::renew;
}
public void acquire() {
if (LOG.isLoggable(INFO)) LOG.info("Acquiring wake lock " + tag);
synchronized (lock) {
if (wakeLock != null) {
LOG.info("Already acquired");
return;
}
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
}
}
private void renew() {
if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag);
synchronized (lock) {
if (wakeLock == null) {
LOG.info("Already released");
return;
}
PowerManager.WakeLock oldWakeLock = wakeLock;
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
oldWakeLock.release();
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
}
}
public void release() {
if (LOG.isLoggable(INFO)) LOG.info("Releasing wake lock " + tag);
synchronized (lock) {
if (wakeLock == null) {
LOG.info("Already released");
return;
}
if (future == null) throw new AssertionError();
future.cancel(false);
future = null;
wakeLock.release();
wakeLock = null;
}
}
}

View File

@@ -0,0 +1,5 @@
Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
#Bridge 128.105.214.161:8081 1E326AAFB3FCB515015250D8FCCC8E37F91A153B

View File

@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Annotation for injecting the executor for long-running IO tasks. Also used * Annotation for injecting the executor for long-running IO tasks. Also used
* for annotating methods that should run on the UI executor. * for annotating methods that should run on the IO executor.
* <p> * <p>
* The contract of this executor is that tasks may be run concurrently, and * The contract of this executor is that tasks may be run concurrently, and
* submitting a task will never block. Tasks may run indefinitely. Tasks * submitting a task will never block. Tasks may run indefinitely. Tasks

View File

@@ -0,0 +1,36 @@
package org.briarproject.bramble.util;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
public class LogUtils {
private static final int NANOS_PER_MILLI = 1000 * 1000;
/**
* Returns the elapsed time in milliseconds since some arbitrary
* starting time. This is only useful for measuring elapsed time.
*/
public static long now() {
return System.nanoTime() / NANOS_PER_MILLI;
}
/**
* Logs the duration of a task.
* @param logger the logger to use
* @param task a description of the task
* @param start the start time of the task, as returned by {@link #now()}
*/
public static void logDuration(Logger logger, String task, long start) {
if (logger.isLoggable(FINE)) {
long duration = now() - start;
logger.fine(task + " took " + duration + " ms");
}
}
public static void logException(Logger logger, Level level, Throwable t) {
if (logger.isLoggable(level)) logger.log(level, t.toString(), t);
}
}

View File

@@ -5,12 +5,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINE;
import static org.briarproject.bramble.util.LogUtils.now;
/** /**
* An {@link Executor} that delegates its tasks to another {@link Executor} * An {@link Executor} that delegates its tasks to another {@link Executor}
@@ -20,8 +20,6 @@ import static java.util.logging.Level.FINE;
@NotNullByDefault @NotNullByDefault
public class PoliteExecutor implements Executor { public class PoliteExecutor implements Executor {
private static final Level LOG_LEVEL = FINE;
private final Object lock = new Object(); private final Object lock = new Object();
@GuardedBy("lock") @GuardedBy("lock")
private final Queue<Runnable> queue = new LinkedList<>(); private final Queue<Runnable> queue = new LinkedList<>();
@@ -49,11 +47,11 @@ public class PoliteExecutor implements Executor {
@Override @Override
public void execute(Runnable r) { public void execute(Runnable r) {
long submitted = System.currentTimeMillis(); long submitted = now();
Runnable wrapped = () -> { Runnable wrapped = () -> {
if (log.isLoggable(LOG_LEVEL)) { if (log.isLoggable(FINE)) {
long queued = System.currentTimeMillis() - submitted; long queued = now() - submitted;
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); log.fine("Queue time " + queued + " ms");
} }
try { try {
r.run(); r.run();

View File

@@ -6,16 +6,14 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINE;
import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault @NotNullByDefault
public class TimeLoggingExecutor extends ThreadPoolExecutor { public class TimeLoggingExecutor extends ThreadPoolExecutor {
private static final Level LOG_LEVEL = FINE;
private final Logger log; private final Logger log;
public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize, public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize,
@@ -29,15 +27,15 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
@Override @Override
public void execute(Runnable r) { public void execute(Runnable r) {
if (log.isLoggable(LOG_LEVEL)) { if (log.isLoggable(FINE)) {
long submitted = System.currentTimeMillis(); long submitted = now();
super.execute(() -> { super.execute(() -> {
long started = System.currentTimeMillis(); long started = now();
long queued = started - submitted; long queued = started - submitted;
log.log(LOG_LEVEL, "Queue time " + queued + " ms"); log.fine("Queue time " + queued + " ms");
r.run(); r.run();
long executing = System.currentTimeMillis() - started; long executing = now() - started;
log.log(LOG_LEVEL, "Execution time " + executing + " ms"); log.fine("Execution time " + executing + " ms");
}); });
} else { } else {
super.execute(r); super.execute(r);

View File

@@ -46,6 +46,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO; import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -122,7 +123,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
in = conn.getReader().getInputStream(); in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream(); out = conn.getWriter().getOutputStream();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
tryToClose(conn); tryToClose(conn);
return; return;
@@ -133,7 +134,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
try { try {
localProperties = transportPropertyManager.getLocalProperties(); localProperties = transportPropertyManager.getLocalProperties();
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
tryToClose(conn); tryToClose(conn);
return; return;
@@ -194,7 +195,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
LOG.info("End of stream"); LOG.info("End of stream");
} }
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
tryToClose(conn); tryToClose(conn);
return; return;
@@ -222,11 +223,11 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
LOG.info("Pseudonym exchange succeeded"); LOG.info("Pseudonym exchange succeeded");
listener.contactExchangeSucceeded(remoteInfo.author); listener.contactExchangeSucceeded(remoteInfo.author);
} catch (ContactExistsException e) { } catch (ContactExistsException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
tryToClose(conn); tryToClose(conn);
listener.duplicateContact(remoteInfo.author); listener.duplicateContact(remoteInfo.author);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
tryToClose(conn); tryToClose(conn);
listener.contactExchangeFailed(); listener.contactExchangeFailed();
} }
@@ -307,7 +308,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
conn.getReader().dispose(true, true); conn.getReader().dispose(true, true);
conn.getWriter().dispose(true); conn.getWriter().dispose(true);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -32,6 +32,8 @@ import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault @NotNullByDefault
class CryptoComponentImpl implements CryptoComponent { class CryptoComponentImpl implements CryptoComponent {
@@ -127,16 +129,14 @@ class CryptoComponentImpl implements CryptoComponent {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (!(pub instanceof Curve25519PublicKey)) if (!(pub instanceof Curve25519PublicKey))
throw new IllegalArgumentException(); throw new IllegalArgumentException();
long now = System.currentTimeMillis(); long start = now();
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(), byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
priv.getEncoded()); priv.getEncoded());
// If the shared secret is all zeroes, the public key is invalid // If the shared secret is all zeroes, the public key is invalid
byte allZero = 0; byte allZero = 0;
for (byte b : secret) allZero |= b; for (byte b : secret) allZero |= b;
if (allZero == 0) throw new GeneralSecurityException(); if (allZero == 0) throw new GeneralSecurityException();
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Deriving shared secret", start);
if (LOG.isLoggable(INFO))
LOG.info("Deriving shared secret took " + duration + " ms");
return secret; return secret;
} }

View File

@@ -10,6 +10,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
class ScryptKdf implements PasswordBasedKdf { class ScryptKdf implements PasswordBasedKdf {
@@ -50,13 +52,11 @@ class ScryptKdf implements PasswordBasedKdf {
@Override @Override
public SecretKey deriveKey(String password, byte[] salt, int cost) { public SecretKey deriveKey(String password, byte[] salt, int cost) {
long start = System.currentTimeMillis(); long start = now();
byte[] passwordBytes = StringUtils.toUtf8(password); byte[] passwordBytes = StringUtils.toUtf8(password);
SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost, SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost,
BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH)); BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH));
long duration = System.currentTimeMillis() - start; logDuration(LOG, "Deriving key from password", start);
if (LOG.isLoggable(INFO))
LOG.info("Deriving key from password took " + duration + " ms");
return k; return k;
} }
} }

View File

@@ -16,7 +16,8 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static java.util.logging.Level.INFO; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
/** /**
* A key parser that uses the encoding defined in "SEC 1: Elliptic Curve * A key parser that uses the encoding defined in "SEC 1: Elliptic Curve
@@ -48,7 +49,7 @@ class Sec1KeyParser implements KeyParser {
throws GeneralSecurityException { throws GeneralSecurityException {
// The validation procedure comes from SEC 1, section 3.2.2.1. Note // The validation procedure comes from SEC 1, section 3.2.2.1. Note
// that SEC 1 parameter names are used below, not RFC 5639 names // that SEC 1 parameter names are used below, not RFC 5639 names
long now = System.currentTimeMillis(); long start = now();
if (encodedKey.length != publicKeyBytes) if (encodedKey.length != publicKeyBytes)
throw new GeneralSecurityException(); throw new GeneralSecurityException();
// The first byte must be 0x04 // The first byte must be 0x04
@@ -80,16 +81,14 @@ class Sec1KeyParser implements KeyParser {
// Construct a public key from the point (x, y) and the params // Construct a public key from the point (x, y) and the params
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params); ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
PublicKey p = new Sec1PublicKey(k); PublicKey p = new Sec1PublicKey(k);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Parsing public key", start);
if (LOG.isLoggable(INFO))
LOG.info("Parsing public key took " + duration + " ms");
return p; return p;
} }
@Override @Override
public PrivateKey parsePrivateKey(byte[] encodedKey) public PrivateKey parsePrivateKey(byte[] encodedKey)
throws GeneralSecurityException { throws GeneralSecurityException {
long now = System.currentTimeMillis(); long start = now();
if (encodedKey.length != privateKeyBytes) if (encodedKey.length != privateKeyBytes)
throw new GeneralSecurityException(); throw new GeneralSecurityException();
BigInteger d = new BigInteger(1, encodedKey); // Positive signum BigInteger d = new BigInteger(1, encodedKey); // Positive signum
@@ -99,9 +98,7 @@ class Sec1KeyParser implements KeyParser {
// Construct a private key from the private value and the params // Construct a private key from the private value and the params
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params); ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
PrivateKey p = new Sec1PrivateKey(k, keyBits); PrivateKey p = new Sec1PrivateKey(k, keyBits);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Parsing private key", start);
if (LOG.isLoggable(INFO))
LOG.info("Parsing private key took " + duration + " ms");
return p; return p;
} }
} }

View File

@@ -68,13 +68,15 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED; import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN; import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES; import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -108,7 +110,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
try { try {
close(); close();
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
return reopened; return reopened;
@@ -125,13 +127,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
// Don't allow reentrant locking // Don't allow reentrant locking
if (lock.getReadHoldCount() > 0) throw new IllegalStateException(); if (lock.getReadHoldCount() > 0) throw new IllegalStateException();
if (lock.getWriteHoldCount() > 0) throw new IllegalStateException(); if (lock.getWriteHoldCount() > 0) throw new IllegalStateException();
long start = System.currentTimeMillis(); long start = now();
if (readOnly) lock.readLock().lock(); if (readOnly) {
else lock.writeLock().lock(); lock.readLock().lock();
if (LOG.isLoggable(FINE)) { logDuration(LOG, "Waiting for read lock", start);
long duration = System.currentTimeMillis() - start; } else {
if (readOnly) LOG.fine("Waited " + duration + " ms for read lock"); lock.writeLock().lock();
else LOG.fine("Waited " + duration + " ms for write lock"); logDuration(LOG, "Waiting for write lock", start);
} }
try { try {
return new Transaction(db.startTransaction(), readOnly); return new Transaction(db.startTransaction(), readOnly);

View File

@@ -66,6 +66,7 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE; import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY; import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry; import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
import static org.briarproject.bramble.util.LogUtils.logException;
/** /**
* A generic database implementation that can be used with any JDBC-compatible * A generic database implementation that can be used with any JDBC-compatible
@@ -404,7 +405,7 @@ abstract class JdbcDatabase implements Database<Connection> {
try { try {
if (rs != null) rs.close(); if (rs != null) rs.close();
} catch (SQLException e) { } catch (SQLException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -412,7 +413,7 @@ abstract class JdbcDatabase implements Database<Connection> {
try { try {
if (s != null) s.close(); if (s != null) s.close();
} catch (SQLException e) { } catch (SQLException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -509,12 +510,11 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} catch (SQLException e) { } catch (SQLException e) {
// Try to close the connection // Try to close the connection
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
try { try {
txn.close(); txn.close();
} catch (SQLException e1) { } catch (SQLException e1) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e1);
LOG.log(WARNING, e1.toString(), e1);
} }
// Whatever happens, allow the database to close // Whatever happens, allow the database to close
connectionsLock.lock(); connectionsLock.lock();

View File

@@ -10,6 +10,7 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
class Migration38_39 implements Migration<Connection> { class Migration38_39 implements Migration<Connection> {
@@ -48,7 +49,7 @@ class Migration38_39 implements Migration<Connection> {
try { try {
if (s != null) s.close(); if (s != null) s.close();
} catch (SQLException e) { } catch (SQLException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -31,6 +31,7 @@ import javax.annotation.Nullable;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class KeyAgreementConnector { class KeyAgreementConnector {
@@ -134,7 +135,7 @@ class KeyAgreementConnector {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return null; return null;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} finally { } finally {
stopListening(); stopListening();

View File

@@ -28,6 +28,7 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -120,13 +121,11 @@ class KeyAgreementTaskImpl extends Thread implements KeyAgreementTask,
// Broadcast result to caller // Broadcast result to caller
eventBus.broadcast(new KeyAgreementFinishedEvent(result)); eventBus.broadcast(new KeyAgreementFinishedEvent(result));
} catch (AbortException e) { } catch (AbortException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
// Notify caller that the protocol was aborted // Notify caller that the protocol was aborted
eventBus.broadcast(new KeyAgreementAbortedEvent(e.receivedAbort)); eventBus.broadcast(new KeyAgreementAbortedEvent(e.receivedAbort));
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
// Notify caller that the connection failed // Notify caller that the connection failed
eventBus.broadcast(new KeyAgreementFailedEvent()); eventBus.broadcast(new KeyAgreementFailedEvent());
} }

View File

@@ -20,6 +20,7 @@ import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PR
import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT; import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM; import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY; import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY;
import static org.briarproject.bramble.util.LogUtils.logException;
/** /**
* Handles the sending and receiving of BQP records. * Handles the sending and receiving of BQP records.
@@ -72,7 +73,7 @@ class KeyAgreementTransport {
try { try {
writeRecord(ABORT, new byte[0]); writeRecord(ABORT, new byte[0]);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
exception = true; exception = true;
} }
tryToClose(exception); tryToClose(exception);
@@ -83,7 +84,7 @@ class KeyAgreementTransport {
kac.getConnection().getReader().dispose(exception, true); kac.getConnection().getReader().dispose(exception, true);
kac.getConnection().getWriter().dispose(exception); kac.getConnection().getWriter().dispose(exception);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -30,6 +30,7 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
@@ -43,6 +44,9 @@ import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResul
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ERROR; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ERROR;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -101,24 +105,20 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
} }
private LocalAuthor createLocalAuthor(String nickname) { private LocalAuthor createLocalAuthor(String nickname) {
long now = System.currentTimeMillis(); long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair(); KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded(); byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded(); byte[] privateKey = keyPair.getPrivate().getEncoded();
LocalAuthor localAuthor = authorFactory LocalAuthor localAuthor = authorFactory
.createLocalAuthor(nickname, publicKey, privateKey); .createLocalAuthor(nickname, publicKey, privateKey);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Creating local author", start);
if (LOG.isLoggable(INFO))
LOG.info("Creating local author took " + duration + " ms");
return localAuthor; return localAuthor;
} }
private void registerLocalAuthor(LocalAuthor author) throws DbException { private void registerLocalAuthor(LocalAuthor author) throws DbException {
long now = System.currentTimeMillis(); long start = now();
identityManager.registerLocalAuthor(author); identityManager.registerLocalAuthor(author);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Registering local author", start);
if (LOG.isLoggable(INFO))
LOG.info("Registering local author took " + duration + " ms");
} }
@Override @Override
@@ -129,15 +129,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
} }
try { try {
LOG.info("Starting services"); LOG.info("Starting services");
long start = System.currentTimeMillis(); long start = now();
boolean reopened = db.open(this); boolean reopened = db.open(this);
long duration = System.currentTimeMillis() - start; if (reopened) logDuration(LOG, "Reopening database", start);
if (LOG.isLoggable(INFO)) { else logDuration(LOG, "Creating database", start);
if (reopened)
LOG.info("Reopening database took " + duration + " ms");
else LOG.info("Creating database took " + duration + " ms");
}
if (nickname != null) { if (nickname != null) {
registerLocalAuthor(createLocalAuthor(nickname)); registerLocalAuthor(createLocalAuthor(nickname));
@@ -150,13 +146,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
for (Client c : clients) { for (Client c : clients) {
start = System.currentTimeMillis(); start = now();
c.createLocalState(txn); c.createLocalState(txn);
duration = System.currentTimeMillis() - start; if (LOG.isLoggable(FINE)) {
if (LOG.isLoggable(INFO)) { logDuration(LOG, "Starting client "
LOG.info("Starting client " + c.getClass().getSimpleName(), start);
+ c.getClass().getSimpleName()
+ " took " + duration + " ms");
} }
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -164,12 +158,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
for (Service s : services) { for (Service s : services) {
start = System.currentTimeMillis(); start = now();
s.startService(); s.startService();
duration = System.currentTimeMillis() - start; if (LOG.isLoggable(FINE)) {
if (LOG.isLoggable(INFO)) { logDuration(LOG, "Starting service "
LOG.info("Starting service " + s.getClass().getSimpleName() + s.getClass().getSimpleName(), start);
+ " took " + duration + " ms");
} }
} }
@@ -178,16 +171,16 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
eventBus.broadcast(new LifecycleEvent(RUNNING)); eventBus.broadcast(new LifecycleEvent(RUNNING));
return SUCCESS; return SUCCESS;
} catch (DataTooOldException e) { } catch (DataTooOldException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return DATA_TOO_OLD_ERROR; return DATA_TOO_OLD_ERROR;
} catch (DataTooNewException e) { } catch (DataTooNewException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return DATA_TOO_NEW_ERROR; return DATA_TOO_NEW_ERROR;
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return DB_ERROR; return DB_ERROR;
} catch (ServiceException e) { } catch (ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return SERVICE_ERROR; return SERVICE_ERROR;
} finally { } finally {
startStopSemaphore.release(); startStopSemaphore.release();
@@ -213,29 +206,26 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
state = STOPPING; state = STOPPING;
eventBus.broadcast(new LifecycleEvent(STOPPING)); eventBus.broadcast(new LifecycleEvent(STOPPING));
for (Service s : services) { for (Service s : services) {
long start = System.currentTimeMillis(); long start = now();
s.stopService(); s.stopService();
long duration = System.currentTimeMillis() - start; if (LOG.isLoggable(FINE)) {
if (LOG.isLoggable(INFO)) { logDuration(LOG, "Stopping service "
LOG.info("Stopping service " + s.getClass().getSimpleName() + s.getClass().getSimpleName(), start);
+ " took " + duration + " ms");
} }
} }
for (ExecutorService e : executors) { for (ExecutorService e : executors) {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(FINE)) {
LOG.info("Stopping executor " LOG.fine("Stopping executor "
+ e.getClass().getSimpleName()); + e.getClass().getSimpleName());
} }
e.shutdownNow(); e.shutdownNow();
} }
long start = System.currentTimeMillis(); long start = now();
db.close(); db.close();
long duration = System.currentTimeMillis() - start; logDuration(LOG, "Closing database", start);
if (LOG.isLoggable(INFO))
LOG.info("Closing database took " + duration + " ms");
shutdownLatch.countDown(); shutdownLatch.countDown();
} catch (DbException | ServiceException e) { } catch (DbException | ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} finally { } finally {
startStopSemaphore.release(); startStopSemaphore.release();
} }

View File

@@ -27,6 +27,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.util.LogUtils.logException;
class ConnectionManagerImpl implements ConnectionManager { class ConnectionManagerImpl implements ConnectionManager {
@@ -135,7 +136,7 @@ class ConnectionManagerImpl implements ConnectionManager {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, false); disposeReader(true, false);
return; return;
} }
@@ -151,7 +152,7 @@ class ConnectionManagerImpl implements ConnectionManager {
createIncomingSession(ctx, reader).run(); createIncomingSession(ctx, reader).run();
disposeReader(false, true); disposeReader(false, true);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId, connectionRegistry.unregisterConnection(contactId, transportId,
@@ -163,7 +164,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
reader.dispose(exception, recognised); reader.dispose(exception, recognised);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }
@@ -188,7 +189,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
ctx = keyManager.getStreamContext(contactId, transportId); ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
return; return;
} }
@@ -204,7 +205,7 @@ class ConnectionManagerImpl implements ConnectionManager {
createSimplexOutgoingSession(ctx, writer).run(); createSimplexOutgoingSession(ctx, writer).run();
disposeWriter(false); disposeWriter(false);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId, connectionRegistry.unregisterConnection(contactId, transportId,
@@ -216,7 +217,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
writer.dispose(exception); writer.dispose(exception);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }
@@ -246,7 +247,7 @@ class ConnectionManagerImpl implements ConnectionManager {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, false); disposeReader(true, false);
return; return;
} }
@@ -265,7 +266,7 @@ class ConnectionManagerImpl implements ConnectionManager {
incomingSession.run(); incomingSession.run();
disposeReader(false, true); disposeReader(false, true);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId, connectionRegistry.unregisterConnection(contactId, transportId,
@@ -279,7 +280,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
ctx = keyManager.getStreamContext(contactId, transportId); ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
return; return;
} }
@@ -294,7 +295,7 @@ class ConnectionManagerImpl implements ConnectionManager {
outgoingSession.run(); outgoingSession.run();
disposeWriter(false); disposeWriter(false);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
} }
} }
@@ -305,7 +306,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
reader.dispose(exception, recognised); reader.dispose(exception, recognised);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -317,7 +318,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
writer.dispose(exception); writer.dispose(exception);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }
@@ -347,7 +348,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
ctx = keyManager.getStreamContext(contactId, transportId); ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
return; return;
} }
@@ -364,7 +365,7 @@ class ConnectionManagerImpl implements ConnectionManager {
outgoingSession.run(); outgoingSession.run();
disposeWriter(false); disposeWriter(false);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeWriter(true); disposeWriter(true);
} }
} }
@@ -376,7 +377,7 @@ class ConnectionManagerImpl implements ConnectionManager {
byte[] tag = readTag(reader); byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag); ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) { } catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, false); disposeReader(true, false);
return; return;
} }
@@ -400,7 +401,7 @@ class ConnectionManagerImpl implements ConnectionManager {
incomingSession.run(); incomingSession.run();
disposeReader(false, true); disposeReader(false, true);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
disposeReader(true, true); disposeReader(true, true);
} finally { } finally {
connectionRegistry.unregisterConnection(contactId, transportId, connectionRegistry.unregisterConnection(contactId, transportId,
@@ -414,7 +415,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
reader.dispose(exception, recognised); reader.dispose(exception, recognised);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -426,7 +427,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try { try {
writer.dispose(exception); writer.dispose(exception);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -49,8 +49,12 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -205,17 +209,16 @@ class PluginManagerImpl implements PluginManager, Service {
@Override @Override
public void run() { public void run() {
try { try {
long start = System.currentTimeMillis(); long start = now();
plugin.start(); plugin.start();
long duration = System.currentTimeMillis() - start; if (LOG.isLoggable(FINE)) {
if (LOG.isLoggable(INFO)) { logDuration(LOG, "Starting plugin " + plugin.getId(),
LOG.info("Starting plugin " + plugin.getId() + " took " + start);
duration + " ms");
} }
} catch (PluginException e) { } catch (PluginException e) {
if (LOG.isLoggable(WARNING)) { if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not start"); LOG.warning("Plugin " + plugin.getId() + " did not start");
LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} finally { } finally {
startLatch.countDown(); startLatch.countDown();
@@ -243,12 +246,11 @@ class PluginManagerImpl implements PluginManager, Service {
// Wait for the plugin to finish starting // Wait for the plugin to finish starting
startLatch.await(); startLatch.await();
// Stop the plugin // Stop the plugin
long start = System.currentTimeMillis(); long start = now();
plugin.stop(); plugin.stop();
long duration = System.currentTimeMillis() - start; if (LOG.isLoggable(FINE)) {
if (LOG.isLoggable(INFO)) { logDuration(LOG, "Stopping plugin " + plugin.getId(),
LOG.info("Stopping plugin " + plugin.getId() start);
+ " took " + duration + " ms");
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for plugin to stop"); LOG.warning("Interrupted while waiting for plugin to stop");
@@ -256,7 +258,7 @@ class PluginManagerImpl implements PluginManager, Service {
} catch (PluginException e) { } catch (PluginException e) {
if (LOG.isLoggable(WARNING)) { if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not stop"); LOG.warning("Plugin " + plugin.getId() + " did not stop");
LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} finally { } finally {
stopLatch.countDown(); stopLatch.countDown();
@@ -278,7 +280,7 @@ class PluginManagerImpl implements PluginManager, Service {
try { try {
return settingsManager.getSettings(id.getString()); return settingsManager.getSettings(id.getString());
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return new Settings(); return new Settings();
} }
} }
@@ -288,7 +290,7 @@ class PluginManagerImpl implements PluginManager, Service {
try { try {
return transportPropertyManager.getLocalProperties(id); return transportPropertyManager.getLocalProperties(id);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return new TransportProperties(); return new TransportProperties();
} }
} }
@@ -298,7 +300,7 @@ class PluginManagerImpl implements PluginManager, Service {
try { try {
settingsManager.mergeSettings(s, id.getString()); settingsManager.mergeSettings(s, id.getString());
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -307,7 +309,7 @@ class PluginManagerImpl implements PluginManager, Service {
try { try {
transportPropertyManager.mergeLocalProperties(id, p); transportPropertyManager.mergeLocalProperties(id, p);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -41,6 +41,7 @@ import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -134,7 +135,7 @@ class Poller implements EventListener {
if (w != null) if (w != null)
connectionManager.manageOutgoingConnection(c, t, w); connectionManager.manageOutgoingConnection(c, t, w);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -150,7 +151,7 @@ class Poller implements EventListener {
if (d != null) if (d != null)
connectionManager.manageOutgoingConnection(c, t, d); connectionManager.manageOutgoingConnection(c, t, d);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -211,7 +212,7 @@ class Poller implements EventListener {
remote.keySet().removeAll(connected); remote.keySet().removeAll(connected);
if (!remote.isEmpty()) p.poll(remote); if (!remote.isEmpty()) p.poll(remote);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -13,6 +13,7 @@ import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
@ThreadSafe @ThreadSafe
@@ -92,7 +93,7 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
conn.getWriter().dispose(false); conn.getWriter().dispose(false);
conn.getReader().dispose(false, false); conn.getReader().dispose(false, false);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -43,6 +43,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENA
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES; import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -169,7 +170,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
try { try {
ss = openServerSocket(contactConnectionsUuid); ss = openServerSocket(contactConnectionsUuid);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return; return;
} }
if (!isRunning() || !shouldAllowContactConnections()) { if (!isRunning() || !shouldAllowContactConnections()) {
@@ -336,7 +337,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
try { try {
ss = openServerSocket(uuid); ss = openServerSocket(uuid);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} }
if (!isRunning()) { if (!isRunning()) {

View File

@@ -15,6 +15,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH; import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@NotNullByDefault @NotNullByDefault
@@ -51,7 +52,7 @@ abstract class FilePlugin implements SimplexPlugin {
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);
return new FileTransportReader(file, in, this); return new FileTransportReader(file, in, this);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} }
} }
@@ -70,7 +71,7 @@ abstract class FilePlugin implements SimplexPlugin {
FileOutputStream out = new FileOutputStream(file); FileOutputStream out = new FileOutputStream(file);
return new FileTransportWriter(file, out, this); return new FileTransportWriter(file, out, this);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} }
} }

View File

@@ -9,6 +9,7 @@ import java.io.InputStream;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class FileTransportReader implements TransportConnectionReader { class FileTransportReader implements TransportConnectionReader {
@@ -36,7 +37,7 @@ class FileTransportReader implements TransportConnectionReader {
try { try {
in.close(); in.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
plugin.readerFinished(file, exception, recognised); plugin.readerFinished(file, exception, recognised);
} }

View File

@@ -9,6 +9,7 @@ import java.io.OutputStream;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class FileTransportWriter implements TransportConnectionWriter { class FileTransportWriter implements TransportConnectionWriter {
@@ -46,7 +47,7 @@ class FileTransportWriter implements TransportConnectionWriter {
try { try {
out.close(); out.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
plugin.writerFinished(file, exception); plugin.writerFinished(file, exception);
} }

View File

@@ -35,6 +35,7 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS; import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS; import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED; import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
@NotNullByDefault @NotNullByDefault
@@ -295,7 +296,7 @@ class LanTcpPlugin extends TcpPlugin {
try { try {
ss.close(); ss.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -17,6 +17,7 @@ import javax.xml.parsers.ParserConfigurationException;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
@ThreadSafe @ThreadSafe
@@ -59,7 +60,7 @@ class PortMapperImpl implements PortMapper {
if (externalString != null) if (externalString != null)
external = InetAddress.getByName(externalString); external = InetAddress.getByName(externalString);
} catch (IOException | SAXException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
return new MappingResult(internal, external, port, succeeded); return new MappingResult(internal, external, port, succeeded);
} }
@@ -76,7 +77,7 @@ class PortMapperImpl implements PortMapper {
try { try {
d.discover(); d.discover();
} catch (IOException | SAXException | ParserConfigurationException e) { } catch (IOException | SAXException | ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
gateway = d.getValidGateway(); gateway = d.getValidGateway();
} }
@@ -87,7 +88,7 @@ class PortMapperImpl implements PortMapper {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Deleted mapping for port " + port); LOG.info("Deleted mapping for port " + port);
} catch (IOException | SAXException e) { } catch (IOException | SAXException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -37,6 +37,7 @@ import javax.annotation.Nullable;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -152,7 +153,7 @@ abstract class TcpPlugin implements DuplexPlugin {
try { try {
if (ss != null) ss.close(); if (ss != null) ss.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} finally { } finally {
callback.transportDisabled(); callback.transportDisabled();
} }
@@ -306,7 +307,7 @@ abstract class TcpPlugin implements DuplexPlugin {
try { try {
ifaces = Collections.list(NetworkInterface.getNetworkInterfaces()); ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) { } catch (SocketException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return Collections.emptyList(); return Collections.emptyList();
} }
List<InetAddress> addrs = new ArrayList<>(); List<InetAddress> addrs = new ArrayList<>();

View File

@@ -16,6 +16,7 @@ import java.util.logging.Logger;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -78,7 +79,7 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
running = false; running = false;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
running = false; running = false;
} }
}); });

View File

@@ -32,6 +32,7 @@ import javax.inject.Inject;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
@@ -132,7 +133,7 @@ class DevReporterImpl implements DevReporter, EventListener {
try { try {
if (c != null) c.close(); if (c != null) c.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -140,7 +141,7 @@ class DevReporterImpl implements DevReporter, EventListener {
try { try {
if (s != null) s.close(); if (s != null) s.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -42,6 +42,7 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.util.LogUtils.logException;
/** /**
* An outgoing {@link SyncSession} suitable for duplex transports. The session * An outgoing {@link SyncSession} suitable for duplex transports. The session
@@ -240,7 +241,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated ack: " + (a != null)); LOG.info("Generated ack: " + (a != null));
if (a != null) writerTasks.add(new WriteAck(a)); if (a != null) writerTasks.add(new WriteAck(a));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -287,7 +288,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated batch: " + (b != null)); LOG.info("Generated batch: " + (b != null));
if (b != null) writerTasks.add(new WriteBatch(b)); if (b != null) writerTasks.add(new WriteBatch(b));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -334,7 +335,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated offer: " + (o != null)); LOG.info("Generated offer: " + (o != null));
if (o != null) writerTasks.add(new WriteOffer(o)); if (o != null) writerTasks.add(new WriteOffer(o));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -379,7 +380,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated request: " + (r != null)); LOG.info("Generated request: " + (r != null));
if (r != null) writerTasks.add(new WriteRequest(r)); if (r != null) writerTasks.add(new WriteRequest(r));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }

View File

@@ -28,6 +28,7 @@ import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
import static org.briarproject.bramble.util.LogUtils.logException;
/** /**
* An incoming {@link SyncSession}. * An incoming {@link SyncSession}.
@@ -127,7 +128,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -153,7 +154,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -179,7 +180,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -205,7 +206,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }

View File

@@ -32,6 +32,7 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.util.LogUtils.logException;
/** /**
* An outgoing {@link SyncSession} suitable for simplex transports. The session * An outgoing {@link SyncSession} suitable for simplex transports. The session
@@ -139,7 +140,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
if (a == null) decrementOutstandingQueries(); if (a == null) decrementOutstandingQueries();
else writerTasks.add(new WriteAck(a)); else writerTasks.add(new WriteAck(a));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }
@@ -184,7 +185,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
if (b == null) decrementOutstandingQueries(); if (b == null) decrementOutstandingQueries();
else writerTasks.add(new WriteBatch(b)); else writerTasks.add(new WriteBatch(b));
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
interrupt(); interrupt();
} }
} }

View File

@@ -40,6 +40,7 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED; import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID; import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING; import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -110,7 +111,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
validateNextMessageAsync(unvalidated); validateNextMessageAsync(unvalidated);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -144,7 +145,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
LOG.info("Group removed before validation"); LOG.info("Group removed before validation");
validateNextMessageAsync(unvalidated); validateNextMessageAsync(unvalidated);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -165,7 +166,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
deliverNextPendingMessageAsync(pending); deliverNextPendingMessageAsync(pending);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -231,7 +232,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
LOG.info("Group removed before delivery"); LOG.info("Group removed before delivery");
deliverNextPendingMessageAsync(pending); deliverNextPendingMessageAsync(pending);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -252,8 +253,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
storeMessageContextAsync(m, g.getClientId(), storeMessageContextAsync(m, g.getClientId(),
g.getMajorVersion(), context); g.getMajorVersion(), context);
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
if (LOG.isLoggable(INFO)) logException(LOG, INFO, e);
LOG.log(INFO, e.toString(), e);
Queue<MessageId> invalidate = new LinkedList<>(); Queue<MessageId> invalidate = new LinkedList<>();
invalidate.add(m.getId()); invalidate.add(m.getId());
invalidateNextMessageAsync(invalidate); invalidateNextMessageAsync(invalidate);
@@ -326,7 +326,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} catch (NoSuchGroupException e) { } catch (NoSuchGroupException e) {
LOG.info("Group removed during validation"); LOG.info("Group removed during validation");
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -377,7 +377,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} }
shareNextMessageAsync(toShare); shareNextMessageAsync(toShare);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -412,7 +412,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
LOG.info("Group removed before sharing"); LOG.info("Group removed before sharing");
shareNextMessageAsync(toShare); shareNextMessageAsync(toShare);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -440,7 +440,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
LOG.info("Message removed before invalidation"); LOG.info("Message removed before invalidation");
invalidateNextMessageAsync(invalidate); invalidateNextMessageAsync(invalidate);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -492,7 +492,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} catch (NoSuchGroupException e) { } catch (NoSuchGroupException e) {
LOG.info("Group removed before validation"); LOG.info("Group removed before validation");
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -13,6 +13,7 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
@@ -49,7 +50,7 @@ class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
out.close(); out.close();
} catch (IOException e) { } catch (IOException e) {
// On some devices /dev/urandom isn't writable - this isn't fatal // On some devices /dev/urandom isn't writable - this isn't fatal
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -10,6 +10,7 @@ import java.security.SecureRandomSpi;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
public class LinuxSecureRandomSpi extends SecureRandomSpi { public class LinuxSecureRandomSpi extends SecureRandomSpi {
@@ -39,7 +40,7 @@ public class LinuxSecureRandomSpi extends SecureRandomSpi {
out.close(); out.close();
} catch (IOException e) { } catch (IOException e) {
// On some devices /dev/urandom isn't writable - this isn't fatal // On some devices /dev/urandom isn't writable - this isn't fatal
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -36,6 +36,7 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -169,7 +170,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
db.endTransaction(txn); db.endTransaction(txn);
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -28,6 +28,7 @@ import javax.annotation.concurrent.ThreadSafe;
import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER; import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER;
import static com.sun.jna.Library.OPTION_TYPE_MAPPER; import static com.sun.jna.Library.OPTION_TYPE_MAPPER;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -141,7 +142,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
user32.DispatchMessage(msg); user32.DispatchMessage(msg);
} }
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -19,6 +19,7 @@ import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier; import javax.microedition.io.StreamConnectionNotifier;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isValidMac; import static org.briarproject.bramble.util.StringUtils.isValidMac;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -85,7 +86,7 @@ class JavaBluetoothPlugin extends BluetoothPlugin<StreamConnectionNotifier> {
try { try {
if (ss != null) ss.close(); if (ss != null) ss.close();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -27,6 +27,7 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static jssc.SerialPort.PURGE_RXCLEAR; import static jssc.SerialPort.PURGE_RXCLEAR;
import static jssc.SerialPort.PURGE_TXCLEAR; import static jssc.SerialPort.PURGE_TXCLEAR;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -136,7 +137,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try { try {
if (port != null) port.closePort(); if (port != null) port.closePort();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -327,7 +328,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
} }
} }
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
@@ -394,8 +395,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try { try {
answer(); answer();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
} }
}); });
} }

View File

@@ -23,6 +23,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -81,7 +82,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
running = true; running = true;
return; return;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
throw new PluginException(); throw new PluginException();
@@ -94,7 +95,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try { try {
modem.stop(); modem.stop();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
} }
@@ -131,7 +132,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
LOG.info("Initialised modem on " + portName); LOG.info("Initialised modem on " + portName);
return true; return true;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }
running = false; running = false;
@@ -157,7 +158,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try { try {
if (!modem.dial(number)) return null; if (!modem.dial(number)) return null;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
resetModem(); resetModem();
return null; return null;
} }
@@ -209,7 +210,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try { try {
modem.hangUp(); modem.hangUp();
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
exception = true; exception = true;
} }
if (exception) resetModem(); if (exception) resetModem();

View File

@@ -4,3 +4,4 @@ build
local.properties local.properties
.settings .settings
src/main/assets/*.zip src/main/assets/*.zip
src/main/res/values-iw

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 24 24"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="notification_ongoing.svg"
width="24"
height="24"><metadata
id="metadata61"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs59" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview57"
showgrid="false"
inkscape:zoom="11.466748"
inkscape:cx="-4.790356"
inkscape:cy="17.536496"
inkscape:window-x="1442"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
units="px" /><style
type="text/css"
id="style3">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#87C214;}
.st2{fill:#87C214;}
.st3{display:none;fill:#FFFFFF;}
.st4{fill:#95D220;}
.st5{display:none;fill:#95D220;}
</style><path
style="fill:#ffffff;stroke-width:0.07272727"
d="M 12,0 A 12,12 0 0 0 0,12 12,12 0 0 0 12,24 12,12 0 0 0 24,12 12,12 0 0 0 12,0 Z M 8.1454545,3.4764204 h 0.6036931 c 0.7054546,0 1.2872164,0.5817614 1.2872164,1.287216 V 6.4 H 6.8582386 V 4.7636364 c 0,-0.7054546 0.5817614,-1.287216 1.2872159,-1.287216 z m 7.0545455,0 h 0.603693 c 0.712727,0 1.287216,0.5817614 1.287216,1.287216 V 13.454545 H 13.912784 V 4.7636364 c 0,-0.7054546 0.581761,-1.287216 1.287216,-1.287216 z M 4.7127841,6.9090909 H 13.403693 V 10.087216 H 4.7127841 c -0.7127273,0 -1.287358,-0.5817618 -1.287358,-1.2872156 V 8.1963069 c 0,-0.7127273 0.5819034,-1.287216 1.287358,-1.287216 z m 12.8872159,0 h 1.636364 c 0.705454,0 1.279943,0.5817615 1.287216,1.287216 v 0.6036935 c 0,0.7127269 -0.581762,1.2872156 -1.287216,1.2872156 H 17.6 Z M 6.8582386,10.596307 h 3.1781254 v 8.690909 c 0,0.705454 -0.5817618,1.287358 -1.2872164,1.287358 H 8.1454545 c -0.7127272,0 -1.2872159,-0.581904 -1.2872159,-1.287358 z m -2.1454545,3.367329 h 1.6363636 v 3.178125 H 4.7127841 c -0.7127273,0 -1.287358,-0.581761 -1.287358,-1.287216 v -0.603693 c 0,-0.712727 0.5819034,-1.287216 1.287358,-1.287216 z m 5.8326709,0 h 8.690909 c 0.705454,0 1.279943,0.581761 1.287216,1.287216 v 0.603693 c 0,0.705455 -0.581762,1.287216 -1.287216,1.287216 h -8.690909 z m 3.367329,3.687216 h 3.178125 v 1.636364 c 0,0.705454 -0.581761,1.287358 -1.287216,1.287358 H 15.2 c -0.705455,0 -1.287216,-0.581904 -1.287216,-1.287358 z"
id="circle7"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 24 24"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="notification_reminder.svg"
width="24"
height="24"><metadata
id="metadata61"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs59" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview57"
showgrid="false"
inkscape:zoom="32.43286"
inkscape:cx="6.4172501"
inkscape:cy="12.231457"
inkscape:window-x="1442"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
units="px" /><style
type="text/css"
id="style3">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#87C214;}
.st2{fill:#87C214;}
.st3{display:none;fill:#FFFFFF;}
.st4{fill:#95D220;}
.st5{display:none;fill:#95D220;}
</style><path
style="display:inline;fill:#ffffff;stroke-width:0.07272727"
d="M 12 0 A 12 12 0 0 0 4.875 2.3613281 L 6.9316406 4.4160156 C 7.0875805 3.8805807 7.5639651 3.4765625 8.1464844 3.4765625 L 8.7480469 3.4765625 C 9.4535014 3.4765625 10.035156 4.0582174 10.035156 4.7636719 L 10.035156 6.4003906 L 8.9140625 6.4003906 L 9.4238281 6.9101562 L 13.404297 6.9101562 L 13.404297 10.085938 L 12.601562 10.085938 L 13.914062 11.398438 L 13.914062 4.7636719 C 13.914062 4.0582174 14.495717 3.4765625 15.201172 3.4765625 L 15.802734 3.4765625 C 16.515461 3.4765625 17.089844 4.0582174 17.089844 4.7636719 L 17.089844 13.455078 L 15.96875 13.455078 L 16.478516 13.964844 L 19.236328 13.964844 C 19.941782 13.964844 20.516165 14.546498 20.523438 15.251953 L 20.523438 15.853516 C 20.523438 16.436036 20.119418 16.91242 19.583984 17.068359 L 21.638672 19.125 A 12 12 0 0 0 24 12 A 12 12 0 0 0 12 0 z M 1.2617188 1.3632812 L 0 2.6269531 L 2.3125 4.9472656 A 12 12 0 0 0 0 12 A 12 12 0 0 0 12 24 A 12 12 0 0 0 19.027344 21.707031 L 21.314453 24 L 22.576172 22.734375 L 2.7519531 2.8554688 L 1.9863281 2.0898438 L 1.2617188 1.3632812 z M 17.599609 6.9101562 L 19.236328 6.9101562 C 19.941782 6.9101562 20.516165 7.4918111 20.523438 8.1972656 L 20.523438 8.7988281 C 20.523438 9.511555 19.941782 10.085937 19.236328 10.085938 L 17.599609 10.085938 L 17.599609 6.9101562 z M 4.359375 6.9980469 L 7.4394531 10.085938 L 4.7128906 10.085938 C 4.0001632 10.085938 3.4257813 9.504282 3.4257812 8.7988281 L 3.4257812 8.1972656 C 3.4257812 7.6133228 3.8294199 7.1540656 4.359375 6.9980469 z M 6.859375 10.595703 L 7.9472656 10.595703 L 10.035156 12.689453 L 10.035156 19.287109 C 10.035156 19.992562 9.4535014 20.574219 8.7480469 20.574219 L 8.1464844 20.574219 C 7.4337573 20.574219 6.859375 19.992563 6.859375 19.287109 L 6.859375 10.595703 z M 4.7128906 13.964844 L 6.3496094 13.964844 L 6.3496094 17.140625 L 4.7128906 17.140625 C 4.0001632 17.140625 3.4257813 16.558971 3.4257812 15.853516 L 3.4257812 15.251953 C 3.4257812 14.539226 4.007436 13.964844 4.7128906 13.964844 z M 10.544922 13.964844 L 11.306641 13.964844 L 14.474609 17.140625 L 10.544922 17.140625 L 10.544922 13.964844 z M 13.914062 17.650391 L 14.982422 17.650391 L 16.992188 19.666016 C 16.827053 20.182975 16.371277 20.574219 15.802734 20.574219 L 15.201172 20.574219 C 14.495717 20.574219 13.914063 19.992563 13.914062 19.287109 L 13.914062 17.650391 z "
id="circle7" /></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -22,7 +22,7 @@ dependencies {
implementation "com.android.support:support-annotations:$supportVersion" implementation "com.android.support:support-annotations:$supportVersion"
implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation('ch.acra:acra:4.8.5') { implementation('ch.acra:acra:4.9.1') {
exclude module: 'support-v4' exclude module: 'support-v4'
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }
@@ -61,7 +61,7 @@ dependencyVerification {
'android.arch.lifecycle:viewmodel:1.1.0:viewmodel-1.1.0.aar:6407c93a5ea9850661dca42a0068d6f3deccefd7228ee69bae1c35d70cbc2557', 'android.arch.lifecycle:viewmodel:1.1.0:viewmodel-1.1.0.aar:6407c93a5ea9850661dca42a0068d6f3deccefd7228ee69bae1c35d70cbc2557',
'backport-util-concurrent:backport-util-concurrent:3.1:backport-util-concurrent-3.1.jar:f5759b7fcdfc83a525a036deedcbd32e5b536b625ebc282426f16ca137eb5902', 'backport-util-concurrent:backport-util-concurrent:3.1:backport-util-concurrent-3.1.jar:f5759b7fcdfc83a525a036deedcbd32e5b536b625ebc282426f16ca137eb5902',
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'ch.acra:acra:4.8.5:acra-4.8.5.aar:afd5b28934d5166b55f261c85685ad59e8a4ebe9ca1960906afaa8c76d8dc9eb', 'ch.acra:acra:4.9.1:acra-4.9.1.aar:d2762968c448757a7d6acc9f141881d9632f664988e9723ece33b5f7c79f3bc9',
'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3', 'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05', 'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
'com.android.support.constraint:constraint-layout-solver:1.1.0:constraint-layout-solver-1.1.0.jar:fcb4c7d705754ca3d69b1b2c3caf445a425599fda8caabbcf855d98ea0663e4e', 'com.android.support.constraint:constraint-layout-solver:1.1.0:constraint-layout-solver-1.1.0.jar:fcb4c7d705754ca3d69b1b2c3caf445a425599fda8caabbcf855d98ea0663e4e',
@@ -82,32 +82,32 @@ dependencyVerification {
'com.android.support:support-v4:27.1.1:support-v4-27.1.1.aar:4f41dfc3e89f2738e45c86264a85c0934d055ee8ebe2020e23c97f303b80a48b', 'com.android.support:support-v4:27.1.1:support-v4-27.1.1.aar:4f41dfc3e89f2738e45c86264a85c0934d055ee8ebe2020e23c97f303b80a48b',
'com.android.support:support-vector-drawable:27.1.1:support-vector-drawable-27.1.1.aar:1c0f421114cf4627cf208776d6eb4f76340c78b7e96fe6e12b3e6eb950caf1b9', 'com.android.support:support-vector-drawable:27.1.1:support-vector-drawable-27.1.1.aar:1c0f421114cf4627cf208776d6eb4f76340c78b7e96fe6e12b3e6eb950caf1b9',
'com.android.support:transition:27.1.1:transition-27.1.1.aar:c0765b2f3c78696567ec5b3f519d22da1e3df11ac994625adf4bb4dc571caacc', 'com.android.support:transition:27.1.1:transition-27.1.1.aar:c0765b2f3c78696567ec5b3f519d22da1e3df11ac994625adf4bb4dc571caacc',
'com.android.tools.analytics-library:protos:26.1.2:protos-26.1.2.jar:52672a0b42b572a06aecc3535d5068eb46c0e15d129b9f1085d3c16a1da5cdbb', 'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.2:shared-26.1.2.jar:5c7e0eda18c6f87feeb83628c707e8aaa3298b41fb72e38efe31ad1675f9e8e9', 'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.2:tracker-26.1.2.jar:06f97aa0adf44ffb06f8681c6a79d9be153a08f61d21eddc42b8d3db96df4282', 'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.2:apksig-3.1.2.jar:40696a4559124d1d57873d208857eee059d48859239d569c7d18374ac644a8be', 'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.2:builder-model-3.1.2.jar:d49bfa2a135c9562b6ca7aa4342036cfa1582c7074c2d1d93d1dae8b3a134e17', 'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.2:builder-test-api-3.1.2.jar:dfe2a50b740d41b11189101062434d4283d18647e89a492ad51710c719363e9f', 'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.2:builder-3.1.2.jar:b60f825a42e2efe8433619fbc759f3d9effecab718279048d36881188ceb1d14', 'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.2:gradle-api-3.1.2.jar:e58bcc5b893e4583ab0f5c8ef89c4dbcce202b405a9d7fcc116d21e5357d4893', 'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.2:manifest-merger-26.1.2.jar:9c61c27ea5266573107b954acf1216d398f4d7e7ae6fad6409d6b2b767eb091c', 'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.2:ddmlib-26.1.2.jar:18a2a5fbef36882f07d03c2b9e59eba05cf8248177bf5cbff736e4b582804c44', 'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.2:intellij-core-26.1.2.jar:37c5acf279f1ae3e85b1a5be3c9f15f43bde7b08f978eefefffb9c4035760c52', 'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.2:kotlin-compiler-26.1.2.jar:152df0bee7580326c77316b669a9d96e3b09efb1d45f545dce4147271b0b8944', 'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.2:uast-26.1.2.jar:02d39582206d3f5fc0a6cb18bfd9e8b9f9c1acb805ec6dac08b4e3a56849d279', 'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.2:layoutlib-api-26.1.2.jar:20220039fcc7d799f928153beff862e704457c0f55ab44258f3745ebeb662b4f', 'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.2:lint-api-26.1.2.jar:e1d5b62b870a7c566e9877a6b96b27784a4d713f8caa07fdcb4705d47a40a1d9', 'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.2:lint-checks-26.1.2.jar:211e2afd58504372385d71b1e5be982c2b5121ab6fee1c04ddabeb75a8729e07', 'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.2:lint-gradle-api-26.1.2.jar:71284f2a8b03c3e55c94511c9eb36f8184fbb85324325fc6b78abf5183f03d90', 'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.2:lint-gradle-26.1.2.jar:855f0c82b7fc690df1b7319c0774f7517f7f8f5dd4eee1f6077dcf50e07c6240', 'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.2:lint-kotlin-26.1.2.jar:1e591f70bcbbc11569720a9bbcca2bc1f3d4f789f01f40f642848d920643d484', 'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.2:lint-26.1.2.jar:93736c62e9f1976998c2b4aa716aea0734cdb162d05502f4af7292654aedb182', 'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.2:annotations-26.1.2.jar:72773dcaf5c4ccca828e3c8467f1b78a8a00b3cc5f8ad1aab88fcf9379928018', 'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.2:common-26.1.2.jar:ea4320f0c17dcbc4491896bb705c4d25ec08bd62ef02ab0579fe154e75e788e6', 'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.2:dvlib-26.1.2.jar:1187aa4fb666595c96c4deb6bc0e0f4b7e396bde9f6243330b49a232946130ea', 'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.2:repository-26.1.2.jar:8b86e512ad6d32bd76989451eefe2b271f5efce6d4d65ecb173afaf14606e01a', 'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.2:sdk-common-26.1.2.jar:23584720a60a21cdcb5b1ec10269e3013789d6805d153cc696c39ec7ce251896', 'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.2:sdklib-26.1.2.jar:d3870fafc59ab8efa70d3f9649f40ee299c8ec5b58377b06e8853d7272a5bf4e', 'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655', 'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd', 'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed', 'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
@@ -238,15 +238,16 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 26 targetSdkVersion 26
versionCode 10005 versionCode 10011
versionName "1.0.5" versionName "1.0.11"
applicationId "org.briarproject.briar.android" applicationId "org.briarproject.briar.android"
resValue "string", "app_package", "org.briarproject.briar.android" resValue "string", "app_package", "org.briarproject.briar.android"
resValue "string", "app_name", "Briar" resValue "string", "app_name", "Briar"
buildConfigField "String", "GitHash", buildConfigField "String", "GitHash",
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\"" "\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
def now = (long) (System.currentTimeMillis() / 1000)
buildConfigField "Long", "BuildTimestamp", buildConfigField "Long", "BuildTimestamp",
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], 0)}000L" "${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
} }
buildTypes { buildTypes {
@@ -260,7 +261,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
} }
release { release {
shrinkResources true shrinkResources false
minifyEnabled true minifyEnabled true
crunchPngs false crunchPngs false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
@@ -284,3 +285,46 @@ android {
warning 'ExtraTranslation' warning 'ExtraTranslation'
} }
} }
task verifyTranslations {
doLast {
def file = project.file("src/main/res/values/arrays.xml")
def arrays = new XmlParser().parse(file)
def lc = arrays.children().find { it.@name == "pref_language_values" }
def translations = []
lc.children().each { value -> translations.add(value.text()) }
def folders = ["default", "en-US"]
project.file("src/main/res").eachDir { dir ->
if (dir.name.startsWith("values-") && !dir.name.endsWith("night")) {
folders.add(dir.name.substring(7).replace("-r", "-"))
}
}
folders.each { n ->
if (!translations.remove(n) && n != 'iw') {
throw new GradleException("Translation " + n + " is missing in $file")
}
}
if (translations.size() != 0)
throw new GradleException("Translations\n" + translations.join("\n")
+ "\nhave no matching value folder")
// Some devices use iw instead of he for hebrew
def hebrew_legacy = project.file("src/main/res/values-iw")
def hebrew = project.file("src/main/res/values-he")
// Copy values-he to values-iw
if (hebrew.exists()) {
hebrew_legacy.mkdir()
copy {
from hebrew.getAbsolutePath()
into hebrew_legacy.getAbsolutePath()
}
}
}
}
project.afterEvaluate {
preBuild.dependsOn.add(verifyTranslations)
}

View File

@@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application <application
@@ -24,6 +25,14 @@
android:logo="@mipmap/ic_launcher_round" android:logo="@mipmap/ic_launcher_round"
android:theme="@style/BriarTheme"> android:theme="@style/BriarTheme">
<receiver
android:name="org.briarproject.briar.android.BootReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service <service
android:name="org.briarproject.briar.android.BriarService" android:name="org.briarproject.briar.android.BriarService"
android:exported="false"> android:exported="false">
@@ -44,7 +53,6 @@
android:finishOnTaskLaunch="true" android:finishOnTaskLaunch="true"
android:label="@string/crash_report_title" android:label="@string/crash_report_title"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:process=":briar_error_handler"
android:theme="@style/BriarTheme.NoActionBar" android:theme="@style/BriarTheme.NoActionBar"
android:windowSoftInputMode="stateHidden"> android:windowSoftInputMode="stateHidden">
</activity> </activity>
@@ -301,7 +309,7 @@
</activity> </activity>
<activity <activity
android:name="org.briarproject.briar.android.keyagreement.KeyAgreementActivity" android:name="org.briarproject.briar.android.keyagreement.ContactExchangeActivity"
android:label="@string/add_contact_title" android:label="@string/add_contact_title"
android:theme="@style/BriarTheme.NoActionBar" android:theme="@style/BriarTheme.NoActionBar"
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"> android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">

View File

@@ -150,6 +150,8 @@ public interface AndroidComponent
@IoExecutor @IoExecutor
Executor ioExecutor(); Executor ioExecutor();
void inject(BootReceiver briarService);
void inject(BriarService briarService); void inject(BriarService briarService);
void inject(BriarReportSender briarReportSender); void inject(BriarReportSender briarReportSender);

View File

@@ -70,6 +70,7 @@ import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE; import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL; import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID; import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID; import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_BLOGS; import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_BLOGS;
@@ -84,13 +85,6 @@ import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_
class AndroidNotificationManagerImpl implements AndroidNotificationManager, class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Service, EventListener { Service, EventListener {
// Notification IDs
private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
private static final int GROUP_MESSAGE_NOTIFICATION_ID = 4;
private static final int FORUM_POST_NOTIFICATION_ID = 5;
private static final int BLOG_POST_NOTIFICATION_ID = 6;
private static final int INTRODUCTION_SUCCESS_NOTIFICATION_ID = 7;
private static final long SOUND_DELAY = TimeUnit.SECONDS.toMillis(2); private static final long SOUND_DELAY = TimeUnit.SECONDS.toMillis(2);
private static final Logger LOG = private static final Logger LOG =
@@ -265,8 +259,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
try { try {
settings = settingsManager.getSettings(SETTINGS_NAMESPACE); settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
} }
}); });
} }

View File

@@ -20,16 +20,17 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.reporting.DevConfig; import org.briarproject.bramble.api.reporting.DevConfig;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.Scheduler; import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory; import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.plugin.tor.TorPluginFactory; import org.briarproject.bramble.plugin.tor.TorPluginFactory;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.ReferenceManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
import java.io.File; import java.io.File;
@@ -97,14 +98,15 @@ public class AppModule {
@Scheduler ScheduledExecutorService scheduler, @Scheduler ScheduledExecutorService scheduler,
AndroidExecutor androidExecutor, SecureRandom random, AndroidExecutor androidExecutor, SecureRandom random,
SocketFactory torSocketFactory, BackoffFactory backoffFactory, SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, LocationUtils locationUtils, EventBus eventBus) { Application app, LocationUtils locationUtils, EventBus eventBus,
CircumventionProvider circumventionProvider, Clock clock) {
Context appContext = app.getApplicationContext(); Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = DuplexPluginFactory bluetooth =
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor, new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
appContext, random, eventBus, backoffFactory); appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler, DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler,
appContext, locationUtils, eventBus, appContext, locationUtils, eventBus, torSocketFactory,
torSocketFactory, backoffFactory); backoffFactory, circumventionProvider, clock);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
scheduler, backoffFactory, appContext); scheduler, backoffFactory, appContext);
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan); Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
@@ -163,12 +165,6 @@ public class AppModule {
return app.getSharedPreferences("db", MODE_PRIVATE); return app.getSharedPreferences("db", MODE_PRIVATE);
} }
@Provides
@Singleton
ReferenceManager provideReferenceManager() {
return new ReferenceManagerImpl();
}
@Provides @Provides
@Singleton @Singleton
AndroidNotificationManager provideAndroidNotificationManager( AndroidNotificationManager provideAndroidNotificationManager(

View File

@@ -0,0 +1,83 @@
package org.briarproject.briar.android;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.briar.R;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import javax.inject.Inject;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.PRIORITY_LOW;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class BootReceiver extends BroadcastReceiver {
@Inject
DatabaseConfig databaseConfig;
@Override
public void onReceive(Context ctx, Intent intent) {
if (!FEATURE_FLAG_SIGN_IN_REMINDER) return;
AndroidComponent applicationComponent =
((BriarApplication) ctx.getApplicationContext())
.getApplicationComponent();
applicationComponent.inject(this);
String action = intent.getAction();
if (action != null && action.equals(ACTION_BOOT_COMPLETED)) {
if (databaseConfig.databaseExists()) {
showSignInNotification(ctx);
}
}
}
private void showSignInNotification(Context ctx) {
NotificationManager nm = (NotificationManager)
ctx.getSystemService(NOTIFICATION_SERVICE);
if (nm == null) return;
if (SDK_INT >= 26) {
NotificationChannel channel =
new NotificationChannel(REMINDER_CHANNEL_ID, ctx.getString(
R.string.reminder_notification_channel_title),
IMPORTANCE_LOW);
channel.setLockscreenVisibility(VISIBILITY_SECRET);
nm.createNotificationChannel(channel);
}
NotificationCompat.Builder b =
new NotificationCompat.Builder(ctx, REMINDER_CHANNEL_ID);
b.setSmallIcon(R.drawable.notification_reminder);
b.setColor(ContextCompat.getColor(ctx, R.color.briar_primary));
b.setContentTitle(ctx.getText(R.string.reminder_notification_title));
b.setContentText(ctx.getText(R.string.reminder_notification_text));
b.setAutoCancel(true);
b.setWhen(0); // Don't show the time
b.setPriority(PRIORITY_LOW);
Intent i = new Intent(ctx, NavDrawerActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(ctx, 0, i, 0));
nm.notify(REMINDER_NOTIFICATION_ID, b.build());
}
}

View File

@@ -2,9 +2,12 @@ package org.briarproject.briar.android;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.StrictMode; import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy; import android.os.StrictMode.ThreadPolicy;
import android.os.StrictMode.VmPolicy; import android.os.StrictMode.VmPolicy;
import android.preference.PreferenceManager;
import org.acra.ACRA; import org.acra.ACRA;
import org.acra.ReportingInteractionMode; import org.acra.ReportingInteractionMode;
@@ -16,12 +19,14 @@ import org.briarproject.briar.android.logging.CachingLogHandler;
import org.briarproject.briar.android.reporting.BriarReportPrimer; import org.briarproject.briar.android.reporting.BriarReportPrimer;
import org.briarproject.briar.android.reporting.BriarReportSenderFactory; import org.briarproject.briar.android.reporting.BriarReportSenderFactory;
import org.briarproject.briar.android.reporting.DevReportActivity; import org.briarproject.briar.android.reporting.DevReportActivity;
import org.briarproject.briar.android.util.UiUtils;
import java.util.Collection; import java.util.Collection;
import java.util.logging.Handler; import java.util.logging.Handler;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.acra.ReportField.ANDROID_VERSION; import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.APP_VERSION_CODE; import static org.acra.ReportField.APP_VERSION_CODE;
@@ -75,7 +80,13 @@ public class BriarApplicationImpl extends Application
@Override @Override
protected void attachBaseContext(Context base) { protected void attachBaseContext(Context base) {
super.attachBaseContext(base); SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(base);
// Loading the language needs to be done here.
Localizer.initialize(prefs);
super.attachBaseContext(
Localizer.getInstance().setLocale(base));
setTheme(base, prefs);
ACRA.init(this); ACRA.init(this);
} }
@@ -93,7 +104,7 @@ public class BriarApplicationImpl extends Application
} }
} }
rootLogger.addHandler(logHandler); rootLogger.addHandler(logHandler);
rootLogger.setLevel(INFO); rootLogger.setLevel(IS_DEBUG_BUILD || IS_BETA_BUILD ? FINE : INFO);
LOG.info("Created"); LOG.info("Created");
@@ -106,6 +117,24 @@ public class BriarApplicationImpl extends Application
BrambleCoreModule.initEagerSingletons(applicationComponent); BrambleCoreModule.initEagerSingletons(applicationComponent);
BriarCoreModule.initEagerSingletons(applicationComponent); BriarCoreModule.initEagerSingletons(applicationComponent);
AndroidEagerSingletons.initEagerSingletons(applicationComponent); AndroidEagerSingletons.initEagerSingletons(applicationComponent);
new SleepMonitor().start();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Localizer.getInstance().setLocale(this);
}
private void setTheme(Context ctx, SharedPreferences prefs) {
String theme = prefs.getString("pref_key_theme", null);
if (theme == null) {
// set default value
theme = getString(R.string.pref_theme_light_value);
prefs.edit().putString("pref_key_theme", theme).apply();
}
// set theme
UiUtils.setTheme(ctx, theme);
} }
private void enableStrictMode() { private void enableStrictMode() {

View File

@@ -0,0 +1,84 @@
package org.briarproject.briar.android;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.PowerManager;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.POWER_SERVICE;
import static android.content.Intent.ACTION_AIRPLANE_MODE_CHANGED;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.BatteryManager.EXTRA_LEVEL;
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.BatteryManager.EXTRA_SCALE;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED;
public class BriarBroadcastReceiver extends WakefulBroadcastReceiver {
IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SCREEN_ON);
filter.addAction(ACTION_SCREEN_OFF);
filter.addAction(ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
if (SDK_INT >= 21) filter.addAction(ACTION_POWER_SAVE_MODE_CHANGED);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
filter.addAction(ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(CONNECTIVITY_ACTION);
return filter;
}
@Override
public void onReceive(Context ctx, Intent i) {
String action = i.getAction();
if (ACTION_SCREEN_ON.equals(action)) {
Log.i("DEVICE_STATUS", "Screen on");
} else if (ACTION_SCREEN_OFF.equals(action)) {
Log.i("DEVICE_STATUS", "Screen off");
} else if (ACTION_BATTERY_CHANGED.equals(action)) {
int level = i.getIntExtra(EXTRA_LEVEL, -1);
int scale = i.getIntExtra(EXTRA_SCALE, -1);
int plugged = i.getIntExtra(EXTRA_PLUGGED, -1);
Log.i("DEVICE_STATUS", "Battery level: " + (level / (float) scale)
+ ", plugged: " + (plugged != 0));
} else if (ACTION_POWER_CONNECTED.equals(action)) {
Log.i("DEVICE_STATUS", "Power connected");
} else if (ACTION_POWER_DISCONNECTED.equals(action)) {
Log.i("DEVICE_STATUS", "Power disconnected");
} else if (SDK_INT >= 21
&& ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
PowerManager pm = (PowerManager)
ctx.getSystemService(POWER_SERVICE);
Log.i("DEVICE_STATUS", "Power save mode: " + pm.isPowerSaveMode());
} else if (SDK_INT >= 23
&& ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
PowerManager pm = (PowerManager)
ctx.getSystemService(POWER_SERVICE);
Log.i("DEVICE_STATUS", " Idle mode: " + pm.isDeviceIdleMode());
} else if (ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
Log.i("DEVICE_STATUS",
"Airplane mode: " + i.getBooleanExtra("state", false));
} else if (CONNECTIVITY_ACTION.equals(action)) {
ConnectivityManager cm = (ConnectivityManager)
ctx.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo net = cm.getActiveNetworkInfo();
boolean online = net != null && net.isConnected();
boolean wifi = net != null && net.getType() == TYPE_WIFI;
Log.i("DEVICE_STATUS", "Online: " + online + ", wifi: " + wifi);
}
}
}

View File

@@ -1,5 +1,8 @@
package org.briarproject.briar.android; package org.briarproject.briar.android;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlarmManager;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@@ -11,9 +14,14 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Binder; import android.os.Binder;
import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.util.Log;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -30,8 +38,11 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
@@ -40,13 +51,22 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE;
import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.PowerTestingConstants.ALARM_DELAY;
import static org.briarproject.bramble.PowerTestingConstants.USE_TOR_WAKE_LOCK;
import static org.briarproject.bramble.PowerTestingConstants.WAKE_LOCK_DURATION;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class BriarService extends Service { public class BriarService extends Service {
@@ -57,13 +77,12 @@ public class BriarService extends Service {
public static String EXTRA_STARTUP_FAILED = public static String EXTRA_STARTUP_FAILED =
"org.briarproject.briar.STARTUP_FAILED"; "org.briarproject.briar.STARTUP_FAILED";
private static final int ONGOING_NOTIFICATION_ID = 1; // This tag prevents the wake lock from being ignored on some Huawei devices
private static final int FAILURE_NOTIFICATION_ID = 2; private static final String WAKE_LOCK_TAG = "LocationManagerService";
private static final String ACTION_ALARM =
// Channels are sorted by channel ID in the Settings app, so use IDs "org.briarproject.briar.android.ACTION_ALARM";
// that will sort below the main channels such as contacts private static final String EXTRA_DUE_MILLIS =
private static final String ONGOING_CHANNEL_ID = "zForegroundService"; "org.briarproject.briar.android.DUE_MILLIS";
private static final String FAILURE_CHANNEL_ID = "zStartupFailure";
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(BriarService.class.getName()); Logger.getLogger(BriarService.class.getName());
@@ -71,9 +90,14 @@ public class BriarService extends Service {
private final AtomicBoolean created = new AtomicBoolean(false); private final AtomicBoolean created = new AtomicBoolean(false);
private final Binder binder = new BriarBinder(); private final Binder binder = new BriarBinder();
private AlarmManager alarm;
@Nullable @Nullable
private BroadcastReceiver receiver = null; private BroadcastReceiver receiver = null;
@Nullable
private BriarBroadcastReceiver testReceiver = null;
@Inject @Inject
protected DatabaseConfig databaseConfig; protected DatabaseConfig databaseConfig;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@@ -90,6 +114,11 @@ public class BriarService extends Service {
BriarApplication application = (BriarApplication) getApplication(); BriarApplication application = (BriarApplication) getApplication();
application.getApplicationComponent().inject(this); application.getApplicationComponent().inject(this);
alarm = (AlarmManager)
getApplicationContext().getSystemService(ALARM_SERVICE);
setAlarm();
LOG.info("Created"); LOG.info("Created");
if (created.getAndSet(true)) { if (created.getAndSet(true)) {
LOG.info("Already created"); LOG.info("Already created");
@@ -103,9 +132,9 @@ public class BriarService extends Service {
} }
// Create notification channels // Create notification channels
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (SDK_INT >= 26) { if (SDK_INT >= 26) {
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
NotificationChannel ongoingChannel = new NotificationChannel( NotificationChannel ongoingChannel = new NotificationChannel(
ONGOING_CHANNEL_ID, ONGOING_CHANNEL_ID,
getString(R.string.ongoing_notification_title), getString(R.string.ongoing_notification_title),
@@ -137,6 +166,8 @@ public class BriarService extends Service {
} }
b.setPriority(PRIORITY_MIN); b.setPriority(PRIORITY_MIN);
startForeground(ONGOING_NOTIFICATION_ID, b.build()); startForeground(ONGOING_NOTIFICATION_ID, b.build());
// Remove sign-in reminder notification
nm.cancel(REMINDER_NOTIFICATION_ID);
// Start the services in a background thread // Start the services in a background thread
new Thread(() -> { new Thread(() -> {
String nickname = databaseConfig.getLocalAuthorName(); String nickname = databaseConfig.getLocalAuthorName();
@@ -166,6 +197,39 @@ public class BriarService extends Service {
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF"); filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF"); filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
registerReceiver(receiver, filter); registerReceiver(receiver, filter);
testReceiver = new BriarBroadcastReceiver();
registerReceiver(testReceiver, testReceiver.getIntentFilter());
}
private void setAlarm() {
long dueMillis = SystemClock.elapsedRealtime() + ALARM_DELAY;
PendingIntent pi = getPendingIntent(dueMillis);
if (SDK_INT >= 23) {
alarm.setExactAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP,
dueMillis, pi);
} else if (SDK_INT >= 19) {
alarm.setExact(ELAPSED_REALTIME_WAKEUP, dueMillis, pi);
} else {
alarm.set(ELAPSED_REALTIME_WAKEUP, dueMillis, pi);
}
Log.i("ALARM_TEST", "Alarm set for " + ALARM_DELAY + " ms");
}
PendingIntent getPendingIntent(long dueMillis) {
return PendingIntent.getService(getApplicationContext(), 0,
getAlarmIntent(dueMillis), FLAG_CANCEL_CURRENT);
}
Intent getAlarmIntent(long dueMillis) {
Intent i = new Intent(getApplicationContext(), BriarService.class);
i.setAction(ACTION_ALARM);
i.putExtra(EXTRA_DUE_MILLIS, dueMillis);
return i;
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(Localizer.getInstance().setLocale(base));
} }
private void showStartupFailureNotification(StartResult result) { private void showStartupFailureNotification(StartResult result) {
@@ -197,6 +261,30 @@ public class BriarService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_ALARM.equals(intent.getAction())) {
long dueMillis = intent.getLongExtra(EXTRA_DUE_MILLIS, 0);
long late = SystemClock.elapsedRealtime() - dueMillis;
Log.i("ALARM_TEST", "Alarm fired " + late + " ms late");
PowerManager powerManager = (PowerManager)
getApplicationContext().getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG);
if (!USE_TOR_WAKE_LOCK) {
//acquire wakelock
wakeLock.acquire();
Log.i("ALARM_TEST", "WakeLock acquired for "
+ WAKE_LOCK_DURATION + " ms");
}
new Handler().postDelayed(() -> {
//set alarm before releasing wake lock
setAlarm();
if (!USE_TOR_WAKE_LOCK) {
//release wakelock
Log.i("ALARM_TEST", "Releasing WakeLock");
wakeLock.release();
}
}, WAKE_LOCK_DURATION);
}
return START_NOT_STICKY; // Don't restart automatically if killed return START_NOT_STICKY; // Don't restart automatically if killed
} }
@@ -211,10 +299,12 @@ public class BriarService extends Service {
LOG.info("Destroyed"); LOG.info("Destroyed");
stopForeground(true); stopForeground(true);
if (receiver != null) unregisterReceiver(receiver); if (receiver != null) unregisterReceiver(receiver);
if (testReceiver != null) unregisterReceiver(testReceiver);
// Stop the services in a background thread // Stop the services in a background thread
new Thread(() -> { new Thread(() -> {
if (started) lifecycleManager.stopServices(); if (started) lifecycleManager.stopServices();
}).start(); }).start();
} }
@Override @Override
@@ -243,8 +333,10 @@ public class BriarService extends Service {
LOG.info("Trim memory: running low"); LOG.info("Trim memory: running low");
} else if (level == TRIM_MEMORY_RUNNING_CRITICAL) { } else if (level == TRIM_MEMORY_RUNNING_CRITICAL) {
LOG.info("Trim memory: running critically low"); LOG.info("Trim memory: running critically low");
// Clear the UI to save some memory // If we're not in the foreground, clear the UI to save memory
hideUi(); RunningAppProcessInfo info = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(info);
if (info.importance != IMPORTANCE_FOREGROUND) hideUi();
} else if (LOG.isLoggable(INFO)) { } else if (LOG.isLoggable(INFO)) {
LOG.info("Trim memory: unknown level " + level); LOG.info("Trim memory: unknown level " + level);
} }

View File

@@ -0,0 +1,92 @@
package org.briarproject.briar.android;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Locale;
import javax.annotation.Nullable;
import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.briar.android.settings.SettingsFragment.LANGUAGE;
@NotNullByDefault
public class Localizer {
// Locking: class
@Nullable
private static Localizer INSTANCE;
private final Locale systemLocale;
private final Locale locale;
private Localizer(SharedPreferences sharedPreferences) {
this(Locale.getDefault(), getLocaleFromTag(
sharedPreferences.getString(LANGUAGE, "default")));
}
private Localizer(Locale systemLocale, @Nullable Locale userLocale) {
this.systemLocale = systemLocale;
if (userLocale == null) locale = systemLocale;
else locale = userLocale;
}
// Instantiate the Localizer.
public static synchronized void initialize(SharedPreferences prefs) {
if (INSTANCE == null)
INSTANCE = new Localizer(prefs);
}
// Reinstantiate the Localizer with the system locale
public static synchronized void reinitialize() {
if (INSTANCE != null)
INSTANCE = new Localizer(INSTANCE.systemLocale, null);
}
// Get the current instance.
public static synchronized Localizer getInstance() {
if (INSTANCE == null)
throw new IllegalStateException("Localizer not initialized");
return INSTANCE;
}
// Get Locale from BCP-47 tag
@Nullable
public static Locale getLocaleFromTag(String tag) {
if (tag.equals("default"))
return null;
if (SDK_INT >= 21) {
return Locale.forLanguageTag(tag);
}
if (tag.contains("-")) {
String[] langArray = tag.split("-");
return new Locale(langArray[0], langArray[1]);
} else
return new Locale(tag);
}
// Returns the localized version of context
public Context setLocale(Context context) {
Resources res = context.getResources();
Configuration conf = res.getConfiguration();
Locale currentLocale;
if (SDK_INT >= 24) {
currentLocale = conf.getLocales().get(0);
} else
currentLocale = conf.locale;
if (locale.equals(currentLocale))
return context;
Locale.setDefault(locale);
if (SDK_INT >= 17) {
conf.setLocale(locale);
context.createConfigurationContext(conf);
} else
conf.locale = locale;
//noinspection deprecation
res.updateConfiguration(conf, res.getDisplayMetrics());
return context;
}
}

View File

@@ -4,11 +4,11 @@ import android.net.TrafficStats;
import android.os.Process; import android.os.Process;
import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.LogUtils.now;
class NetworkUsageLogger implements Service { class NetworkUsageLogger implements Service {
@@ -18,17 +18,17 @@ class NetworkUsageLogger implements Service {
private volatile long startTime, rxBytes, txBytes; private volatile long startTime, rxBytes, txBytes;
@Override @Override
public void startService() throws ServiceException { public void startService() {
startTime = System.currentTimeMillis(); startTime = now();
int uid = Process.myUid(); int uid = Process.myUid();
rxBytes = TrafficStats.getUidRxBytes(uid); rxBytes = TrafficStats.getUidRxBytes(uid);
txBytes = TrafficStats.getUidTxBytes(uid); txBytes = TrafficStats.getUidTxBytes(uid);
} }
@Override @Override
public void stopService() throws ServiceException { public void stopService() {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
long sessionDuration = System.currentTimeMillis() - startTime; long sessionDuration = now() - startTime;
int uid = Process.myUid(); int uid = Process.myUid();
long rx = TrafficStats.getUidRxBytes(uid) - rxBytes; long rx = TrafficStats.getUidRxBytes(uid) - rxBytes;
long tx = TrafficStats.getUidTxBytes(uid) - txBytes; long tx = TrafficStats.getUidTxBytes(uid) - txBytes;

View File

@@ -1,83 +0,0 @@
package org.briarproject.briar.android;
import org.briarproject.briar.api.android.ReferenceManager;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
class ReferenceManagerImpl implements ReferenceManager {
private static final Logger LOG =
Logger.getLogger(ReferenceManagerImpl.class.getName());
private final Lock lock = new ReentrantLock();
// The following are locking: lock
private final Map<Class<?>, Map<Long, Object>> outerMap = new HashMap<>();
private long nextHandle = 0;
@Override
public <T> T getReference(long handle, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) {
if (LOG.isLoggable(INFO))
LOG.info("0 handles for " + c.getName());
return null;
}
if (LOG.isLoggable(INFO))
LOG.info(innerMap.size() + " handles for " + c.getName());
Object o = innerMap.get(handle);
return c.cast(o);
} finally {
lock.unlock();
}
}
@Override
public <T> long putReference(T reference, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) {
innerMap = new HashMap<>();
outerMap.put(c, innerMap);
}
long handle = nextHandle++;
innerMap.put(handle, reference);
if (LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after put");
}
return handle;
} finally {
lock.unlock();
}
}
@Override
public <T> T removeReference(long handle, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) return null;
Object o = innerMap.remove(handle);
if (innerMap.isEmpty()) outerMap.remove(c);
if (LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after remove");
}
return c.cast(o);
} finally {
lock.unlock();
}
}
}

View File

@@ -48,6 +48,7 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service { class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
@@ -189,7 +190,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
String publicKey = StringUtils.toHexString(publicKeyBytes); String publicKey = StringUtils.toHexString(publicKeyBytes);
return PLAY_SERVICES_PUBLIC_KEY.equals(publicKey); return PLAY_SERVICES_PUBLIC_KEY.equals(publicKey);
} catch (NameNotFoundException | CertificateException e) { } catch (NameNotFoundException | CertificateException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return false; return false;
} }
} }

View File

@@ -0,0 +1,77 @@
package org.briarproject.briar.android;
import android.os.SystemClock;
import android.util.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static java.util.Locale.US;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class SleepMonitor implements Runnable {
/**
* How often to check the uptime and real time.
*/
private static final int INTERVAL_MS = 5000;
/**
* If the difference between uptime and real time changes by more than
* this amount, assume deep sleep has occurred.
*/
private static final int MIN_SLEEP_DURATION_MS = 1000;
private final ScheduledExecutorService executorService;
private volatile long uptime, realtime, diff;
SleepMonitor() {
uptime = SystemClock.uptimeMillis();
realtime = SystemClock.elapsedRealtime();
diff = realtime - uptime;
executorService = Executors.newSingleThreadScheduledExecutor();
}
void start() {
executorService.scheduleAtFixedRate(this, 0, INTERVAL_MS, MILLISECONDS);
}
@Override
public void run() {
long lastRealtime = realtime;
long sleepDuration = getSleepDuration();
if (sleepDuration > MIN_SLEEP_DURATION_MS) {
long elapsed = realtime - lastRealtime;
long now = System.currentTimeMillis();
String earliestStart = getTime(now - elapsed);
String earliestEnd = getTime(now - elapsed + sleepDuration);
String latestStart = getTime(now - sleepDuration);
String latestEnd = getTime(now);
Log.i("SLEEP_INFO", "System slept for " + sleepDuration
+ " ms since last check " + elapsed
+ " ms ago (earliest " + earliestStart + " - "
+ earliestEnd + ", latest " + latestStart + " - "
+ latestEnd + ")");
}
}
/**
* Returns the amount of time spent in deep sleep since the last check.
*/
private long getSleepDuration() {
uptime = SystemClock.uptimeMillis();
realtime = SystemClock.elapsedRealtime();
long lastDiff = diff;
diff = realtime - uptime;
return diff - lastDiff;
}
private String getTime(long time) {
DateFormat sdf = new SimpleDateFormat("HH:mm:ss", US);
return sdf.format(new Date(time));
}
}

View File

@@ -30,4 +30,14 @@ public interface TestingConstants {
long EXPIRY_DATE = IS_DEBUG_BUILD || IS_BETA_BUILD ? long EXPIRY_DATE = IS_DEBUG_BUILD || IS_BETA_BUILD ?
BuildConfig.BuildTimestamp + 90 * 24 * 60 * 60 * 1000L : BuildConfig.BuildTimestamp + 90 * 24 * 60 * 60 * 1000L :
Long.MAX_VALUE; Long.MAX_VALUE;
/**
* Feature flag for enabling the dark UI theme in release builds.
*/
boolean FEATURE_FLAG_DARK_THEME = false;
/**
* Feature flag for enabling the sign-in reminder in release builds.
*/
boolean FEATURE_FLAG_SIGN_IN_REMINDER = IS_DEBUG_BUILD;
} }

View File

@@ -26,9 +26,10 @@ import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
import org.briarproject.briar.android.introduction.ContactChooserFragment; import org.briarproject.briar.android.introduction.ContactChooserFragment;
import org.briarproject.briar.android.introduction.IntroductionActivity; import org.briarproject.briar.android.introduction.IntroductionActivity;
import org.briarproject.briar.android.introduction.IntroductionMessageFragment; import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
import org.briarproject.briar.android.keyagreement.IntroFragment; import org.briarproject.briar.android.keyagreement.IntroFragment;
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity; import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment; import org.briarproject.briar.android.keyagreement.KeyAgreementFragment;
import org.briarproject.briar.android.login.AuthorNameFragment; import org.briarproject.briar.android.login.AuthorNameFragment;
import org.briarproject.briar.android.login.ChangePasswordActivity; import org.briarproject.briar.android.login.ChangePasswordActivity;
import org.briarproject.briar.android.login.DozeFragment; import org.briarproject.briar.android.login.DozeFragment;
@@ -100,6 +101,8 @@ public interface ActivityComponent {
void inject(PanicPreferencesActivity activity); void inject(PanicPreferencesActivity activity);
void inject(ContactExchangeActivity activity);
void inject(KeyAgreementActivity activity); void inject(KeyAgreementActivity activity);
void inject(ConversationActivity activity); void inject(ConversationActivity activity);
@@ -185,7 +188,7 @@ public interface ActivityComponent {
void inject(IntroFragment fragment); void inject(IntroFragment fragment);
void inject(ShowQrCodeFragment fragment); void inject(KeyAgreementFragment fragment);
void inject(ContactChooserFragment fragment); void inject(ContactChooserFragment fragment);

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.android.activity; package org.briarproject.briar.android.activity;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.support.annotation.LayoutRes; import android.support.annotation.LayoutRes;
@@ -18,6 +19,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.AndroidComponent; import org.briarproject.briar.android.AndroidComponent;
import org.briarproject.briar.android.BriarApplication; import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.DestroyableContext; import org.briarproject.briar.android.DestroyableContext;
import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.controller.ActivityLifecycleController; import org.briarproject.briar.android.controller.ActivityLifecycleController;
import org.briarproject.briar.android.forum.ForumModule; import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
@@ -84,6 +86,12 @@ public abstract class BaseActivity extends AppCompatActivity
} }
} }
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(
Localizer.getInstance().setLocale(base));
}
public ActivityComponent getActivityComponent() { public ActivityComponent getActivityComponent() {
return activityComponent; return activityComponent;
} }

View File

@@ -92,7 +92,6 @@ public abstract class BriarActivity extends BaseActivity {
window.setEnterTransition(slide); window.setEnterTransition(slide);
window.setTransitionBackgroundFadeDuration(getResources() window.setTransitionBackgroundFadeDuration(getResources()
.getInteger(android.R.integer.config_longAnimTime)); .getInteger(android.R.integer.config_longAnimTime));
window.setBackgroundDrawableResource(android.R.color.transparent);
} }
/** /**

View File

@@ -32,8 +32,10 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.util.HtmlUtils.ARTICLE; import static org.briarproject.briar.util.HtmlUtils.ARTICLE;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -101,30 +103,25 @@ abstract class BaseControllerImpl extends DbControllerImpl
Collection<BlogPostItem> items = loadItems(groupId); Collection<BlogPostItem> items = loadItems(groupId);
handler.onResult(items); handler.onResult(items);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });
} }
Collection<BlogPostItem> loadItems(GroupId groupId) throws DbException { Collection<BlogPostItem> loadItems(GroupId groupId) throws DbException {
long now = System.currentTimeMillis(); long start = now();
Collection<BlogPostHeader> headers = Collection<BlogPostHeader> headers =
blogManager.getPostHeaders(groupId); blogManager.getPostHeaders(groupId);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading headers", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading headers took " + duration + " ms");
Collection<BlogPostItem> items = new ArrayList<>(headers.size()); Collection<BlogPostItem> items = new ArrayList<>(headers.size());
now = System.currentTimeMillis(); start = now();
for (BlogPostHeader h : headers) { for (BlogPostHeader h : headers) {
headerCache.put(h.getId(), h); headerCache.put(h.getId(), h);
BlogPostItem item = getItem(h); BlogPostItem item = getItem(h);
items.add(item); items.add(item);
} }
duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading bodies", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading bodies took " + duration + " ms");
return items; return items;
} }
@@ -140,15 +137,12 @@ abstract class BaseControllerImpl extends DbControllerImpl
} }
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
BlogPostItem item = getItem(header); BlogPostItem item = getItem(header);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading body", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading body took " + duration + " ms");
handler.onResult(item); handler.onResult(item);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -166,16 +160,13 @@ abstract class BaseControllerImpl extends DbControllerImpl
} }
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
BlogPostHeader header1 = getPostHeader(g, m); BlogPostHeader header1 = getPostHeader(g, m);
BlogPostItem item = getItem(header1); BlogPostItem item = getItem(header1);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading post", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading post took " + duration + " ms");
handler.onResult(item); handler.onResult(item);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -191,8 +182,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
BlogPostHeader h = item.getHeader(); BlogPostHeader h = item.getHeader();
blogManager.addLocalComment(a, b.getId(), comment, h); blogManager.addLocalComment(a, b.getId(), comment, h);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });

View File

@@ -35,8 +35,10 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -154,19 +156,16 @@ class BlogControllerImpl extends BaseControllerImpl
if (groupId == null) throw new IllegalStateException(); if (groupId == null) throw new IllegalStateException();
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
LocalAuthor a = identityManager.getLocalAuthor(); LocalAuthor a = identityManager.getLocalAuthor();
Blog b = blogManager.getBlog(groupId); Blog b = blogManager.getBlog(groupId);
boolean ours = a.getId().equals(b.getAuthor().getId()); boolean ours = a.getId().equals(b.getAuthor().getId());
boolean removable = blogManager.canBeRemoved(b); boolean removable = blogManager.canBeRemoved(b);
BlogItem blog = new BlogItem(b, ours, removable); BlogItem blog = new BlogItem(b, ours, removable);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading blog", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading blog took " + duration + " ms");
handler.onResult(blog); handler.onResult(blog);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -177,16 +176,13 @@ class BlogControllerImpl extends BaseControllerImpl
if (groupId == null) throw new IllegalStateException(); if (groupId == null) throw new IllegalStateException();
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Blog b = blogManager.getBlog(groupId); Blog b = blogManager.getBlog(groupId);
blogManager.removeBlog(b); blogManager.removeBlog(b);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Removing blog", start);
if (LOG.isLoggable(INFO))
LOG.info("Removing blog took " + duration + " ms");
handler.onResult(null); handler.onResult(null);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -205,8 +201,7 @@ class BlogControllerImpl extends BaseControllerImpl
for (Contact c : contacts) contactIds.add(c.getId()); for (Contact c : contacts) contactIds.add(c.getId());
handler.onResult(contactIds); handler.onResult(contactIds);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
handler.onException(e); handler.onException(e);
} }
}); });

View File

@@ -11,7 +11,7 @@ import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageButton;
import android.widget.TextView; import android.widget.TextView;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
@@ -40,7 +40,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
private final ViewGroup layout; private final ViewGroup layout;
private final AuthorView reblogger; private final AuthorView reblogger;
private final AuthorView author; private final AuthorView author;
private final ImageView reblogButton; private final ImageButton reblogButton;
private final TextView body; private final TextView body;
private final ViewGroup commentContainer; private final ViewGroup commentContainer;
private final boolean fullText; private final boolean fullText;

View File

@@ -26,8 +26,10 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -99,22 +101,19 @@ class FeedControllerImpl extends BaseControllerImpl
ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) { ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Collection<BlogPostItem> posts = new ArrayList<>(); Collection<BlogPostItem> posts = new ArrayList<>();
for (Blog b : blogManager.getBlogs()) { for (Blog b : blogManager.getBlogs()) {
try { try {
posts.addAll(loadItems(b.getId())); posts.addAll(loadItems(b.getId()));
} catch (NoSuchGroupException | NoSuchMessageException e) { } catch (NoSuchGroupException | NoSuchMessageException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
} }
} }
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading all posts", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading all posts took " + duration + " ms");
handler.onResult(posts); handler.onResult(posts);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -125,15 +124,13 @@ class FeedControllerImpl extends BaseControllerImpl
ResultExceptionHandler<Blog, DbException> handler) { ResultExceptionHandler<Blog, DbException> handler) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Author a = identityManager.getLocalAuthor(); Author a = identityManager.getLocalAuthor();
Blog b = blogManager.getPersonalBlog(a); Blog b = blogManager.getPersonalBlog(a);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading personal blog", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading blog took " + duration + " ms");
handler.onResult(b); handler.onResult(b);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
handler.onException(e); handler.onException(e);
} }
}); });

View File

@@ -30,6 +30,7 @@ import javax.inject.Inject;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
public class RssFeedImportActivity extends BriarActivity { public class RssFeedImportActivity extends BriarActivity {
@@ -124,7 +125,7 @@ public class RssFeedImportActivity extends BriarActivity {
feedManager.addFeed(url); feedManager.addFeed(url);
feedImported(); feedImported();
} catch (DbException | IOException e) { } catch (DbException | IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
importFailed(); importFailed();
} }
}); });

View File

@@ -27,6 +27,7 @@ import javax.inject.Inject;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.support.design.widget.Snackbar.LENGTH_LONG; import static android.support.design.widget.Snackbar.LENGTH_LONG;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
public class RssFeedManageActivity extends BriarActivity public class RssFeedManageActivity extends BriarActivity
implements RssFeedListener { implements RssFeedListener {
@@ -123,7 +124,7 @@ public class RssFeedManageActivity extends BriarActivity
try { try {
displayFeeds(revision, feedManager.getFeeds()); displayFeeds(revision, feedManager.getFeeds());
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
onLoadError(); onLoadError();
} }
}); });
@@ -148,7 +149,7 @@ public class RssFeedManageActivity extends BriarActivity
feedManager.removeFeed(feed); feedManager.removeFeed(feed);
onFeedDeleted(feed); onFeedDeleted(feed);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
onDeleteError(); onDeleteError();
} }
}); });

View File

@@ -34,6 +34,7 @@ import javax.inject.Inject;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH; import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
public class WriteBlogPostActivity extends BriarActivity public class WriteBlogPostActivity extends BriarActivity
@@ -142,16 +143,16 @@ public class WriteBlogPostActivity extends BriarActivity
private void storePost(String body) { private void storePost(String body) {
runOnDbThread(() -> { runOnDbThread(() -> {
long now = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
try { try {
LocalAuthor author = identityManager.getLocalAuthor(); LocalAuthor author = identityManager.getLocalAuthor();
BlogPost p = blogPostFactory BlogPost p = blogPostFactory
.createBlogPost(groupId, now, null, author, body); .createBlogPost(groupId, timestamp, null, author, body);
blogManager.addLocalPost(p); blogManager.addLocalPost(p);
postPublished(); postPublished();
} catch (DbException | GeneralSecurityException } catch (DbException | GeneralSecurityException
| FormatException e) { | FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
postFailedToPublish(); postFailedToPublish();
} }
}); });

View File

@@ -33,7 +33,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener; import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity; import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.client.BaseMessageHeader; import org.briarproject.briar.api.client.BaseMessageHeader;
@@ -59,8 +59,10 @@ import javax.inject.Inject;
import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation; import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
import static android.support.v4.view.ViewCompat.getTransitionName; import static android.support.v4.view.ViewCompat.getTransitionName;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID; import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -163,7 +165,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_add_contact: case R.id.action_add_contact:
Intent intent = Intent intent =
new Intent(getContext(), KeyAgreementActivity.class); new Intent(getContext(), ContactExchangeActivity.class);
startActivity(intent); startActivity(intent);
return true; return true;
default: default:
@@ -194,7 +196,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
int revision = adapter.getRevision(); int revision = adapter.getRevision();
listener.runOnDbThread(() -> { listener.runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
List<ContactListItem> contacts = new ArrayList<>(); List<ContactListItem> contacts = new ArrayList<>();
for (Contact c : contactManager.getActiveContacts()) { for (Contact c : contactManager.getActiveContacts()) {
try { try {
@@ -208,12 +210,10 @@ public class ContactListFragment extends BaseFragment implements EventListener {
// Continue // Continue
} }
} }
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Full load", start);
if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms");
displayContacts(revision, contacts); displayContacts(revision, contacts);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -106,6 +106,9 @@ import static android.support.v7.util.SortedList.INVALID_POSITION;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRODUCTION; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRODUCTION;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName; import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
@@ -290,21 +293,19 @@ public class ConversationActivity extends BriarActivity
private void loadContactDetailsAndMessages() { private void loadContactDetailsAndMessages() {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
if (contactName == null || contactAuthorId == null) { if (contactName == null || contactAuthorId == null) {
Contact contact = contactManager.getContact(contactId); Contact contact = contactManager.getContact(contactId);
contactName = contact.getAuthor().getName(); contactName = contact.getAuthor().getName();
contactAuthorId = contact.getAuthor().getId(); contactAuthorId = contact.getAuthor().getId();
} }
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading contact", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading contact took " + duration + " ms");
loadMessages(); loadMessages();
displayContactDetails(); displayContactDetails();
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
finishOnUiThread(); finishOnUiThread();
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -340,7 +341,7 @@ public class ConversationActivity extends BriarActivity
int revision = adapter.getRevision(); int revision = adapter.getRevision();
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Collection<PrivateMessageHeader> headers = Collection<PrivateMessageHeader> headers =
messagingManager.getMessageHeaders(contactId); messagingManager.getMessageHeaders(contactId);
Collection<IntroductionMessage> introductions = Collection<IntroductionMessage> introductions =
@@ -357,14 +358,12 @@ public class ConversationActivity extends BriarActivity
invitations.addAll(forumInvitations); invitations.addAll(forumInvitations);
invitations.addAll(blogInvitations); invitations.addAll(blogInvitations);
invitations.addAll(groupInvitations); invitations.addAll(groupInvitations);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading messages", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading messages took " + duration + " ms");
displayMessages(revision, headers, introductions, invitations); displayMessages(revision, headers, introductions, invitations);
} catch (NoSuchContactException e) { } catch (NoSuchContactException e) {
finishOnUiThread(); finishOnUiThread();
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -438,14 +437,12 @@ public class ConversationActivity extends BriarActivity
private void loadMessageBody(MessageId m) { private void loadMessageBody(MessageId m) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
String body = messagingManager.getMessageBody(m); String body = messagingManager.getMessageBody(m);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading body", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading body took " + duration + " ms");
displayMessageBody(m, body); displayMessageBody(m, body);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -669,7 +666,7 @@ public class ConversationActivity extends BriarActivity
messagingManager.getConversationId(contactId); messagingManager.getConversationId(contactId);
createMessage(body, timestamp); createMessage(body, timestamp);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
@@ -689,11 +686,9 @@ public class ConversationActivity extends BriarActivity
private void storeMessage(PrivateMessage m, String body) { private void storeMessage(PrivateMessage m, String body) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
messagingManager.addLocalMessage(m); messagingManager.addLocalMessage(m);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Storing message", start);
if (LOG.isLoggable(INFO))
LOG.info("Storing message took " + duration + " ms");
Message message = m.getMessage(); Message message = m.getMessage();
PrivateMessageHeader h = new PrivateMessageHeader( PrivateMessageHeader h = new PrivateMessageHeader(
message.getId(), message.getGroupId(), message.getId(), message.getGroupId(),
@@ -703,7 +698,7 @@ public class ConversationActivity extends BriarActivity
bodyCache.put(message.getId(), body); bodyCache.put(message.getId(), body);
addConversationItem(item); addConversationItem(item);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -726,7 +721,7 @@ public class ConversationActivity extends BriarActivity
try { try {
contactManager.removeContact(contactId); contactManager.removeContact(contactId);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} finally { } finally {
finishAfterContactRemoved(); finishAfterContactRemoved();
} }
@@ -755,7 +750,7 @@ public class ConversationActivity extends BriarActivity
} }
} }
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -803,7 +798,7 @@ public class ConversationActivity extends BriarActivity
settings.putBoolean(SHOW_ONBOARDING_INTRODUCTION, false); settings.putBoolean(SHOW_ONBOARDING_INTRODUCTION, false);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -816,13 +811,11 @@ public class ConversationActivity extends BriarActivity
private void markMessageRead(GroupId g, MessageId m) { private void markMessageRead(GroupId g, MessageId m) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
messagingManager.setReadFlag(g, m, true); messagingManager.setReadFlag(g, m, true);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Marking read", start);
if (LOG.isLoggable(INFO))
LOG.info("Marking read took " + duration + " ms");
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -860,10 +853,10 @@ public class ConversationActivity extends BriarActivity
loadMessages(); loadMessages();
} catch (ProtocolStateException e) { } catch (ProtocolStateException e) {
// Action is no longer valid - reloading should solve the issue // Action is no longer valid - reloading should solve the issue
if (LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e); logException(LOG, INFO, e);
} catch (DbException e) { } catch (DbException e) {
// TODO show an error message // TODO show an error message
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -19,6 +19,7 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
@@ -53,7 +54,7 @@ public abstract class ContactSelectorControllerImpl
} }
handler.onResult(contacts); handler.onResult(contacts);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
handler.onException(e); handler.onException(e);
} }
}); });

View File

@@ -21,6 +21,7 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting; import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
@@ -101,8 +102,7 @@ public class BriarControllerImpl implements BriarController {
boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true); boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true);
handler.onResult(ask); handler.onResult(ask);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
} }
}); });
} }
@@ -115,8 +115,7 @@ public class BriarControllerImpl implements BriarController {
settings.putBoolean(DOZE_ASK_AGAIN, false); settings.putBoolean(DOZE_ASK_AGAIN, false);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) logException(LOG, WARNING, e);
LOG.log(WARNING, e.toString(), e);
} }
}); });
} }

View File

@@ -20,6 +20,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
public class ConfigControllerImpl implements ConfigController { public class ConfigControllerImpl implements ConfigController {
@@ -89,7 +90,7 @@ public class ConfigControllerImpl implements ConfigController {
reader.close(); reader.close();
return key; return key;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} }
} }
@@ -137,7 +138,7 @@ public class ConfigControllerImpl implements ConfigController {
LOG.info("Stored second copy of database key in backup file"); LOG.info("Stored second copy of database key in backup file");
return true; return true;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return false; return false;
} }
} }

View File

@@ -28,8 +28,10 @@ import javax.inject.Inject;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -122,14 +124,12 @@ public class CreateForumActivity extends BriarActivity {
private void storeForum(String name) { private void storeForum(String name) {
runOnDbThread(() -> { runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Forum f = forumManager.addForum(name); Forum f = forumManager.addForum(name);
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Storing forum", start);
if (LOG.isLoggable(INFO))
LOG.info("Storing forum took " + duration + " ms");
displayForum(f); displayForum(f);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
finishOnUiThread(); finishOnUiThread();
} }
}); });

View File

@@ -39,6 +39,7 @@ import javax.inject.Inject;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class ForumControllerImpl extends class ForumControllerImpl extends
@@ -130,7 +131,7 @@ class ForumControllerImpl extends
for (Contact c : contacts) contactIds.add(c.getId()); for (Contact c : contacts) contactIds.add(c.getId());
handler.onResult(contactIds); handler.onResult(contactIds);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
handler.onException(e); handler.onException(e);
} }
}); });
@@ -150,7 +151,7 @@ class ForumControllerImpl extends
parentItem.getId() : null; parentItem.getId() : null;
createMessage(body, timestamp, parentId, author, handler); createMessage(body, timestamp, parentId, author, handler);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
handler.onException(e); handler.onException(e);
} }
}); });

View File

@@ -2,7 +2,6 @@ package org.briarproject.briar.android.forum;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -55,12 +54,8 @@ class ForumListAdapter
ui.postCount.setText(ctx.getResources() ui.postCount.setText(ctx.getResources()
.getQuantityString(R.plurals.posts, postCount, .getQuantityString(R.plurals.posts, postCount,
postCount)); postCount));
ui.postCount.setTextColor(
ContextCompat.getColor(ctx, R.color.briar_text_secondary));
} else { } else {
ui.postCount.setText(ctx.getString(R.string.no_posts)); ui.postCount.setText(ctx.getString(R.string.no_posts));
ui.postCount.setTextColor(
ContextCompat.getColor(ctx, R.color.briar_text_tertiary));
} }
// Date // Date

View File

@@ -44,8 +44,10 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE; import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID; import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -157,7 +159,7 @@ public class ForumListFragment extends BaseEventFragment implements
int revision = adapter.getRevision(); int revision = adapter.getRevision();
listener.runOnDbThread(() -> { listener.runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
Collection<ForumListItem> forums = new ArrayList<>(); Collection<ForumListItem> forums = new ArrayList<>();
for (Forum f : forumManager.getForums()) { for (Forum f : forumManager.getForums()) {
try { try {
@@ -168,12 +170,10 @@ public class ForumListFragment extends BaseEventFragment implements
// Continue // Continue
} }
} }
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Full load", start);
if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms");
displayForums(revision, forums); displayForums(revision, forums);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -194,14 +194,12 @@ public class ForumListFragment extends BaseEventFragment implements
private void loadAvailableForums() { private void loadAvailableForums() {
listener.runOnDbThread(() -> { listener.runOnDbThread(() -> {
try { try {
long now = System.currentTimeMillis(); long start = now();
int available = forumSharingManager.getInvitations().size(); int available = forumSharingManager.getInvitations().size();
long duration = System.currentTimeMillis() - now; logDuration(LOG, "Loading available", start);
if (LOG.isLoggable(INFO))
LOG.info("Loading available took " + duration + " ms");
displayAvailableForums(available); displayAvailableForums(available);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -29,6 +29,7 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID; import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
public class ContactChooserFragment extends BaseFragment { public class ContactChooserFragment extends BaseFragment {
@@ -129,7 +130,7 @@ public class ContactChooserFragment extends BaseFragment {
} }
displayContacts(contacts); displayContacts(contacts);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }

View File

@@ -36,6 +36,7 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH; import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
public class IntroductionMessageFragment extends BaseFragment public class IntroductionMessageFragment extends BaseFragment
@@ -129,7 +130,7 @@ public class IntroductionMessageFragment extends BaseFragment
boolean possible = introductionManager.canIntroduce(c1, c2); boolean possible = introductionManager.canIntroduce(c1, c2);
setUpViews(c1, c2, possible); setUpViews(c1, c2, possible);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -204,7 +205,7 @@ public class IntroductionMessageFragment extends BaseFragment
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
introductionManager.makeIntroduction(c1, c2, msg, timestamp); introductionManager.makeIntroduction(c1, c2, msg, timestamp);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
introductionError(); introductionError();
} }
}); });

View File

@@ -9,10 +9,12 @@ import android.hardware.Camera.Size;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Display;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.WindowManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -21,6 +23,7 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import static android.content.Context.WINDOW_SERVICE;
import static android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK; import static android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK;
import static android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT; import static android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT;
import static android.hardware.Camera.Parameters.FLASH_MODE_OFF; import static android.hardware.Camera.Parameters.FLASH_MODE_OFF;
@@ -35,6 +38,7 @@ import static android.hardware.Camera.Parameters.SCENE_MODE_BARCODE;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -96,7 +100,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
} }
@UiThread @UiThread
public void start(int rotationDegrees) throws CameraException { public void start() throws CameraException {
LOG.info("Opening camera"); LOG.info("Opening camera");
try { try {
int cameras = Camera.getNumberOfCameras(); int cameras = Camera.getNumberOfCameras();
@@ -121,7 +125,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw new CameraException(e); throw new CameraException(e);
} }
setDisplayOrientation(rotationDegrees); setDisplayOrientation(getScreenRotationDegrees());
// Use barcode scene mode if it's available // Use barcode scene mode if it's available
Parameters params = camera.getParameters(); Parameters params = camera.getParameters();
params = setSceneMode(camera, params); params = setSceneMode(camera, params);
@@ -156,6 +160,27 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
camera = null; camera = null;
} }
/**
* See {@link Camera#setDisplayOrientation(int)}.
*/
private int getScreenRotationDegrees() {
WindowManager wm =
(WindowManager) getContext().getSystemService(WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
switch (d.getRotation()) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
default:
throw new AssertionError();
}
}
@UiThread @UiThread
private void startPreview(SurfaceHolder holder) throws CameraException { private void startPreview(SurfaceHolder holder) throws CameraException {
LOG.info("Starting preview"); LOG.info("Starting preview");
@@ -408,7 +433,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try { try {
surfaceCreatedUi(holder); surfaceCreatedUi(holder);
} catch (CameraException e) { } catch (CameraException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -430,7 +455,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try { try {
surfaceChangedUi(holder, w, h); surfaceChangedUi(holder, w, h);
} catch (CameraException e) { } catch (CameraException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
}); });
} }
@@ -488,7 +513,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try { try {
startAutoFocus(); startAutoFocus();
} catch (CameraException e) { } catch (CameraException e) {
LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
} }
} }

View File

@@ -0,0 +1,144 @@
package org.briarproject.briar.android.keyagreement;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.R.string;
import org.briarproject.briar.android.activity.ActivityComponent;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ContactExchangeActivity extends KeyAgreementActivity implements
ContactExchangeListener {
private static final Logger LOG =
Logger.getLogger(ContactExchangeActivity.class.getName());
// Fields that are accessed from background threads must be volatile
@Inject
volatile ContactExchangeTask contactExchangeTask;
@Inject
volatile IdentityManager identityManager;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
getSupportActionBar().setTitle(string.add_contact_title);
}
private void startContactExchange(KeyAgreementResult result) {
runOnDbThread(() -> {
LocalAuthor localAuthor;
// Load the local pseudonym
try {
localAuthor = identityManager.getLocalAuthor();
} catch (DbException e) {
logException(LOG, WARNING, e);
contactExchangeFailed();
return;
}
// Exchange contact details
contactExchangeTask.startExchange(ContactExchangeActivity.this,
localAuthor, result.getMasterKey(),
result.getConnection(), result.getTransportId(),
result.wasAlice());
});
}
@Override
public void contactExchangeSucceeded(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(string.contact_added_toast);
String text = String.format(format, contactName);
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
.show();
supportFinishAfterTransition();
});
}
@Override
public void duplicateContact(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(string.contact_already_exists);
String text = String.format(format, contactName);
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
.show();
finish();
});
}
@Override
public void contactExchangeFailed() {
runOnUiThreadUnlessDestroyed(() -> {
Toast.makeText(ContactExchangeActivity.this,
string.contact_exchange_failed, LENGTH_LONG).show();
finish();
});
}
@UiThread
@Override
public void keyAgreementFailed() {
// TODO show failure somewhere persistent?
Toast.makeText(this, R.string.connection_failed,
LENGTH_LONG).show();
}
@UiThread
@Override
public String keyAgreementWaiting() {
return getString(R.string.waiting_for_contact_to_scan);
}
@UiThread
@Override
public String keyAgreementStarted() {
return getString(R.string.authenticating_with_device);
}
@UiThread
@Override
public String keyAgreementAborted(boolean remoteAborted) {
// TODO show abort somewhere persistent?
Toast.makeText(this,
remoteAborted ? R.string.connection_aborted_remote :
R.string.connection_aborted_local, LENGTH_LONG)
.show();
return null;
}
@UiThread
@Override
public String keyAgreementFinished(KeyAgreementResult result) {
startContactExchange(result);
return getString(string.exchanging_contact_details);
}
}

View File

@@ -16,17 +16,7 @@ import android.support.v7.widget.Toolbar;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent; import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
@@ -53,15 +43,14 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_ENABLE_BLUETOOTH; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_ENABLE_BLUETOOTH;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class KeyAgreementActivity extends BriarActivity implements public abstract class KeyAgreementActivity extends BriarActivity implements
BaseFragmentListener, IntroScreenSeenListener, EventListener, BaseFragmentListener, IntroScreenSeenListener,
ContactExchangeListener { KeyAgreementFragment.KeyAgreementEventListener {
private enum BluetoothState { private enum BluetoothState {
UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED
@@ -73,12 +62,6 @@ public class KeyAgreementActivity extends BriarActivity implements
@Inject @Inject
EventBus eventBus; EventBus eventBus;
// Fields that are accessed from background threads must be volatile
@Inject
volatile ContactExchangeTask contactExchangeTask;
@Inject
volatile IdentityManager identityManager;
private boolean isResumed = false, enableWasRequested = false; private boolean isResumed = false, enableWasRequested = false;
private boolean continueClicked, gotCameraPermission; private boolean continueClicked, gotCameraPermission;
private BluetoothState bluetoothState = BluetoothState.UNKNOWN; private BluetoothState bluetoothState = BluetoothState.UNKNOWN;
@@ -94,13 +77,9 @@ public class KeyAgreementActivity extends BriarActivity implements
public void onCreate(@Nullable Bundle state) { public void onCreate(@Nullable Bundle state) {
super.onCreate(state); super.onCreate(state);
setContentView(R.layout.activity_fragment_container_toolbar); setContentView(R.layout.activity_fragment_container_toolbar);
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.add_contact_title);
if (state == null) { if (state == null) {
showInitialFragment(IntroFragment.newInstance()); showInitialFragment(IntroFragment.newInstance());
} }
@@ -115,18 +94,6 @@ public class KeyAgreementActivity extends BriarActivity implements
if (bluetoothReceiver != null) unregisterReceiver(bluetoothReceiver); if (bluetoothReceiver != null) unregisterReceiver(bluetoothReceiver);
} }
@Override
public void onStart() {
super.onStart();
eventBus.addListener(this);
}
@Override
protected void onStop() {
super.onStop();
eventBus.removeListener(this);
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@@ -147,7 +114,7 @@ public class KeyAgreementActivity extends BriarActivity implements
if (canShowQrCodeFragment()) showQrCodeFragment(); if (canShowQrCodeFragment()) showQrCodeFragment();
} }
boolean canShowQrCodeFragment() { private boolean canShowQrCodeFragment() {
return isResumed && continueClicked return isResumed && continueClicked
&& (SDK_INT < 23 || gotCameraPermission) && (SDK_INT < 23 || gotCameraPermission)
&& bluetoothState != BluetoothState.UNKNOWN && bluetoothState != BluetoothState.UNKNOWN
@@ -206,10 +173,11 @@ public class KeyAgreementActivity extends BriarActivity implements
} }
private void showQrCodeFragment() { private void showQrCodeFragment() {
continueClicked = false;
// FIXME #824 // FIXME #824
FragmentManager fm = getSupportFragmentManager(); FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(ShowQrCodeFragment.TAG) == null) { if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
BaseFragment f = ShowQrCodeFragment.newInstance(); BaseFragment f = KeyAgreementFragment.newInstance();
fm.beginTransaction() fm.beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag()) .replace(R.id.fragmentContainer, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag()) .addToBackStack(f.getUniqueTag())
@@ -279,69 +247,6 @@ public class KeyAgreementActivity extends BriarActivity implements
} }
} }
@Override
public void eventOccurred(Event e) {
if (e instanceof KeyAgreementFinishedEvent) {
KeyAgreementFinishedEvent event = (KeyAgreementFinishedEvent) e;
keyAgreementFinished(event.getResult());
}
}
private void keyAgreementFinished(KeyAgreementResult result) {
runOnUiThreadUnlessDestroyed(() -> startContactExchange(result));
}
private void startContactExchange(KeyAgreementResult result) {
runOnDbThread(() -> {
LocalAuthor localAuthor;
// Load the local pseudonym
try {
localAuthor = identityManager.getLocalAuthor();
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
contactExchangeFailed();
return;
}
// Exchange contact details
contactExchangeTask.startExchange(KeyAgreementActivity.this,
localAuthor, result.getMasterKey(),
result.getConnection(), result.getTransportId(),
result.wasAlice());
});
}
@Override
public void contactExchangeSucceeded(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(string.contact_added_toast);
String text = String.format(format, contactName);
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
});
}
@Override
public void duplicateContact(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(string.contact_already_exists);
String text = String.format(format, contactName);
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG).show();
finish();
});
}
@Override
public void contactExchangeFailed() {
runOnUiThreadUnlessDestroyed(() -> {
Toast.makeText(KeyAgreementActivity.this,
string.contact_exchange_failed, LENGTH_LONG).show();
finish();
});
}
private class BluetoothStateReceiver extends BroadcastReceiver { private class BluetoothStateReceiver extends BroadcastReceiver {
@Override @Override

View File

@@ -2,18 +2,12 @@ package org.briarproject.briar.android.keyagreement;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams; import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView; import android.widget.TextView;
@@ -24,6 +18,7 @@ import com.google.zxing.Result;
import org.briarproject.bramble.api.UnsupportedVersionException; import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask; import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.Payload; import org.briarproject.bramble.api.keyagreement.Payload;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder; import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
@@ -36,11 +31,13 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent; import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseEventFragment; import org.briarproject.briar.android.fragment.BaseEventFragment;
import org.briarproject.briar.android.fragment.ErrorFragment; import org.briarproject.briar.android.fragment.ErrorFragment;
import org.briarproject.briar.android.view.QrCodeView;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@@ -59,13 +56,14 @@ import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ShowQrCodeFragment extends BaseEventFragment public class KeyAgreementFragment extends BaseEventFragment
implements QrCodeDecoder.ResultCallback { implements QrCodeDecoder.ResultCallback, QrCodeView.FullscreenListener {
static final String TAG = ShowQrCodeFragment.class.getName(); static final String TAG = KeyAgreementFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG); private static final Logger LOG = Logger.getLogger(TAG);
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
@@ -83,26 +81,29 @@ public class ShowQrCodeFragment extends BaseEventFragment
EventBus eventBus; EventBus eventBus;
private CameraView cameraView; private CameraView cameraView;
private LinearLayout cameraOverlay;
private View statusView; private View statusView;
private QrCodeView qrCodeView;
private TextView status; private TextView status;
private ImageView qrCode;
private TextView mainProgressTitle;
private ViewGroup mainProgressContainer;
private boolean fullscreen = false;
private boolean gotRemotePayload; private boolean gotRemotePayload;
private volatile boolean gotLocalPayload; private volatile boolean gotLocalPayload;
private KeyAgreementTask task; private KeyAgreementTask task;
private KeyAgreementEventListener listener;
public static ShowQrCodeFragment newInstance() { public static KeyAgreementFragment newInstance() {
Bundle args = new Bundle(); Bundle args = new Bundle();
KeyAgreementFragment fragment = new KeyAgreementFragment();
ShowQrCodeFragment fragment = new ShowQrCodeFragment();
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (KeyAgreementEventListener) context;
}
@Override @Override
public void injectFragment(ActivityComponent component) { public void injectFragment(ActivityComponent component) {
component.inject(this); component.inject(this);
@@ -118,7 +119,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
public View onCreateView(LayoutInflater inflater, public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_keyagreement_qr, container, return inflater.inflate(R.layout.fragment_keyagreement_qr, container,
false); false);
} }
@@ -126,47 +126,17 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
cameraView = view.findViewById(R.id.camera_view); cameraView = view.findViewById(R.id.camera_view);
cameraOverlay = view.findViewById(R.id.camera_overlay);
statusView = view.findViewById(R.id.status_container); statusView = view.findViewById(R.id.status_container);
status = view.findViewById(R.id.connect_status); status = view.findViewById(R.id.connect_status);
qrCode = view.findViewById(R.id.qr_code); qrCodeView = view.findViewById(R.id.qr_code_view);
mainProgressTitle = view.findViewById(R.id.title_progress_bar); qrCodeView.setFullscreenListener(this);
mainProgressContainer = view.findViewById(R.id.container_progress);
ImageView fullscreenButton = view.findViewById(R.id.fullscreen_button);
fullscreenButton.setOnClickListener(v -> {
View qrCodeContainer = view.findViewById(R.id.qr_code_container);
LinearLayout cameraOverlay = view.findViewById(R.id.camera_overlay);
LayoutParams statusParams, qrCodeParams;
if (fullscreen) {
// Shrink the QR code container to fill half its parent
if (cameraOverlay.getOrientation() == HORIZONTAL) {
statusParams = new LayoutParams(0, MATCH_PARENT, 1f);
qrCodeParams = new LayoutParams(0, MATCH_PARENT, 1f);
} else {
statusParams = new LayoutParams(MATCH_PARENT, 0, 1f);
qrCodeParams = new LayoutParams(MATCH_PARENT, 0, 1f);
}
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_black_48dp);
} else {
// Grow the QR code container to fill its parent
statusParams = new LayoutParams(0, 0, 0f);
qrCodeParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f);
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_exit_black_48dp);
}
statusView.setLayoutParams(statusParams);
qrCodeContainer.setLayoutParams(qrCodeParams);
cameraOverlay.invalidate();
fullscreen = !fullscreen;
});
} }
@Override @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
cameraView.setPreviewConsumer(new QrCodeDecoder(this)); cameraView.setPreviewConsumer(new QrCodeDecoder(this));
} }
@@ -175,30 +145,33 @@ public class ShowQrCodeFragment extends BaseEventFragment
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
try { try {
cameraView.start(getScreenRotationDegrees()); cameraView.start();
} catch (CameraException e) { } catch (CameraException e) {
logCameraExceptionAndFinish(e); logCameraExceptionAndFinish(e);
} }
startListening(); startListening();
} }
/** @Override
* See {@link Camera#setDisplayOrientation(int)}. public void setFullscreen(boolean fullscreen) {
*/ LinearLayout.LayoutParams statusParams, qrCodeParams;
private int getScreenRotationDegrees() { if (fullscreen) {
Display d = getActivity().getWindowManager().getDefaultDisplay(); // Grow the QR code view to fill its parent
switch (d.getRotation()) { statusParams = new LayoutParams(0, 0, 0f);
case Surface.ROTATION_0: qrCodeParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f);
return 0; } else {
case Surface.ROTATION_90: // Shrink the QR code view to fill half its parent
return 90; if (cameraOverlay.getOrientation() == HORIZONTAL) {
case Surface.ROTATION_180: statusParams = new LayoutParams(0, MATCH_PARENT, 1f);
return 180; qrCodeParams = new LayoutParams(0, MATCH_PARENT, 1f);
case Surface.ROTATION_270: } else {
return 270; statusParams = new LayoutParams(MATCH_PARENT, 0, 1f);
default: qrCodeParams = new LayoutParams(MATCH_PARENT, 0, 1f);
throw new AssertionError(); }
} }
statusView.setLayoutParams(statusParams);
qrCodeView.setLayoutParams(qrCodeParams);
cameraOverlay.invalidate();
} }
@Override @Override
@@ -214,7 +187,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
@UiThread @UiThread
private void logCameraExceptionAndFinish(CameraException e) { private void logCameraExceptionAndFinish(CameraException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
Toast.makeText(getActivity(), R.string.camera_error, Toast.makeText(getActivity(), R.string.camera_error,
LENGTH_LONG).show(); LENGTH_LONG).show();
finish(); finish();
@@ -244,7 +217,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
// If we've stopped the camera view, restart it // If we've stopped the camera view, restart it
if (gotRemotePayload) { if (gotRemotePayload) {
try { try {
cameraView.start(getScreenRotationDegrees()); cameraView.start();
} catch (CameraException e) { } catch (CameraException e) {
logCameraExceptionAndFinish(e); logCameraExceptionAndFinish(e);
return; return;
@@ -278,7 +251,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
} catch (CameraException e) { } catch (CameraException e) {
logCameraExceptionAndFinish(e); logCameraExceptionAndFinish(e);
} catch (IOException | IllegalArgumentException e) { } catch (IOException | IllegalArgumentException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, "QR Code Invalid", e); LOG.log(WARNING, "QR Code Invalid", e);
reset(); reset();
Toast.makeText(getActivity(), R.string.qr_code_invalid, Toast.makeText(getActivity(), R.string.qr_code_invalid,
LENGTH_LONG).show(); LENGTH_LONG).show();
@@ -301,82 +274,60 @@ public class ShowQrCodeFragment extends BaseEventFragment
KeyAgreementAbortedEvent event = (KeyAgreementAbortedEvent) e; KeyAgreementAbortedEvent event = (KeyAgreementAbortedEvent) e;
keyAgreementAborted(event.didRemoteAbort()); keyAgreementAborted(event.didRemoteAbort());
} else if (e instanceof KeyAgreementFinishedEvent) { } else if (e instanceof KeyAgreementFinishedEvent) {
runOnUiThreadUnlessDestroyed(() -> { keyAgreementFinished(((KeyAgreementFinishedEvent) e).getResult());
mainProgressContainer.setVisibility(VISIBLE);
mainProgressTitle.setText(R.string.exchanging_contact_details);
});
} }
} }
@UiThread
private void generateBitmapQR(Payload payload) {
// Get narrowest screen dimension
Context context = getContext();
if (context == null) return;
DisplayMetrics dm = context.getResources().getDisplayMetrics();
new AsyncTask<Void, Void, Bitmap>() {
@Override
@Nullable
protected Bitmap doInBackground(Void... params) {
byte[] payloadBytes = payloadEncoder.encode(payload);
if (LOG.isLoggable(INFO)) {
LOG.info("Local payload is " + payloadBytes.length
+ " bytes");
}
// Use ISO 8859-1 to encode bytes directly as a string
String content = new String(payloadBytes, ISO_8859_1);
return QrCodeUtils.createQrCode(dm, content);
}
@Override
protected void onPostExecute(@Nullable Bitmap bitmap) {
if (bitmap != null && !isDetached()) {
qrCode.setImageBitmap(bitmap);
// Simple fade-in animation
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200);
qrCode.startAnimation(anim);
}
}
}.execute();
}
private void setQrCode(Payload localPayload) {
runOnUiThreadUnlessDestroyed(() -> generateBitmapQR(localPayload));
}
private void keyAgreementFailed() { private void keyAgreementFailed() {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
reset(); reset();
// TODO show failure somewhere persistent? listener.keyAgreementFailed();
Toast.makeText(getActivity(), R.string.connection_failed,
LENGTH_LONG).show();
}); });
} }
private void keyAgreementWaiting() { private void keyAgreementWaiting() {
runOnUiThreadUnlessDestroyed( runOnUiThreadUnlessDestroyed(
() -> status.setText(R.string.waiting_for_contact_to_scan)); () -> status.setText(listener.keyAgreementWaiting()));
} }
private void keyAgreementStarted() { private void keyAgreementStarted() {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
mainProgressContainer.setVisibility(VISIBLE); qrCodeView.setVisibility(INVISIBLE);
mainProgressTitle.setText(R.string.authenticating_with_device); statusView.setVisibility(VISIBLE);
status.setText(listener.keyAgreementStarted());
}); });
} }
private void keyAgreementAborted(boolean remoteAborted) { private void keyAgreementAborted(boolean remoteAborted) {
runOnUiThreadUnlessDestroyed(() -> { runOnUiThreadUnlessDestroyed(() -> {
reset(); reset();
mainProgressContainer.setVisibility(INVISIBLE); qrCodeView.setVisibility(VISIBLE);
mainProgressTitle.setText(""); statusView.setVisibility(INVISIBLE);
// TODO show abort somewhere persistent? status.setText(listener.keyAgreementAborted(remoteAborted));
Toast.makeText(getActivity(), });
remoteAborted ? R.string.connection_aborted_remote : }
R.string.connection_aborted_local, LENGTH_LONG)
.show(); private void keyAgreementFinished(KeyAgreementResult result) {
runOnUiThreadUnlessDestroyed(() -> {
statusView.setVisibility(VISIBLE);
status.setText(listener.keyAgreementFinished(result));
});
}
private void setQrCode(Payload localPayload) {
Context context = getContext();
if (context == null) return;
DisplayMetrics dm = context.getResources().getDisplayMetrics();
ioExecutor.execute(() -> {
byte[] payloadBytes = payloadEncoder.encode(localPayload);
if (LOG.isLoggable(INFO)) {
LOG.info("Local payload is " + payloadBytes.length
+ " bytes");
}
// Use ISO 8859-1 to encode bytes directly as a string
String content = new String(payloadBytes, ISO_8859_1);
Bitmap qrCode = QrCodeUtils.createQrCode(dm, content);
runOnUiThreadUnlessDestroyed(() -> qrCodeView.setQrCode(qrCode));
}); });
} }
@@ -394,4 +345,31 @@ public class ShowQrCodeFragment extends BaseEventFragment
protected void finish() { protected void finish() {
getActivity().getSupportFragmentManager().popBackStack(); getActivity().getSupportFragmentManager().popBackStack();
} }
@NotNullByDefault
interface KeyAgreementEventListener {
@UiThread
void keyAgreementFailed();
// Should return a string to be displayed as status.
@UiThread
@Nullable
String keyAgreementWaiting();
// Should return a string to be displayed as status.
@UiThread
@Nullable
String keyAgreementStarted();
// Should return a string to be displayed as status.
@UiThread
@Nullable
String keyAgreementAborted(boolean remoteAborted);
// Should return a string to be displayed as status.
@UiThread
@Nullable
String keyAgreementFinished(KeyAgreementResult result);
}
} }

View File

@@ -18,6 +18,7 @@ import static android.graphics.Color.BLACK;
import static android.graphics.Color.WHITE; import static android.graphics.Color.WHITE;
import static com.google.zxing.BarcodeFormat.QR_CODE; import static com.google.zxing.BarcodeFormat.QR_CODE;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class QrCodeUtils { class QrCodeUtils {
@@ -34,7 +35,7 @@ class QrCodeUtils {
smallestDimen, smallestDimen); smallestDimen, smallestDimen);
return renderQrCode(encoded); return renderQrCode(encoded);
} catch (WriterException e) { } catch (WriterException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); logException(LOG, WARNING, e);
return null; return null;
} }
} }

View File

@@ -42,6 +42,22 @@ public class BriefLogFormatter extends Formatter {
tag = tag.substring(tag.lastIndexOf('.') + 1); tag = tag.substring(tag.lastIndexOf('.') + 1);
sb.append(tag).append(": "); sb.append(tag).append(": ");
sb.append(record.getMessage()); sb.append(record.getMessage());
Throwable t = record.getThrown();
if (t != null) {
sb.append('\n');
appendThrowable(sb, t);
}
return sb.toString(); return sb.toString();
} }
private void appendThrowable(StringBuilder sb, Throwable t) {
sb.append(t);
for (StackTraceElement e : t.getStackTrace())
sb.append("\n at ").append(e);
Throwable cause = t.getCause();
if (cause != null) {
sb.append("\n Caused by: ");
appendThrowable(sb, cause);
}
}
} }

View File

@@ -16,6 +16,8 @@ import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.os.Build.VERSION.SDK_INT;
@UiThread @UiThread
@NotNullByDefault @NotNullByDefault
class HuaweiView extends PowerView { class HuaweiView extends PowerView {
@@ -45,6 +47,8 @@ class HuaweiView extends PowerView {
} }
public static boolean needsToBeShown(Context context) { public static boolean needsToBeShown(Context context) {
// "Protected apps" no longer exists on Huawei EMUI 5.0 (Android 7.0)
if (SDK_INT >= 24) return false;
PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(), List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(),
PackageManager.MATCH_DEFAULT_ONLY); PackageManager.MATCH_DEFAULT_ONLY);

Some files were not shown because too many files have changed in this diff Show More