Compare commits

...

114 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
5e679e7a10 Don't show Huawei protected apps button on API 24+. 2018-05-31 09:48:38 +01:00
290 changed files with 3716 additions and 2106 deletions

View File

@@ -21,11 +21,7 @@ test:
test_reproducible:
image: briar/reproducer:latest
script:
- cd /opt/briar-reproducer
- ./reproduce.py ${CI_COMMIT_REF_NAME}
- "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"
only:
- tags

View File

@@ -8,9 +8,11 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10006
versionName "1.0.6"
versionCode 10011
versionName "1.0.11"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
compileOptions {
@@ -31,36 +33,42 @@ dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
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 {
verify = [
'com.android.tools.analytics-library:protos:26.1.2:protos-26.1.2.jar:52672a0b42b572a06aecc3535d5068eb46c0e15d129b9f1085d3c16a1da5cdbb',
'com.android.tools.analytics-library:shared:26.1.2:shared-26.1.2.jar:5c7e0eda18c6f87feeb83628c707e8aaa3298b41fb72e38efe31ad1675f9e8e9',
'com.android.tools.analytics-library:tracker:26.1.2:tracker-26.1.2.jar:06f97aa0adf44ffb06f8681c6a79d9be153a08f61d21eddc42b8d3db96df4282',
'com.android.tools.build:apksig:3.1.2:apksig-3.1.2.jar:40696a4559124d1d57873d208857eee059d48859239d569c7d18374ac644a8be',
'com.android.tools.build:builder-model:3.1.2:builder-model-3.1.2.jar:d49bfa2a135c9562b6ca7aa4342036cfa1582c7074c2d1d93d1dae8b3a134e17',
'com.android.tools.build:builder-test-api:3.1.2:builder-test-api-3.1.2.jar:dfe2a50b740d41b11189101062434d4283d18647e89a492ad51710c719363e9f',
'com.android.tools.build:builder:3.1.2:builder-3.1.2.jar:b60f825a42e2efe8433619fbc759f3d9effecab718279048d36881188ceb1d14',
'com.android.tools.build:gradle-api:3.1.2:gradle-api-3.1.2.jar:e58bcc5b893e4583ab0f5c8ef89c4dbcce202b405a9d7fcc116d21e5357d4893',
'com.android.tools.build:manifest-merger:26.1.2:manifest-merger-26.1.2.jar:9c61c27ea5266573107b954acf1216d398f4d7e7ae6fad6409d6b2b767eb091c',
'com.android.tools.ddms:ddmlib:26.1.2:ddmlib-26.1.2.jar:18a2a5fbef36882f07d03c2b9e59eba05cf8248177bf5cbff736e4b582804c44',
'com.android.tools.external.com-intellij:intellij-core:26.1.2:intellij-core-26.1.2.jar:37c5acf279f1ae3e85b1a5be3c9f15f43bde7b08f978eefefffb9c4035760c52',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.2:kotlin-compiler-26.1.2.jar:152df0bee7580326c77316b669a9d96e3b09efb1d45f545dce4147271b0b8944',
'com.android.tools.external.org-jetbrains:uast:26.1.2:uast-26.1.2.jar:02d39582206d3f5fc0a6cb18bfd9e8b9f9c1acb805ec6dac08b4e3a56849d279',
'com.android.tools.layoutlib:layoutlib-api:26.1.2:layoutlib-api-26.1.2.jar:20220039fcc7d799f928153beff862e704457c0f55ab44258f3745ebeb662b4f',
'com.android.tools.lint:lint-api:26.1.2:lint-api-26.1.2.jar:e1d5b62b870a7c566e9877a6b96b27784a4d713f8caa07fdcb4705d47a40a1d9',
'com.android.tools.lint:lint-checks:26.1.2:lint-checks-26.1.2.jar:211e2afd58504372385d71b1e5be982c2b5121ab6fee1c04ddabeb75a8729e07',
'com.android.tools.lint:lint-gradle-api:26.1.2:lint-gradle-api-26.1.2.jar:71284f2a8b03c3e55c94511c9eb36f8184fbb85324325fc6b78abf5183f03d90',
'com.android.tools.lint:lint-gradle:26.1.2:lint-gradle-26.1.2.jar:855f0c82b7fc690df1b7319c0774f7517f7f8f5dd4eee1f6077dcf50e07c6240',
'com.android.tools.lint:lint-kotlin:26.1.2:lint-kotlin-26.1.2.jar:1e591f70bcbbc11569720a9bbcca2bc1f3d4f789f01f40f642848d920643d484',
'com.android.tools.lint:lint:26.1.2:lint-26.1.2.jar:93736c62e9f1976998c2b4aa716aea0734cdb162d05502f4af7292654aedb182',
'com.android.tools:annotations:26.1.2:annotations-26.1.2.jar:72773dcaf5c4ccca828e3c8467f1b78a8a00b3cc5f8ad1aab88fcf9379928018',
'com.android.tools:common:26.1.2:common-26.1.2.jar:ea4320f0c17dcbc4491896bb705c4d25ec08bd62ef02ab0579fe154e75e788e6',
'com.android.tools:dvlib:26.1.2:dvlib-26.1.2.jar:1187aa4fb666595c96c4deb6bc0e0f4b7e396bde9f6243330b49a232946130ea',
'com.android.tools:repository:26.1.2:repository-26.1.2.jar:8b86e512ad6d32bd76989451eefe2b271f5efce6d4d65ecb173afaf14606e01a',
'com.android.tools:sdk-common:26.1.2:sdk-common-26.1.2.jar:23584720a60a21cdcb5b1ec10269e3013789d6805d153cc696c39ec7ce251896',
'com.android.tools:sdklib:26.1.2:sdklib-26.1.2.jar:d3870fafc59ab8efa70d3f9649f40ee299c8ec5b58377b06e8853d7272a5bf4e',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'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.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'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.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'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.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'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.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'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;
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 javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module(includes = {
AndroidSystemModule.class
})
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_ON;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -145,7 +146,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
try {
if (ss != null) ss.close();
} 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 {
if (c != null) c.close();
} 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.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.FileObserver;
import android.os.PowerManager;
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.settings.Settings;
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.util.IoUtils;
import org.briarproject.bramble.util.RenewableWakeLock;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
@@ -49,13 +50,14 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
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.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
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.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
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.ID;
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_PORT;
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;
@MethodsNotNullByDefault
@@ -102,8 +105,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
};
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}");
// This tag may prevent Huawei's power manager from killing us
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName());
@@ -112,14 +118,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Context appContext;
private final LocationUtils locationUtils;
private final SocketFactory torSocketFactory;
private final Clock clock;
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final String architecture;
private final CircumventionProvider circumventionProvider;
private final int maxLatency, maxIdleTime, socketTimeout;
private final ConnectionStatus connectionStatus;
private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile;
private final PowerManager.WakeLock wakeLock;
private final RenewableWakeLock wakeLock;
private final AtomicReference<Future<?>> connectivityCheck =
new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -132,17 +140,19 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, LocationUtils locationUtils,
SocketFactory torSocketFactory, Backoff backoff,
SocketFactory torSocketFactory, Clock clock, Backoff backoff,
DuplexPluginCallback callback, String architecture,
int maxLatency, int maxIdleTime) {
CircumventionProvider circumventionProvider, int maxLatency, int maxIdleTime) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext;
this.locationUtils = locationUtils;
this.torSocketFactory = torSocketFactory;
this.clock = clock;
this.backoff = backoff;
this.callback = callback;
this.architecture = architecture;
this.circumventionProvider = circumventionProvider;
this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime;
if (maxIdleTime > Integer.MAX_VALUE / 2)
@@ -155,14 +165,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done");
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
connectionStatusExecutor = new PoliteExecutor("TorPlugin",
ioExecutor, 1);
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
}
@Override
@@ -185,18 +194,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (used.getAndSet(true)) throw new IllegalStateException();
// Install or update the assets if necessary
if (!assetsAreUpToDate()) installAssets();
LOG.info("Starting Tor");
// Watch for the auth cookie file being updated
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();
if (cookieFile.exists() && !cookieFile.delete())
LOG.warning("Old auth cookie not deleted");
// Start a new Tor process
LOG.info("Starting Tor");
String torPath = torFile.getAbsolutePath();
String configPath = configFile.getAbsolutePath();
String pid = String.valueOf(android.os.Process.myPid());
@@ -235,11 +236,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
throw new PluginException();
}
// Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException();
long start = clock.currentTimeMillis();
while (cookieFile.length() < 32) {
if (clock.currentTimeMillis() - start > COOKIE_TIMEOUT_MS) {
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) {
LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt();
@@ -347,7 +353,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try {
if (c != null) c.close();
} 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 {
if (s != null) s.close();
} 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();
if (children != null) for (File child : children) listFiles(child);
} 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.bind(new InetSocketAddress("127.0.0.1", port));
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
tryToClose(ss);
return;
}
@@ -423,7 +429,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try {
if (ss != null) ss.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
} finally {
callback.transportDisabled();
}
@@ -442,7 +448,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
response = controlConnection.addOnion(portLines);
else response = controlConnection.addOnion(privKey, portLines);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return;
}
if (!response.containsKey(HS_ADDRESS)) {
@@ -488,12 +494,23 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void enableNetwork(boolean enable) throws IOException {
if (!running) return;
if (enable) wakeLock.acquire();
if (enable && USE_TOR_WAKE_LOCK) wakeLock.acquire();
connectionStatus.enableNetwork(enable);
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
if (!enable) {
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");
controlSocket.close();
} 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
@@ -641,22 +658,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
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
public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) {
@@ -677,8 +678,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
boolean online = net != null && net.isConnected();
boolean wifi = online && net.getType() == TYPE_WIFI;
String country = locationUtils.getCurrentCountry();
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
country);
boolean blocked =
circumventionProvider.isTorProbablyBlocked(country);
Settings s = callback.getSettings();
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
@@ -692,19 +693,26 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (!online) {
LOG.info("Disabling network, device is offline");
enableNetwork(false);
} else if (blocked) {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting");
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 {
LOG.info("Enabling network");
enableBridges(false);
enableNetwork(true);
}
} 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.DuplexPluginCallback;
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.util.AndroidUtils;
@@ -42,11 +43,15 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final EventBus eventBus;
private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory;
private final CircumventionProvider circumventionProvider;
private final Clock clock;
public TorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext,
LocationUtils locationUtils, EventBus eventBus,
SocketFactory torSocketFactory, BackoffFactory backoffFactory) {
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
CircumventionProvider circumventionProvider,
Clock clock) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext;
@@ -54,6 +59,8 @@ public class TorPluginFactory implements DuplexPluginFactory {
this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory;
this.circumventionProvider = circumventionProvider;
this.clock = clock;
}
@Override
@@ -90,8 +97,8 @@ public class TorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext,
locationUtils, torSocketFactory, backoff, callback,
architecture, MAX_LATENCY, MAX_IDLE_TIME);
locationUtils, torSocketFactory, clock, backoff, callback,
architecture, circumventionProvider, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(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
* for annotating methods that should run on the UI executor.
* for annotating methods that should run on the IO executor.
* <p>
* The contract of this executor is that tasks may be run concurrently, and
* 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.Queue;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
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}
@@ -20,8 +20,6 @@ import static java.util.logging.Level.FINE;
@NotNullByDefault
public class PoliteExecutor implements Executor {
private static final Level LOG_LEVEL = FINE;
private final Object lock = new Object();
@GuardedBy("lock")
private final Queue<Runnable> queue = new LinkedList<>();
@@ -49,11 +47,11 @@ public class PoliteExecutor implements Executor {
@Override
public void execute(Runnable r) {
long submitted = System.currentTimeMillis();
long submitted = now();
Runnable wrapped = () -> {
if (log.isLoggable(LOG_LEVEL)) {
long queued = System.currentTimeMillis() - submitted;
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
if (log.isLoggable(FINE)) {
long queued = now() - submitted;
log.fine("Queue time " + queued + " ms");
}
try {
r.run();

View File

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

View File

@@ -46,6 +46,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
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.util.LogUtils.logException;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -122,7 +123,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
tryToClose(conn);
return;
@@ -133,7 +134,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
try {
localProperties = transportPropertyManager.getLocalProperties();
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
tryToClose(conn);
return;
@@ -194,7 +195,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
LOG.info("End of stream");
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
tryToClose(conn);
return;
@@ -222,11 +223,11 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
LOG.info("Pseudonym exchange succeeded");
listener.contactExchangeSucceeded(remoteInfo.author);
} catch (ContactExistsException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
tryToClose(conn);
listener.duplicateContact(remoteInfo.author);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
tryToClose(conn);
listener.contactExchangeFailed();
}
@@ -307,7 +308,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
conn.getReader().dispose(true, true);
conn.getWriter().dispose(true);
} 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 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
class CryptoComponentImpl implements CryptoComponent {
@@ -127,16 +129,14 @@ class CryptoComponentImpl implements CryptoComponent {
throw new IllegalArgumentException();
if (!(pub instanceof Curve25519PublicKey))
throw new IllegalArgumentException();
long now = System.currentTimeMillis();
long start = now();
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
priv.getEncoded());
// If the shared secret is all zeroes, the public key is invalid
byte allZero = 0;
for (byte b : secret) allZero |= b;
if (allZero == 0) throw new GeneralSecurityException();
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Deriving shared secret took " + duration + " ms");
logDuration(LOG, "Deriving shared secret", start);
return secret;
}

View File

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

View File

@@ -16,7 +16,8 @@ import java.util.logging.Logger;
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
@@ -48,7 +49,7 @@ class Sec1KeyParser implements KeyParser {
throws GeneralSecurityException {
// 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
long now = System.currentTimeMillis();
long start = now();
if (encodedKey.length != publicKeyBytes)
throw new GeneralSecurityException();
// 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
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
PublicKey p = new Sec1PublicKey(k);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Parsing public key took " + duration + " ms");
logDuration(LOG, "Parsing public key", start);
return p;
}
@Override
public PrivateKey parsePrivateKey(byte[] encodedKey)
throws GeneralSecurityException {
long now = System.currentTimeMillis();
long start = now();
if (encodedKey.length != privateKeyBytes)
throw new GeneralSecurityException();
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
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
PrivateKey p = new Sec1PrivateKey(k, keyBits);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Parsing private key took " + duration + " ms");
logDuration(LOG, "Parsing private key", start);
return p;
}
}

View File

@@ -68,13 +68,15 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.FINE;
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.SHARED;
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.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
@NotNullByDefault
@@ -108,7 +110,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
try {
close();
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
});
return reopened;
@@ -125,13 +127,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
// Don't allow reentrant locking
if (lock.getReadHoldCount() > 0) throw new IllegalStateException();
if (lock.getWriteHoldCount() > 0) throw new IllegalStateException();
long start = System.currentTimeMillis();
if (readOnly) lock.readLock().lock();
else lock.writeLock().lock();
if (LOG.isLoggable(FINE)) {
long duration = System.currentTimeMillis() - start;
if (readOnly) LOG.fine("Waited " + duration + " ms for read lock");
else LOG.fine("Waited " + duration + " ms for write lock");
long start = now();
if (readOnly) {
lock.readLock().lock();
logDuration(LOG, "Waiting for read lock", start);
} else {
lock.writeLock().lock();
logDuration(LOG, "Waiting for write lock", start);
}
try {
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.SCHEMA_VERSION_KEY;
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
@@ -404,7 +405,7 @@ abstract class JdbcDatabase implements Database<Connection> {
try {
if (rs != null) rs.close();
} 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 {
if (s != null) s.close();
} 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) {
// Try to close the connection
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
try {
txn.close();
} catch (SQLException e1) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e1.toString(), e1);
logException(LOG, WARNING, e1);
}
// Whatever happens, allow the database to close
connectionsLock.lock();

View File

@@ -10,6 +10,7 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
class Migration38_39 implements Migration<Connection> {
@@ -48,7 +49,7 @@ class Migration38_39 implements Migration<Connection> {
try {
if (s != null) s.close();
} 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.WARNING;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
class KeyAgreementConnector {
@@ -134,7 +135,7 @@ class KeyAgreementConnector {
Thread.currentThread().interrupt();
return null;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return null;
} finally {
stopListening();

View File

@@ -28,6 +28,7 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -120,13 +121,11 @@ class KeyAgreementTaskImpl extends Thread implements KeyAgreementTask,
// Broadcast result to caller
eventBus.broadcast(new KeyAgreementFinishedEvent(result));
} catch (AbortException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
// Notify caller that the protocol was aborted
eventBus.broadcast(new KeyAgreementAbortedEvent(e.receivedAbort));
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
// Notify caller that the connection failed
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.CONFIRM;
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.
@@ -72,7 +73,7 @@ class KeyAgreementTransport {
try {
writeRecord(ABORT, new byte[0]);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
exception = true;
}
tryToClose(exception);
@@ -83,7 +84,7 @@ class KeyAgreementTransport {
kac.getConnection().getReader().dispose(exception, true);
kac.getConnection().getWriter().dispose(exception);
} 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.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
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.SERVICE_ERROR;
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
@NotNullByDefault
@@ -101,24 +105,20 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
}
private LocalAuthor createLocalAuthor(String nickname) {
long now = System.currentTimeMillis();
long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
LocalAuthor localAuthor = authorFactory
.createLocalAuthor(nickname, publicKey, privateKey);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Creating local author took " + duration + " ms");
logDuration(LOG, "Creating local author", start);
return localAuthor;
}
private void registerLocalAuthor(LocalAuthor author) throws DbException {
long now = System.currentTimeMillis();
long start = now();
identityManager.registerLocalAuthor(author);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Registering local author took " + duration + " ms");
logDuration(LOG, "Registering local author", start);
}
@Override
@@ -129,15 +129,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
}
try {
LOG.info("Starting services");
long start = System.currentTimeMillis();
long start = now();
boolean reopened = db.open(this);
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
if (reopened)
LOG.info("Reopening database took " + duration + " ms");
else LOG.info("Creating database took " + duration + " ms");
}
if (reopened) logDuration(LOG, "Reopening database", start);
else logDuration(LOG, "Creating database", start);
if (nickname != null) {
registerLocalAuthor(createLocalAuthor(nickname));
@@ -150,13 +146,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
Transaction txn = db.startTransaction(false);
try {
for (Client c : clients) {
start = System.currentTimeMillis();
start = now();
c.createLocalState(txn);
duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Starting client "
+ c.getClass().getSimpleName()
+ " took " + duration + " ms");
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting client "
+ c.getClass().getSimpleName(), start);
}
}
db.commitTransaction(txn);
@@ -164,12 +158,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
db.endTransaction(txn);
}
for (Service s : services) {
start = System.currentTimeMillis();
start = now();
s.startService();
duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Starting service " + s.getClass().getSimpleName()
+ " took " + duration + " ms");
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting service "
+ s.getClass().getSimpleName(), start);
}
}
@@ -178,16 +171,16 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
eventBus.broadcast(new LifecycleEvent(RUNNING));
return SUCCESS;
} catch (DataTooOldException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return DATA_TOO_OLD_ERROR;
} catch (DataTooNewException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return DATA_TOO_NEW_ERROR;
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return DB_ERROR;
} catch (ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return SERVICE_ERROR;
} finally {
startStopSemaphore.release();
@@ -213,29 +206,26 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
state = STOPPING;
eventBus.broadcast(new LifecycleEvent(STOPPING));
for (Service s : services) {
long start = System.currentTimeMillis();
long start = now();
s.stopService();
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Stopping service " + s.getClass().getSimpleName()
+ " took " + duration + " ms");
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Stopping service "
+ s.getClass().getSimpleName(), start);
}
}
for (ExecutorService e : executors) {
if (LOG.isLoggable(INFO)) {
LOG.info("Stopping executor "
if (LOG.isLoggable(FINE)) {
LOG.fine("Stopping executor "
+ e.getClass().getSimpleName());
}
e.shutdownNow();
}
long start = System.currentTimeMillis();
long start = now();
db.close();
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO))
LOG.info("Closing database took " + duration + " ms");
logDuration(LOG, "Closing database", start);
shutdownLatch.countDown();
} catch (DbException | ServiceException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
} finally {
startStopSemaphore.release();
}

View File

@@ -27,6 +27,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.util.LogUtils.logException;
class ConnectionManagerImpl implements ConnectionManager {
@@ -135,7 +136,7 @@ class ConnectionManagerImpl implements ConnectionManager {
byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, false);
return;
}
@@ -151,7 +152,7 @@ class ConnectionManagerImpl implements ConnectionManager {
createIncomingSession(ctx, reader).run();
disposeReader(false, true);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, true);
} finally {
connectionRegistry.unregisterConnection(contactId, transportId,
@@ -163,7 +164,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try {
reader.dispose(exception, recognised);
} 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 {
ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
return;
}
@@ -204,7 +205,7 @@ class ConnectionManagerImpl implements ConnectionManager {
createSimplexOutgoingSession(ctx, writer).run();
disposeWriter(false);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
} finally {
connectionRegistry.unregisterConnection(contactId, transportId,
@@ -216,7 +217,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try {
writer.dispose(exception);
} 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);
ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, false);
return;
}
@@ -265,7 +266,7 @@ class ConnectionManagerImpl implements ConnectionManager {
incomingSession.run();
disposeReader(false, true);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, true);
} finally {
connectionRegistry.unregisterConnection(contactId, transportId,
@@ -279,7 +280,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try {
ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
return;
}
@@ -294,7 +295,7 @@ class ConnectionManagerImpl implements ConnectionManager {
outgoingSession.run();
disposeWriter(false);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
}
}
@@ -305,7 +306,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try {
reader.dispose(exception, recognised);
} 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 {
writer.dispose(exception);
} 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 {
ctx = keyManager.getStreamContext(contactId, transportId);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
return;
}
@@ -364,7 +365,7 @@ class ConnectionManagerImpl implements ConnectionManager {
outgoingSession.run();
disposeWriter(false);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeWriter(true);
}
}
@@ -376,7 +377,7 @@ class ConnectionManagerImpl implements ConnectionManager {
byte[] tag = readTag(reader);
ctx = keyManager.getStreamContext(transportId, tag);
} catch (IOException | DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, false);
return;
}
@@ -400,7 +401,7 @@ class ConnectionManagerImpl implements ConnectionManager {
incomingSession.run();
disposeReader(false, true);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
disposeReader(true, true);
} finally {
connectionRegistry.unregisterConnection(contactId, transportId,
@@ -414,7 +415,7 @@ class ConnectionManagerImpl implements ConnectionManager {
try {
reader.dispose(exception, recognised);
} 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 {
writer.dispose(exception);
} 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.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
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
@NotNullByDefault
@@ -205,17 +209,16 @@ class PluginManagerImpl implements PluginManager, Service {
@Override
public void run() {
try {
long start = System.currentTimeMillis();
long start = now();
plugin.start();
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Starting plugin " + plugin.getId() + " took " +
duration + " ms");
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting plugin " + plugin.getId(),
start);
}
} catch (PluginException e) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not start");
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
} finally {
startLatch.countDown();
@@ -243,12 +246,11 @@ class PluginManagerImpl implements PluginManager, Service {
// Wait for the plugin to finish starting
startLatch.await();
// Stop the plugin
long start = System.currentTimeMillis();
long start = now();
plugin.stop();
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Stopping plugin " + plugin.getId()
+ " took " + duration + " ms");
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Stopping plugin " + plugin.getId(),
start);
}
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for plugin to stop");
@@ -256,7 +258,7 @@ class PluginManagerImpl implements PluginManager, Service {
} catch (PluginException e) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not stop");
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
} finally {
stopLatch.countDown();
@@ -278,7 +280,7 @@ class PluginManagerImpl implements PluginManager, Service {
try {
return settingsManager.getSettings(id.getString());
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return new Settings();
}
}
@@ -288,7 +290,7 @@ class PluginManagerImpl implements PluginManager, Service {
try {
return transportPropertyManager.getLocalProperties(id);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return new TransportProperties();
}
}
@@ -298,7 +300,7 @@ class PluginManagerImpl implements PluginManager, Service {
try {
settingsManager.mergeSettings(s, id.getString());
} 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 {
transportPropertyManager.mergeLocalProperties(id, p);
} 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.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
@@ -134,7 +135,7 @@ class Poller implements EventListener {
if (w != null)
connectionManager.manageOutgoingConnection(c, t, w);
} 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)
connectionManager.manageOutgoingConnection(c, t, d);
} 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);
if (!remote.isEmpty()) p.poll(remote);
} 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.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
@ThreadSafe
@@ -92,7 +93,7 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
conn.getWriter().dispose(false);
conn.getReader().dispose(false, false);
} 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_UUID;
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;
@MethodsNotNullByDefault
@@ -169,7 +170,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
try {
ss = openServerSocket(contactConnectionsUuid);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return;
}
if (!isRunning() || !shouldAllowContactConnections()) {
@@ -336,7 +337,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
try {
ss = openServerSocket(uuid);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return null;
}
if (!isRunning()) {

View File

@@ -15,6 +15,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
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;
@NotNullByDefault
@@ -51,7 +52,7 @@ abstract class FilePlugin implements SimplexPlugin {
FileInputStream in = new FileInputStream(file);
return new FileTransportReader(file, in, this);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return null;
}
}
@@ -70,7 +71,7 @@ abstract class FilePlugin implements SimplexPlugin {
FileOutputStream out = new FileOutputStream(file);
return new FileTransportWriter(file, out, this);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return null;
}
}

View File

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

View File

@@ -9,6 +9,7 @@ import java.io.OutputStream;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
class FileTransportWriter implements TransportConnectionWriter {
@@ -46,7 +47,7 @@ class FileTransportWriter implements TransportConnectionWriter {
try {
out.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
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.PROP_IP_PORTS;
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;
@NotNullByDefault
@@ -295,7 +296,7 @@ class LanTcpPlugin extends TcpPlugin {
try {
ss.close();
} 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.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
@ThreadSafe
@@ -59,7 +60,7 @@ class PortMapperImpl implements PortMapper {
if (externalString != null)
external = InetAddress.getByName(externalString);
} 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);
}
@@ -76,7 +77,7 @@ class PortMapperImpl implements PortMapper {
try {
d.discover();
} catch (IOException | SAXException | ParserConfigurationException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
gateway = d.getValidGateway();
}
@@ -87,7 +88,7 @@ class PortMapperImpl implements PortMapper {
if (LOG.isLoggable(INFO))
LOG.info("Deleted mapping for port " + port);
} 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.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
@MethodsNotNullByDefault
@@ -152,7 +153,7 @@ abstract class TcpPlugin implements DuplexPlugin {
try {
if (ss != null) ss.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
} finally {
callback.transportDisabled();
}
@@ -306,7 +307,7 @@ abstract class TcpPlugin implements DuplexPlugin {
try {
ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return Collections.emptyList();
}
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.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -78,7 +79,7 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
Thread.currentThread().interrupt();
running = false;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
running = false;
}
});

View File

@@ -32,6 +32,7 @@ import javax.inject.Inject;
import javax.net.SocketFactory;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable
@NotNullByDefault
@@ -132,7 +133,7 @@ class DevReporterImpl implements DevReporter, EventListener {
try {
if (c != null) c.close();
} 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 {
if (s != null) s.close();
} 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.record.Record.MAX_RECORD_PAYLOAD_BYTES;
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
@@ -240,7 +241,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated ack: " + (a != null));
if (a != null) writerTasks.add(new WriteAck(a));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -287,7 +288,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated batch: " + (b != null));
if (b != null) writerTasks.add(new WriteBatch(b));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -334,7 +335,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated offer: " + (o != null));
if (o != null) writerTasks.add(new WriteOffer(o));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -379,7 +380,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
LOG.info("Generated request: " + (r != null));
if (r != null) writerTasks.add(new WriteRequest(r));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}

View File

@@ -28,6 +28,7 @@ import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
import static org.briarproject.bramble.util.LogUtils.logException;
/**
* An incoming {@link SyncSession}.
@@ -127,7 +128,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -153,7 +154,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -179,7 +180,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -205,7 +206,7 @@ class IncomingSession implements SyncSession, EventListener {
db.endTransaction(txn);
}
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
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.record.Record.MAX_RECORD_PAYLOAD_BYTES;
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
@@ -139,7 +140,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
if (a == null) decrementOutstandingQueries();
else writerTasks.add(new WriteAck(a));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
interrupt();
}
}
@@ -184,7 +185,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
if (b == null) decrementOutstandingQueries();
else writerTasks.add(new WriteBatch(b));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
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.INVALID;
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
@@ -110,7 +111,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
}
validateNextMessageAsync(unvalidated);
} 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");
validateNextMessageAsync(unvalidated);
} 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);
} 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");
deliverNextPendingMessageAsync(pending);
} 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(),
g.getMajorVersion(), context);
} catch (InvalidMessageException e) {
if (LOG.isLoggable(INFO))
LOG.log(INFO, e.toString(), e);
logException(LOG, INFO, e);
Queue<MessageId> invalidate = new LinkedList<>();
invalidate.add(m.getId());
invalidateNextMessageAsync(invalidate);
@@ -326,7 +326,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
} catch (NoSuchGroupException e) {
LOG.info("Group removed during validation");
} 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);
} 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");
shareNextMessageAsync(toShare);
} 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");
invalidateNextMessageAsync(invalidate);
} 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) {
LOG.info("Group removed before validation");
} 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 static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable
@NotNullByDefault
@@ -49,7 +50,7 @@ class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
out.close();
} catch (IOException e) {
// 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 static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
public class LinuxSecureRandomSpi extends SecureRandomSpi {
@@ -39,7 +40,7 @@ public class LinuxSecureRandomSpi extends SecureRandomSpi {
out.close();
} catch (IOException e) {
// 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.TAG_LENGTH;
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
@@ -169,7 +170,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
db.endTransaction(txn);
}
} 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_TYPE_MAPPER;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
@@ -141,7 +142,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
user32.DispatchMessage(msg);
}
} 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 static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isValidMac;
@MethodsNotNullByDefault
@@ -85,7 +86,7 @@ class JavaBluetoothPlugin extends BluetoothPlugin<StreamConnectionNotifier> {
try {
if (ss != null) ss.close();
} 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 jssc.SerialPort.PURGE_RXCLEAR;
import static jssc.SerialPort.PURGE_TXCLEAR;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -136,7 +137,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try {
if (port != null) port.closePort();
} 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) {
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 {
answer();
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, 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.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -81,7 +82,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
running = true;
return;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
}
throw new PluginException();
@@ -94,7 +95,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try {
modem.stop();
} 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);
return true;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
}
running = false;
@@ -157,7 +158,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try {
if (!modem.dial(number)) return null;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
resetModem();
return null;
}
@@ -209,7 +210,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
try {
modem.hangUp();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
exception = true;
}
if (exception) resetModem();

View File

@@ -4,3 +4,4 @@ build
local.properties
.settings
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.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-annotations'
}
@@ -61,7 +61,7 @@ dependencyVerification {
'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',
'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',
'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',
@@ -82,32 +82,32 @@ dependencyVerification {
'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: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:shared:26.1.2:shared-26.1.2.jar:5c7e0eda18c6f87feeb83628c707e8aaa3298b41fb72e38efe31ad1675f9e8e9',
'com.android.tools.analytics-library:tracker:26.1.2:tracker-26.1.2.jar:06f97aa0adf44ffb06f8681c6a79d9be153a08f61d21eddc42b8d3db96df4282',
'com.android.tools.build:apksig:3.1.2:apksig-3.1.2.jar:40696a4559124d1d57873d208857eee059d48859239d569c7d18374ac644a8be',
'com.android.tools.build:builder-model:3.1.2:builder-model-3.1.2.jar:d49bfa2a135c9562b6ca7aa4342036cfa1582c7074c2d1d93d1dae8b3a134e17',
'com.android.tools.build:builder-test-api:3.1.2:builder-test-api-3.1.2.jar:dfe2a50b740d41b11189101062434d4283d18647e89a492ad51710c719363e9f',
'com.android.tools.build:builder:3.1.2:builder-3.1.2.jar:b60f825a42e2efe8433619fbc759f3d9effecab718279048d36881188ceb1d14',
'com.android.tools.build:gradle-api:3.1.2:gradle-api-3.1.2.jar:e58bcc5b893e4583ab0f5c8ef89c4dbcce202b405a9d7fcc116d21e5357d4893',
'com.android.tools.build:manifest-merger:26.1.2:manifest-merger-26.1.2.jar:9c61c27ea5266573107b954acf1216d398f4d7e7ae6fad6409d6b2b767eb091c',
'com.android.tools.ddms:ddmlib:26.1.2:ddmlib-26.1.2.jar:18a2a5fbef36882f07d03c2b9e59eba05cf8248177bf5cbff736e4b582804c44',
'com.android.tools.external.com-intellij:intellij-core:26.1.2:intellij-core-26.1.2.jar:37c5acf279f1ae3e85b1a5be3c9f15f43bde7b08f978eefefffb9c4035760c52',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.2:kotlin-compiler-26.1.2.jar:152df0bee7580326c77316b669a9d96e3b09efb1d45f545dce4147271b0b8944',
'com.android.tools.external.org-jetbrains:uast:26.1.2:uast-26.1.2.jar:02d39582206d3f5fc0a6cb18bfd9e8b9f9c1acb805ec6dac08b4e3a56849d279',
'com.android.tools.layoutlib:layoutlib-api:26.1.2:layoutlib-api-26.1.2.jar:20220039fcc7d799f928153beff862e704457c0f55ab44258f3745ebeb662b4f',
'com.android.tools.lint:lint-api:26.1.2:lint-api-26.1.2.jar:e1d5b62b870a7c566e9877a6b96b27784a4d713f8caa07fdcb4705d47a40a1d9',
'com.android.tools.lint:lint-checks:26.1.2:lint-checks-26.1.2.jar:211e2afd58504372385d71b1e5be982c2b5121ab6fee1c04ddabeb75a8729e07',
'com.android.tools.lint:lint-gradle-api:26.1.2:lint-gradle-api-26.1.2.jar:71284f2a8b03c3e55c94511c9eb36f8184fbb85324325fc6b78abf5183f03d90',
'com.android.tools.lint:lint-gradle:26.1.2:lint-gradle-26.1.2.jar:855f0c82b7fc690df1b7319c0774f7517f7f8f5dd4eee1f6077dcf50e07c6240',
'com.android.tools.lint:lint-kotlin:26.1.2:lint-kotlin-26.1.2.jar:1e591f70bcbbc11569720a9bbcca2bc1f3d4f789f01f40f642848d920643d484',
'com.android.tools.lint:lint:26.1.2:lint-26.1.2.jar:93736c62e9f1976998c2b4aa716aea0734cdb162d05502f4af7292654aedb182',
'com.android.tools:annotations:26.1.2:annotations-26.1.2.jar:72773dcaf5c4ccca828e3c8467f1b78a8a00b3cc5f8ad1aab88fcf9379928018',
'com.android.tools:common:26.1.2:common-26.1.2.jar:ea4320f0c17dcbc4491896bb705c4d25ec08bd62ef02ab0579fe154e75e788e6',
'com.android.tools:dvlib:26.1.2:dvlib-26.1.2.jar:1187aa4fb666595c96c4deb6bc0e0f4b7e396bde9f6243330b49a232946130ea',
'com.android.tools:repository:26.1.2:repository-26.1.2.jar:8b86e512ad6d32bd76989451eefe2b271f5efce6d4d65ecb173afaf14606e01a',
'com.android.tools:sdk-common:26.1.2:sdk-common-26.1.2.jar:23584720a60a21cdcb5b1ec10269e3013789d6805d153cc696c39ec7ce251896',
'com.android.tools:sdklib:26.1.2:sdklib-26.1.2.jar:d3870fafc59ab8efa70d3f9649f40ee299c8ec5b58377b06e8853d7272a5bf4e',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'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.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'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.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'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.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'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.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',
@@ -238,15 +238,16 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10006
versionName "1.0.6"
versionCode 10011
versionName "1.0.11"
applicationId "org.briarproject.briar.android"
resValue "string", "app_package", "org.briarproject.briar.android"
resValue "string", "app_name", "Briar"
buildConfigField "String", "GitHash",
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
def now = (long) (System.currentTimeMillis() / 1000)
buildConfigField "Long", "BuildTimestamp",
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], 0)}000L"
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
}
buildTypes {
@@ -260,7 +261,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
release {
shrinkResources true
shrinkResources false
minifyEnabled true
crunchPngs false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
@@ -284,3 +285,46 @@ android {
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.VIBRATE" />
<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"/>
<application
@@ -24,6 +25,14 @@
android:logo="@mipmap/ic_launcher_round"
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
android:name="org.briarproject.briar.android.BriarService"
android:exported="false">
@@ -44,7 +53,6 @@
android:finishOnTaskLaunch="true"
android:label="@string/crash_report_title"
android:launchMode="singleInstance"
android:process=":briar_error_handler"
android:theme="@style/BriarTheme.NoActionBar"
android:windowSoftInputMode="stateHidden">
</activity>
@@ -301,7 +309,7 @@
</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:theme="@style/BriarTheme.NoActionBar"
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">

View File

@@ -150,6 +150,8 @@ public interface AndroidComponent
@IoExecutor
Executor ioExecutor();
void inject(BootReceiver briarService);
void inject(BriarService briarService);
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_SOCIAL;
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.contact.ConversationActivity.CONTACT_ID;
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,
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 Logger LOG =
@@ -265,8 +259,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
try {
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, 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.reporting.DevConfig;
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.Scheduler;
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
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.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.ReferenceManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor;
import java.io.File;
@@ -97,14 +98,15 @@ public class AppModule {
@Scheduler ScheduledExecutorService scheduler,
AndroidExecutor androidExecutor, SecureRandom random,
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, LocationUtils locationUtils, EventBus eventBus) {
Application app, LocationUtils locationUtils, EventBus eventBus,
CircumventionProvider circumventionProvider, Clock clock) {
Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth =
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler,
appContext, locationUtils, eventBus,
torSocketFactory, backoffFactory);
appContext, locationUtils, eventBus, torSocketFactory,
backoffFactory, circumventionProvider, clock);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
scheduler, backoffFactory, appContext);
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
@@ -163,12 +165,6 @@ public class AppModule {
return app.getSharedPreferences("db", MODE_PRIVATE);
}
@Provides
@Singleton
ReferenceManager provideReferenceManager() {
return new ReferenceManagerImpl();
}
@Provides
@Singleton
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.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.os.StrictMode.VmPolicy;
import android.preference.PreferenceManager;
import org.acra.ACRA;
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.BriarReportSenderFactory;
import org.briarproject.briar.android.reporting.DevReportActivity;
import org.briarproject.briar.android.util.UiUtils;
import java.util.Collection;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.APP_VERSION_CODE;
@@ -75,7 +80,13 @@ public class BriarApplicationImpl extends Application
@Override
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);
}
@@ -93,7 +104,7 @@ public class BriarApplicationImpl extends Application
}
}
rootLogger.addHandler(logHandler);
rootLogger.setLevel(INFO);
rootLogger.setLevel(IS_DEBUG_BUILD || IS_BETA_BUILD ? FINE : INFO);
LOG.info("Created");
@@ -106,6 +117,24 @@ public class BriarApplicationImpl extends Application
BrambleCoreModule.initEagerSingletons(applicationComponent);
BriarCoreModule.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() {

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;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -11,9 +14,14 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
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.content.ContextCompat;
import android.util.Log;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -30,8 +38,11 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
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_NONE;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.Intent.ACTION_SHUTDOWN;
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_NO_ANIMATION;
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.PRIORITY_MIN;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static java.util.logging.Level.INFO;
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.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 {
@@ -57,13 +77,12 @@ public class BriarService extends Service {
public static String EXTRA_STARTUP_FAILED =
"org.briarproject.briar.STARTUP_FAILED";
private static final int ONGOING_NOTIFICATION_ID = 1;
private static final int FAILURE_NOTIFICATION_ID = 2;
// Channels are sorted by channel ID in the Settings app, so use IDs
// that will sort below the main channels such as contacts
private static final String ONGOING_CHANNEL_ID = "zForegroundService";
private static final String FAILURE_CHANNEL_ID = "zStartupFailure";
// This tag prevents the wake lock from being ignored on some Huawei devices
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private static final String ACTION_ALARM =
"org.briarproject.briar.android.ACTION_ALARM";
private static final String EXTRA_DUE_MILLIS =
"org.briarproject.briar.android.DUE_MILLIS";
private static final Logger LOG =
Logger.getLogger(BriarService.class.getName());
@@ -71,9 +90,14 @@ public class BriarService extends Service {
private final AtomicBoolean created = new AtomicBoolean(false);
private final Binder binder = new BriarBinder();
private AlarmManager alarm;
@Nullable
private BroadcastReceiver receiver = null;
@Nullable
private BriarBroadcastReceiver testReceiver = null;
@Inject
protected DatabaseConfig databaseConfig;
// Fields that are accessed from background threads must be volatile
@@ -90,6 +114,11 @@ public class BriarService extends Service {
BriarApplication application = (BriarApplication) getApplication();
application.getApplicationComponent().inject(this);
alarm = (AlarmManager)
getApplicationContext().getSystemService(ALARM_SERVICE);
setAlarm();
LOG.info("Created");
if (created.getAndSet(true)) {
LOG.info("Already created");
@@ -103,9 +132,9 @@ public class BriarService extends Service {
}
// Create notification channels
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (SDK_INT >= 26) {
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
NotificationChannel ongoingChannel = new NotificationChannel(
ONGOING_CHANNEL_ID,
getString(R.string.ongoing_notification_title),
@@ -137,6 +166,8 @@ public class BriarService extends Service {
}
b.setPriority(PRIORITY_MIN);
startForeground(ONGOING_NOTIFICATION_ID, b.build());
// Remove sign-in reminder notification
nm.cancel(REMINDER_NOTIFICATION_ID);
// Start the services in a background thread
new Thread(() -> {
String nickname = databaseConfig.getLocalAuthorName();
@@ -166,6 +197,39 @@ public class BriarService extends Service {
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
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) {
@@ -197,6 +261,30 @@ public class BriarService extends Service {
@Override
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
}
@@ -211,10 +299,12 @@ public class BriarService extends Service {
LOG.info("Destroyed");
stopForeground(true);
if (receiver != null) unregisterReceiver(receiver);
if (testReceiver != null) unregisterReceiver(testReceiver);
// Stop the services in a background thread
new Thread(() -> {
if (started) lifecycleManager.stopServices();
}).start();
}
@Override
@@ -243,8 +333,10 @@ public class BriarService extends Service {
LOG.info("Trim memory: running low");
} else if (level == TRIM_MEMORY_RUNNING_CRITICAL) {
LOG.info("Trim memory: running critically low");
// Clear the UI to save some memory
hideUi();
// If we're not in the foreground, clear the UI to save memory
RunningAppProcessInfo info = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(info);
if (info.importance != IMPORTANCE_FOREGROUND) hideUi();
} else if (LOG.isLoggable(INFO)) {
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 org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.LogUtils.now;
class NetworkUsageLogger implements Service {
@@ -18,17 +18,17 @@ class NetworkUsageLogger implements Service {
private volatile long startTime, rxBytes, txBytes;
@Override
public void startService() throws ServiceException {
startTime = System.currentTimeMillis();
public void startService() {
startTime = now();
int uid = Process.myUid();
rxBytes = TrafficStats.getUidRxBytes(uid);
txBytes = TrafficStats.getUidTxBytes(uid);
}
@Override
public void stopService() throws ServiceException {
public void stopService() {
if (LOG.isLoggable(INFO)) {
long sessionDuration = System.currentTimeMillis() - startTime;
long sessionDuration = now() - startTime;
int uid = Process.myUid();
long rx = TrafficStats.getUidRxBytes(uid) - rxBytes;
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.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
@@ -189,7 +190,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
String publicKey = StringUtils.toHexString(publicKeyBytes);
return PLAY_SERVICES_PUBLIC_KEY.equals(publicKey);
} catch (NameNotFoundException | CertificateException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
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 ?
BuildConfig.BuildTimestamp + 90 * 24 * 60 * 60 * 1000L :
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.IntroductionActivity;
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.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.ChangePasswordActivity;
import org.briarproject.briar.android.login.DozeFragment;
@@ -100,6 +101,8 @@ public interface ActivityComponent {
void inject(PanicPreferencesActivity activity);
void inject(ContactExchangeActivity activity);
void inject(KeyAgreementActivity activity);
void inject(ConversationActivity activity);
@@ -185,7 +188,7 @@ public interface ActivityComponent {
void inject(IntroFragment fragment);
void inject(ShowQrCodeFragment fragment);
void inject(KeyAgreementFragment fragment);
void inject(ContactChooserFragment fragment);

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.android.activity;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
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.BriarApplication;
import org.briarproject.briar.android.DestroyableContext;
import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.controller.ActivityLifecycleController;
import org.briarproject.briar.android.forum.ForumModule;
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() {
return activityComponent;
}

View File

@@ -92,7 +92,6 @@ public abstract class BriarActivity extends BaseActivity {
window.setEnterTransition(slide);
window.setTransitionBackgroundFadeDuration(getResources()
.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 static java.util.logging.Level.INFO;
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;
@MethodsNotNullByDefault
@@ -101,30 +103,25 @@ abstract class BaseControllerImpl extends DbControllerImpl
Collection<BlogPostItem> items = loadItems(groupId);
handler.onResult(items);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
handler.onException(e);
}
});
}
Collection<BlogPostItem> loadItems(GroupId groupId) throws DbException {
long now = System.currentTimeMillis();
long start = now();
Collection<BlogPostHeader> headers =
blogManager.getPostHeaders(groupId);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading headers took " + duration + " ms");
logDuration(LOG, "Loading headers", start);
Collection<BlogPostItem> items = new ArrayList<>(headers.size());
now = System.currentTimeMillis();
start = now();
for (BlogPostHeader h : headers) {
headerCache.put(h.getId(), h);
BlogPostItem item = getItem(h);
items.add(item);
}
duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading bodies took " + duration + " ms");
logDuration(LOG, "Loading bodies", start);
return items;
}
@@ -140,15 +137,12 @@ abstract class BaseControllerImpl extends DbControllerImpl
}
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
BlogPostItem item = getItem(header);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading body took " + duration + " ms");
logDuration(LOG, "Loading body", start);
handler.onResult(item);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
handler.onException(e);
}
});
@@ -166,16 +160,13 @@ abstract class BaseControllerImpl extends DbControllerImpl
}
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
BlogPostHeader header1 = getPostHeader(g, m);
BlogPostItem item = getItem(header1);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading post took " + duration + " ms");
logDuration(LOG, "Loading post", start);
handler.onResult(item);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
handler.onException(e);
}
});
@@ -191,8 +182,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
BlogPostHeader h = item.getHeader();
blogManager.addLocalComment(a, b.getId(), comment, h);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
handler.onException(e);
}
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,7 +33,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
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.api.android.AndroidNotificationManager;
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.view.ViewCompat.getTransitionName;
import static java.util.logging.Level.INFO;
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;
@MethodsNotNullByDefault
@@ -163,7 +165,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
switch (item.getItemId()) {
case R.id.action_add_contact:
Intent intent =
new Intent(getContext(), KeyAgreementActivity.class);
new Intent(getContext(), ContactExchangeActivity.class);
startActivity(intent);
return true;
default:
@@ -194,7 +196,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
int revision = adapter.getRevision();
listener.runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
List<ContactListItem> contacts = new ArrayList<>();
for (Contact c : contactManager.getActiveContacts()) {
try {
@@ -208,12 +210,10 @@ public class ContactListFragment extends BaseFragment implements EventListener {
// Continue
}
}
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms");
logDuration(LOG, "Full load", start);
displayContacts(revision, contacts);
} 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 java.util.logging.Level.INFO;
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.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
@@ -290,21 +293,19 @@ public class ConversationActivity extends BriarActivity
private void loadContactDetailsAndMessages() {
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
if (contactName == null || contactAuthorId == null) {
Contact contact = contactManager.getContact(contactId);
contactName = contact.getAuthor().getName();
contactAuthorId = contact.getAuthor().getId();
}
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading contact took " + duration + " ms");
logDuration(LOG, "Loading contact", start);
loadMessages();
displayContactDetails();
} catch (NoSuchContactException e) {
finishOnUiThread();
} 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();
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
Collection<PrivateMessageHeader> headers =
messagingManager.getMessageHeaders(contactId);
Collection<IntroductionMessage> introductions =
@@ -357,14 +358,12 @@ public class ConversationActivity extends BriarActivity
invitations.addAll(forumInvitations);
invitations.addAll(blogInvitations);
invitations.addAll(groupInvitations);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading messages took " + duration + " ms");
logDuration(LOG, "Loading messages", start);
displayMessages(revision, headers, introductions, invitations);
} catch (NoSuchContactException e) {
finishOnUiThread();
} 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) {
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
String body = messagingManager.getMessageBody(m);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading body took " + duration + " ms");
logDuration(LOG, "Loading body", start);
displayMessageBody(m, body);
} 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);
createMessage(body, timestamp);
} 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) {
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
messagingManager.addLocalMessage(m);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Storing message took " + duration + " ms");
logDuration(LOG, "Storing message", start);
Message message = m.getMessage();
PrivateMessageHeader h = new PrivateMessageHeader(
message.getId(), message.getGroupId(),
@@ -703,7 +698,7 @@ public class ConversationActivity extends BriarActivity
bodyCache.put(message.getId(), body);
addConversationItem(item);
} 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 {
contactManager.removeContact(contactId);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
} finally {
finishAfterContactRemoved();
}
@@ -755,7 +750,7 @@ public class ConversationActivity extends BriarActivity
}
}
} 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);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} 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) {
runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
messagingManager.setReadFlag(g, m, true);
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Marking read took " + duration + " ms");
logDuration(LOG, "Marking read", start);
} 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();
} catch (ProtocolStateException e) {
// 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) {
// 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 static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable
@NotNullByDefault
@@ -53,7 +54,7 @@ public abstract class ContactSelectorControllerImpl
}
handler.onResult(contacts);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
handler.onException(e);
}
});

View File

@@ -21,6 +21,7 @@ import java.util.logging.Logger;
import javax.inject.Inject;
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.util.UiUtils.needsDozeWhitelisting;
@@ -101,8 +102,7 @@ public class BriarControllerImpl implements BriarController {
boolean ask = settings.getBoolean(DOZE_ASK_AGAIN, true);
handler.onResult(ask);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
});
}
@@ -115,8 +115,7 @@ public class BriarControllerImpl implements BriarController {
settings.putBoolean(DOZE_ASK_AGAIN, false);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
}
});
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,8 +44,10 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
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 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;
@MethodsNotNullByDefault
@@ -157,7 +159,7 @@ public class ForumListFragment extends BaseEventFragment implements
int revision = adapter.getRevision();
listener.runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
Collection<ForumListItem> forums = new ArrayList<>();
for (Forum f : forumManager.getForums()) {
try {
@@ -168,12 +170,10 @@ public class ForumListFragment extends BaseEventFragment implements
// Continue
}
}
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Full load took " + duration + " ms");
logDuration(LOG, "Full load", start);
displayForums(revision, forums);
} 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() {
listener.runOnDbThread(() -> {
try {
long now = System.currentTimeMillis();
long start = now();
int available = forumSharingManager.getInvitations().size();
long duration = System.currentTimeMillis() - now;
if (LOG.isLoggable(INFO))
LOG.info("Loading available took " + duration + " ms");
logDuration(LOG, "Loading available", start);
displayAvailableForums(available);
} 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 static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
public class ContactChooserFragment extends BaseFragment {
@@ -129,7 +130,7 @@ public class ContactChooserFragment extends BaseFragment {
}
displayContacts(contacts);
} 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.widget.Toast.LENGTH_SHORT;
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;
public class IntroductionMessageFragment extends BaseFragment
@@ -129,7 +130,7 @@ public class IntroductionMessageFragment extends BaseFragment
boolean possible = introductionManager.canIntroduce(c1, c2);
setUpViews(c1, c2, possible);
} 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();
introductionManager.makeIntroduction(c1, c2, msg, timestamp);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
introductionError();
}
});

View File

@@ -9,10 +9,12 @@ import android.hardware.Camera.Size;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -21,6 +23,7 @@ import java.io.IOException;
import java.util.List;
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_FRONT;
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 java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@SuppressWarnings("deprecation")
@MethodsNotNullByDefault
@@ -96,7 +100,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
}
@UiThread
public void start(int rotationDegrees) throws CameraException {
public void start() throws CameraException {
LOG.info("Opening camera");
try {
int cameras = Camera.getNumberOfCameras();
@@ -121,7 +125,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
} catch (RuntimeException e) {
throw new CameraException(e);
}
setDisplayOrientation(rotationDegrees);
setDisplayOrientation(getScreenRotationDegrees());
// Use barcode scene mode if it's available
Parameters params = camera.getParameters();
params = setSceneMode(camera, params);
@@ -156,6 +160,27 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
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
private void startPreview(SurfaceHolder holder) throws CameraException {
LOG.info("Starting preview");
@@ -408,7 +433,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try {
surfaceCreatedUi(holder);
} 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 {
surfaceChangedUi(holder, w, h);
} 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 {
startAutoFocus();
} 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.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.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.ParametersNotNullByDefault;
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.os.Build.VERSION.SDK_INT;
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_PERMISSION_CAMERA;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class KeyAgreementActivity extends BriarActivity implements
BaseFragmentListener, IntroScreenSeenListener, EventListener,
ContactExchangeListener {
public abstract class KeyAgreementActivity extends BriarActivity implements
BaseFragmentListener, IntroScreenSeenListener,
KeyAgreementFragment.KeyAgreementEventListener {
private enum BluetoothState {
UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED
@@ -73,12 +62,6 @@ public class KeyAgreementActivity extends BriarActivity implements
@Inject
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 continueClicked, gotCameraPermission;
private BluetoothState bluetoothState = BluetoothState.UNKNOWN;
@@ -94,13 +77,9 @@ public class KeyAgreementActivity extends BriarActivity implements
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_fragment_container_toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.add_contact_title);
if (state == null) {
showInitialFragment(IntroFragment.newInstance());
}
@@ -115,18 +94,6 @@ public class KeyAgreementActivity extends BriarActivity implements
if (bluetoothReceiver != null) unregisterReceiver(bluetoothReceiver);
}
@Override
public void onStart() {
super.onStart();
eventBus.addListener(this);
}
@Override
protected void onStop() {
super.onStop();
eventBus.removeListener(this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@@ -147,7 +114,7 @@ public class KeyAgreementActivity extends BriarActivity implements
if (canShowQrCodeFragment()) showQrCodeFragment();
}
boolean canShowQrCodeFragment() {
private boolean canShowQrCodeFragment() {
return isResumed && continueClicked
&& (SDK_INT < 23 || gotCameraPermission)
&& bluetoothState != BluetoothState.UNKNOWN
@@ -206,10 +173,11 @@ public class KeyAgreementActivity extends BriarActivity implements
}
private void showQrCodeFragment() {
continueClicked = false;
// FIXME #824
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(ShowQrCodeFragment.TAG) == null) {
BaseFragment f = ShowQrCodeFragment.newInstance();
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
BaseFragment f = KeyAgreementFragment.newInstance();
fm.beginTransaction()
.replace(R.id.fragmentContainer, f, 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 {
@Override

View File

@@ -2,18 +2,12 @@ package org.briarproject.briar.android.keyagreement;
import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
@@ -24,6 +18,7 @@ import com.google.zxing.Result;
import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.event.Event;
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.Payload;
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.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseEventFragment;
import org.briarproject.briar.android.fragment.ErrorFragment;
import org.briarproject.briar.android.view.QrCodeView;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -59,13 +56,14 @@ import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ShowQrCodeFragment extends BaseEventFragment
implements QrCodeDecoder.ResultCallback {
public class KeyAgreementFragment extends BaseEventFragment
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 Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
@@ -83,26 +81,29 @@ public class ShowQrCodeFragment extends BaseEventFragment
EventBus eventBus;
private CameraView cameraView;
private LinearLayout cameraOverlay;
private View statusView;
private QrCodeView qrCodeView;
private TextView status;
private ImageView qrCode;
private TextView mainProgressTitle;
private ViewGroup mainProgressContainer;
private boolean fullscreen = false;
private boolean gotRemotePayload;
private volatile boolean gotLocalPayload;
private KeyAgreementTask task;
private KeyAgreementEventListener listener;
public static ShowQrCodeFragment newInstance() {
public static KeyAgreementFragment newInstance() {
Bundle args = new Bundle();
ShowQrCodeFragment fragment = new ShowQrCodeFragment();
KeyAgreementFragment fragment = new KeyAgreementFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (KeyAgreementEventListener) context;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
@@ -118,7 +119,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_keyagreement_qr, container,
false);
}
@@ -126,47 +126,17 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
cameraView = view.findViewById(R.id.camera_view);
cameraOverlay = view.findViewById(R.id.camera_overlay);
statusView = view.findViewById(R.id.status_container);
status = view.findViewById(R.id.connect_status);
qrCode = view.findViewById(R.id.qr_code);
mainProgressTitle = view.findViewById(R.id.title_progress_bar);
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;
});
qrCodeView = view.findViewById(R.id.qr_code_view);
qrCodeView.setFullscreenListener(this);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
cameraView.setPreviewConsumer(new QrCodeDecoder(this));
}
@@ -175,30 +145,33 @@ public class ShowQrCodeFragment extends BaseEventFragment
public void onStart() {
super.onStart();
try {
cameraView.start(getScreenRotationDegrees());
cameraView.start();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
}
startListening();
}
/**
* See {@link Camera#setDisplayOrientation(int)}.
*/
private int getScreenRotationDegrees() {
Display d = getActivity().getWindowManager().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();
@Override
public void setFullscreen(boolean fullscreen) {
LinearLayout.LayoutParams statusParams, qrCodeParams;
if (fullscreen) {
// Grow the QR code view to fill its parent
statusParams = new LayoutParams(0, 0, 0f);
qrCodeParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f);
} else {
// Shrink the QR code view 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);
}
}
statusView.setLayoutParams(statusParams);
qrCodeView.setLayoutParams(qrCodeParams);
cameraOverlay.invalidate();
}
@Override
@@ -214,7 +187,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
@UiThread
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,
LENGTH_LONG).show();
finish();
@@ -244,7 +217,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
// If we've stopped the camera view, restart it
if (gotRemotePayload) {
try {
cameraView.start(getScreenRotationDegrees());
cameraView.start();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
return;
@@ -278,7 +251,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
} catch (IOException | IllegalArgumentException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, "QR Code Invalid", e);
LOG.log(WARNING, "QR Code Invalid", e);
reset();
Toast.makeText(getActivity(), R.string.qr_code_invalid,
LENGTH_LONG).show();
@@ -301,82 +274,60 @@ public class ShowQrCodeFragment extends BaseEventFragment
KeyAgreementAbortedEvent event = (KeyAgreementAbortedEvent) e;
keyAgreementAborted(event.didRemoteAbort());
} else if (e instanceof KeyAgreementFinishedEvent) {
runOnUiThreadUnlessDestroyed(() -> {
mainProgressContainer.setVisibility(VISIBLE);
mainProgressTitle.setText(R.string.exchanging_contact_details);
});
keyAgreementFinished(((KeyAgreementFinishedEvent) e).getResult());
}
}
@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() {
runOnUiThreadUnlessDestroyed(() -> {
reset();
// TODO show failure somewhere persistent?
Toast.makeText(getActivity(), R.string.connection_failed,
LENGTH_LONG).show();
listener.keyAgreementFailed();
});
}
private void keyAgreementWaiting() {
runOnUiThreadUnlessDestroyed(
() -> status.setText(R.string.waiting_for_contact_to_scan));
() -> status.setText(listener.keyAgreementWaiting()));
}
private void keyAgreementStarted() {
runOnUiThreadUnlessDestroyed(() -> {
mainProgressContainer.setVisibility(VISIBLE);
mainProgressTitle.setText(R.string.authenticating_with_device);
qrCodeView.setVisibility(INVISIBLE);
statusView.setVisibility(VISIBLE);
status.setText(listener.keyAgreementStarted());
});
}
private void keyAgreementAborted(boolean remoteAborted) {
runOnUiThreadUnlessDestroyed(() -> {
reset();
mainProgressContainer.setVisibility(INVISIBLE);
mainProgressTitle.setText("");
// TODO show abort somewhere persistent?
Toast.makeText(getActivity(),
remoteAborted ? R.string.connection_aborted_remote :
R.string.connection_aborted_local, LENGTH_LONG)
.show();
qrCodeView.setVisibility(VISIBLE);
statusView.setVisibility(INVISIBLE);
status.setText(listener.keyAgreementAborted(remoteAborted));
});
}
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() {
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 com.google.zxing.BarcodeFormat.QR_CODE;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
class QrCodeUtils {
@@ -34,7 +35,7 @@ class QrCodeUtils {
smallestDimen, smallestDimen);
return renderQrCode(encoded);
} catch (WriterException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
logException(LOG, WARNING, e);
return null;
}
}

View File

@@ -42,6 +42,22 @@ public class BriefLogFormatter extends Formatter {
tag = tag.substring(tag.lastIndexOf('.') + 1);
sb.append(tag).append(": ");
sb.append(record.getMessage());
Throwable t = record.getThrown();
if (t != null) {
sb.append('\n');
appendThrowable(sb, t);
}
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 static android.os.Build.VERSION.SDK_INT;
@UiThread
@NotNullByDefault
class HuaweiView extends PowerView {
@@ -45,6 +47,8 @@ class HuaweiView extends PowerView {
}
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();
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(),
PackageManager.MATCH_DEFAULT_ONLY);

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