Compare commits

...

392 Commits

Author SHA1 Message Date
akwizgran
fe6ce2fe67 Bump version numbers for 1.5.10 release. 2024-03-11 15:31:46 +00:00
akwizgran
65f7a02c33 Update translations. 2024-03-11 15:30:54 +00:00
Torsten Grote
ea7433ffca Merge branch 'onionwrapper-0.1.0' into 'master'
Upgrade onionwrapper to 0.1.0 and snowflake to 2.9.1

See merge request briar/briar!1819
2024-03-11 15:08:22 +00:00
akwizgran
48b6dcf0ff Update summary of Tor bridges setting. 2024-03-09 21:21:18 +00:00
akwizgran
ca9181ee3f Upgrade onionwrapper to 0.1.0 and snowflake to 2.9.1. 2024-03-09 20:52:32 +00:00
akwizgran
f16875c602 Bump version numbers for 1.5.9 release. 2024-01-16 17:47:20 +00:00
Torsten Grote
551dba9425 Merge branch 'onionwrapper-0.0.7' into 'master'
Upgrade onionwrapper to 0.0.7

See merge request briar/briar!1818
2024-01-16 17:24:09 +00:00
akwizgran
07f49e4f1e Upgrade onionwrapper to 0.0.7. 2024-01-16 12:16:57 +00:00
akwizgran
ca14b4bd68 Update translations. 2024-01-15 17:23:20 +00:00
Torsten Grote
58883467f7 Merge branch 'tor-0.4.8.9-1' into 'master'
Upgrade Tor to 0.4.8.9-1

See merge request briar/briar!1817
2024-01-12 19:54:09 +00:00
akwizgran
422a99888b Upgrade Tor to 0.4.8.9-1. 2024-01-12 17:50:46 +00:00
Torsten Grote
28453f28d0 Merge branch 'increase-gradle-heap' into 'master'
Give Gradle more RAM to avoid random OOMs in test pipelines

See merge request briar/briar!1816
2023-12-01 13:42:54 +00:00
akwizgran
f00cfe5ca9 Give Gradle more RAM to avoid random OOMs in test pipelines. 2023-12-01 11:50:56 +00:00
Torsten Grote
3ecb281695 Merge branch 'api-31-tapjacking-protection' into 'master'
API 31 tapjacking protection

See merge request briar/briar!1814
2023-11-28 17:59:06 +00:00
Torsten Grote
eb3a5423bf Merge branch 'increase-hotspot-password-length' into 'master'
Increase password length for app-sharing hotspot

See merge request briar/briar!1815
2023-11-28 17:57:08 +00:00
akwizgran
73fa1052cf Increase password length for app-sharing hotspot.
This makes it impractical for a nearby attacker to brute-force
the password in order to inject malware into the download.
2023-11-28 17:42:44 +00:00
akwizgran
14fded3777 Update link to download page (the old link is now a redirect). 2023-11-28 14:30:36 +00:00
akwizgran
17f5433ab0 Use API 31 tapjacking protection. 2023-11-28 14:30:35 +00:00
akwizgran
1752bca2ae Bump version numbers for 1.5.8 release. 2023-10-09 11:08:31 +01:00
akwizgran
9d9a7ff99d Update translations. 2023-10-09 10:34:35 +01:00
Torsten Grote
36e69c54df Merge branch 'tor-0.4.7.15-onionwrapper-0.0.6' into 'master'
Upgrade Tor to 0.4.7.15 and onionwrapper to 0.0.6

See merge request briar/briar!1813
2023-10-07 17:06:00 +00:00
akwizgran
a3b10cc0d1 Upgrade Tor to 0.4.7.14 and onionwrapper to 0.0.6. 2023-09-29 12:12:36 +01:00
akwizgran
f683d4f3a9 Use same indentation for witness.gradle in AS and script. 2023-09-29 12:08:49 +01:00
Torsten Grote
ea1c58110f Merge branch '2448-bluetooth-permission-prompt' into 'master'
Only show Bluetooth permission prompt when Bluetooth is toggled

Closes #2448

See merge request briar/briar!1812
2023-09-28 14:09:07 +00:00
akwizgran
b559c7782d Only show Bluetooth permission prompt when Bluetooth is toggled. 2023-09-27 16:09:39 +01:00
akwizgran
6ae601e395 Bump version numbers for 1.5.7 release. 2023-09-12 17:30:19 +01:00
akwizgran
c5c1fdb61c Update translations. 2023-09-12 17:30:06 +01:00
Torsten Grote
cc9ebe9eda Merge branch 'catch-security-exception-for-bluetooth-address-setting' into 'master'
Catch SecurityException for bluetooth_address setting

See merge request briar/briar!1811
2023-09-12 16:24:05 +00:00
akwizgran
05b9dd699e Catch SecurityException for bluetooth_address setting. 2023-09-12 17:12:13 +01:00
Torsten Grote
09a9a00af6 Merge branch '2444-catch-exception-when-starting-chooser' into 'master'
Catch ActivityNotFoundException when starting chooser

Closes #2444

See merge request briar/briar!1810
2023-09-06 11:16:43 +00:00
Torsten Grote
67797d0378 Merge branch '2330-catch-npe-from-getbyinetaddress' into 'master'
Catch NPE from NetworkInterface.getByInetAddress()

Closes #2330

See merge request briar/briar!1809
2023-09-06 11:16:09 +00:00
akwizgran
87ef5e58ee Update Play Store metadata. 2023-08-28 16:54:13 +01:00
akwizgran
b8b5e6c201 Update Play Store metadata. 2023-08-24 17:44:35 +01:00
akwizgran
4b11f3c0b3 Catch ActivityNotFoundException when starting chooser. 2023-08-24 15:58:33 +01:00
akwizgran
cc47c8522a Catch NPE from NetworkInterface.getByInetAddress(). 2023-08-24 15:53:00 +01:00
akwizgran
b68d24dca5 Bump version numbers for 1.5.6 release. 2023-08-23 10:45:39 +01:00
Torsten Grote
8bb3ea8a85 Merge branch 'no-tv-for-you' into 'master'
Remove support for Android TV

See merge request briar/briar!1808
2023-08-23 07:51:20 +00:00
Torsten Grote
e13563952b Merge branch 'update-play-store-description' into 'master'
Add links to Play Store description

See merge request briar/briar!1807
2023-08-23 07:49:08 +00:00
Torsten Grote
c74ebabcd1 Merge branch 'update-readme' into 'master'
Update readme: add privacy policy, remove Flattr

See merge request briar/briar!1806
2023-08-23 07:47:35 +00:00
akwizgran
47b8f47f07 Remove support for Android TV.
Google requires apps that support Android TV to be published as app bundles.
2023-08-22 15:59:20 +01:00
akwizgran
d0feacd38f Add links to Play Store description. 2023-08-22 15:35:04 +01:00
akwizgran
2844adb8fa Bump version numbers for 1.5.5 release. 2023-08-21 14:54:06 +01:00
akwizgran
f02dcc9f70 Update translations. 2023-08-21 14:53:21 +01:00
akwizgran
8ab7eb7edf Update readme: add privacy policy, remove Flattr. 2023-08-21 14:44:29 +01:00
akwizgran
1ef1ccc1f7 Merge branch 'fix-group-invitation-state' into 'master'
fix SharingState for private group creator

See merge request briar/briar!1805
2023-08-15 15:33:37 +00:00
akwizgran
c7e382c1af Update translations. 2023-08-15 13:33:02 +01:00
ialokim
38a7217c3f fix SharingState for private group creator 2023-08-14 18:05:48 +02:00
Torsten Grote
6d3e81a074 Merge branch 'tor-0.4.7.14' into 'master'
Upgrade Tor to 0.4.7.14

See merge request briar/briar!1804
2023-08-11 12:44:57 +00:00
akwizgran
4591de2017 Upgrade Tor to 0.4.7.14. 2023-08-08 16:54:09 +01:00
Torsten Grote
6da34fac84 Merge branch 'bdf-javadocs' into 'master'
Add BDF javadocs

See merge request briar/briar!1801
2023-08-07 14:16:22 +00:00
Torsten Grote
810ac24cee Merge branch 'onionwrapper-0.0.5' into 'master'
Upgrade onionwrapper to 0.0.5

See merge request briar/briar!1803
2023-08-07 13:48:36 +00:00
akwizgran
704f69c9fd Upgrade onionwrapper to 0.0.5. 2023-08-07 14:17:11 +01:00
akwizgran
952ee42ad1 Merge branch 'blog-txns' into 'master'
Add transactional versions of BlogManager methods and a bug fix

See merge request briar/briar!1802
2023-07-13 20:30:21 +00:00
Torsten Grote
f61b09d5a9 Fix BlogManager tests after last commits 2023-07-13 14:50:05 -03:00
Torsten Grote
8f735d176e Add transactional versions of BlogManager methods 2023-07-13 13:01:30 -03:00
Torsten Grote
c47253fc5f Mark our own reblogs as read automatically 2023-07-13 12:54:17 -03:00
akwizgran
b1cc63cd49 Deprecate methods for handling non-canonical BDF. 2023-07-05 15:23:14 +01:00
akwizgran
8cd6546840 Add javadocs for BDF classes. 2023-07-05 15:23:08 +01:00
akwizgran
7a0fb74c09 Merge branch '2266-target-sdk-33' into 'master'
Target SDK 33

Closes #2266

See merge request briar/briar!1800
2023-07-03 10:55:46 +00:00
akwizgran
882f536b8d Don't try to get Bluetooth address from settings. 2023-06-30 18:14:12 +01:00
Torsten Grote
74f8e84a9b React to device light idle mode in DozeWatchdog as well 2023-06-29 10:58:32 -03:00
Torsten Grote
23df2a41c2 Add @NotNullByDefault annotation to ConditionManagers 2023-06-29 10:58:32 -03:00
Torsten Grote
c77eaf16d9 Log more mode changes in AndroidBatteryManager 2023-06-29 10:58:31 -03:00
Torsten Grote
9a6bb4b203 Set dozed to true when we are in LowPowerStandby 2023-06-29 10:58:31 -03:00
Torsten Grote
3d237a9104 Introduce tryToStartActivity() helper method 2023-06-29 10:58:31 -03:00
Torsten Grote
fa216ffc6f Move requestEnableWiFi() into AbstractConditionManager 2023-06-29 10:58:31 -03:00
Torsten Grote
a34631d36c Catch ActivityNotFoundException in places where we launch external intents 2023-06-29 10:58:31 -03:00
Torsten Grote
45cda191e5 Log changes to DeviceLightIdleMode in AndroidBatteryManager 2023-06-29 10:58:31 -03:00
Torsten Grote
2495b6f5c0 Add LowPowerStandby stub to DozeWatchdogImpl 2023-06-29 10:58:31 -03:00
Torsten Grote
03fc504f7d Log changes to LowPowerStandby in AndroidBatteryManager 2023-06-29 10:58:30 -03:00
Torsten Grote
d19062e319 Don't disable hotspot start button after click
to avoid issues when coming back to the screen after granting permissions.
2023-06-29 10:58:30 -03:00
Torsten Grote
fdb429ab7a Ask for NEARBY_WIFI_DEVICES permission on SDK 33 and up 2023-06-29 10:58:30 -03:00
Torsten Grote
d0c59a6d75 Target SDK 33 and ask for notification permission
when creating account and when signing in
2023-06-29 10:58:30 -03:00
akwizgran
3bb39c2aa3 Merge branch 'fix-macos-x86-issue' into 'master'
Fix architecture detection for macOS Intel CPUs

See merge request briar/briar!1799
2023-06-28 11:07:26 +00:00
Sebastian Kürten
917fc5e5b6 Fix architecture detection for macOS Intel CPUs 2023-06-28 12:57:20 +02:00
akwizgran
caa078585b Merge branch 'macos3' into 'master'
macOS support

See merge request briar/briar!1790
2023-06-22 17:04:09 +00:00
akwizgran
e68c0c7f4b Merge branch 'onionwrapper-0.0.4' into 'master'
Upgrade onionwrapper to 0.0.4

See merge request briar/briar!1798
2023-06-22 12:26:21 +00:00
akwizgran
a6b3749fb6 Extend comment explaining TorState -> State mapping. 2023-06-22 13:12:58 +01:00
Torsten Grote
a8f6e8e4bd Merge branch 'check-network-status-periodically' into 'master'
Check network status periodically

See merge request briar/briar!1797
2023-06-21 13:32:39 +00:00
akwizgran
4d884601f0 Check more often, only broadcast status if changed. 2023-06-20 17:01:45 +01:00
akwizgran
b71198d9b1 Check network status periodically on JavaSE. 2023-06-20 16:34:45 +01:00
Sebastian Kürten
079c6e0475 Add comment why we choose a differnt port for headless on macOS 2023-06-20 12:21:11 +02:00
Sebastian Kürten
3a0f8ed85c Document building of macOS headless jars and fix included native binaries on macOS 2023-06-15 18:07:18 +02:00
Sebastian Kürten
57f7501780 macOS support 2023-06-15 12:48:01 +02:00
akwizgran
3cc5699fe0 Upgrade onionwrapper to 0.0.4. 2023-06-14 17:06:10 +01:00
akwizgran
7d761710e6 Bump version numbers for 1.5.4 release. 2023-06-02 13:53:20 +01:00
Torsten Grote
7461d3c943 Merge branch '2434-use-us-locale-for-lowercasing-onion-hostname' into 'master'
Use US locale for lowercasing onion hostname

Closes #2434

See merge request briar/briar!1796
2023-05-31 16:27:24 +00:00
akwizgran
9291613175 Fix some other uses of toLowerCase() without a locale. 2023-05-30 22:06:18 +01:00
akwizgran
ce6739a9fd Use US locale for lowercasing onion hostname. 2023-05-30 22:00:41 +01:00
akwizgran
1f1a97f62d Bump version numbers for 1.5.3 release. 2023-05-24 11:33:49 +01:00
akwizgran
7a33d26533 Merge branch 'new-handshake' 2023-05-24 11:22:23 +01:00
akwizgran
f2c85f37be Merge branch '2391-share-link' into 'master'
Share a link to the Briar download page via another app

Closes #2391

See merge request briar/briar!1795
2023-05-22 15:35:43 +00:00
Torsten Grote
8e3fa872fd Move About settings item to the bottom 2023-05-17 08:53:24 -03:00
akwizgran
0d1e81ebdb Merge branch 'use-default-secure-random-provider-on-macos' into 'master'
Use system default secure random provider on macOS

Closes briar-desktop#132

See merge request briar/briar!1794
2023-05-17 09:25:42 +00:00
Sebastian Kürten
bded4e7bc8 Use system default secure random provider on macOS 2023-05-17 11:13:43 +02:00
Torsten Grote
bf1a5cf218 Allow sharing download link for Briar from settings actions 2023-05-16 16:55:19 -03:00
akwizgran
dd7a638984 Merge branch 'fa-string-fix' into 'master'
Fix translation

See merge request briar/briar!1793
2023-05-16 10:38:47 +00:00
paul
942222131e Fix translation. 2023-05-15 21:48:02 +00:00
akwizgran
643757e407 Bump version numbers for 1.5.2 release. 2023-05-15 15:48:50 +01:00
akwizgran
7c530ad7a3 Update translations. 2023-05-15 15:48:00 +01:00
Torsten Grote
23b2dfa4a8 Merge branch 'conversationmanager-txn' into 'master'
Add transactional versions to delete message functions

See merge request briar/briar!1792
2023-05-15 12:03:53 +00:00
ialokim
ce10e6770f add transactional versions to delete message functions 2023-05-12 23:58:59 +02:00
Torsten Grote
b88dbee881 Merge branch 'onionwrapper-0.0.2' into 'master'
Upgrade onionwrapper to 0.0.2 and dont-kill-me-lib to 0.2.7

See merge request briar/briar!1791
2023-05-10 17:00:38 +00:00
akwizgran
0ca21ad4c0 Upgrade onionwrapper to 0.0.2 and dont-kill-me-lib to 0.2.7. 2023-05-09 15:23:17 +01:00
akwizgran
a14f62dcc3 Update translations. 2023-05-05 14:57:46 +01:00
akwizgran
f0c1ebcc1b Merge branch 'kill-android4' into 'master'
Drop support for Android 4

See merge request briar/briar!1770
2023-05-05 13:54:07 +00:00
akwizgran
4a4b04bec3 Rename version constant. 2023-04-26 17:10:23 +01:00
Torsten Grote
6f57ec8281 Merge branch 'privategroup-testdata' into 'master'
TestDataCreator with support for private groups

See merge request briar/briar!1788
2023-04-26 12:38:53 +00:00
Sebastian Kürten
0eb0bbdc99 Add ability to add private group test data in settings 2023-04-26 00:05:49 +02:00
Torsten Grote
76344344d2 Downgrade material library due to upstream bug
https://github.com/material-components/material-components-android/issues/3191
2023-04-25 11:29:51 -03:00
akwizgran
624f11a61f Bump version numbers for 1.5.1 release. 2023-04-21 15:51:55 +01:00
Torsten Grote
fbc32830bd Force kotlin standard lib to latest version to prevent jetifier issues 2023-04-19 11:02:33 -03:00
Torsten Grote
145117a1dc Update most of the things 2023-04-19 11:02:33 -03:00
Torsten Grote
6ed55bcd7d Drop support for Android 4
new minSdk is 21
2023-04-19 11:02:31 -03:00
akwizgran
c6a284bd6d Bump version numbers for 1.5.0 release. 2023-04-19 14:23:20 +01:00
akwizgran
9d4d992009 Update translations. 2023-04-19 14:21:38 +01:00
Torsten Grote
e92eb1c699 Merge branch 'enable-mailbox-in-release-builds' into 'master'
Enable mailbox support in release builds

See merge request briar/briar!1789
2023-04-19 13:17:53 +00:00
akwizgran
07e56f7086 Remove mailbox feature flag. 2023-04-18 14:18:58 +01:00
akwizgran
fe31e60e66 Merge branch '2420-obsolete-bluetooth-permission-api-32' into 'master'
Require obsolete Bluetooth permission on API 32 (and counting)

Closes #2420

See merge request briar/briar!1782
2023-04-18 11:43:59 +00:00
akwizgran
7810e7e848 Enable mailbox support in release builds. 2023-04-18 12:37:33 +01:00
ialokim
f8015272f4 private group support for TestDataCreator 2023-04-06 16:43:18 +02:00
Torsten Grote
2566105f13 Merge branch 'tor-wrapper-library' into 'master'
Use Tor wrapper library

See merge request briar/briar!1787
2023-04-03 19:27:58 +00:00
akwizgran
cab8f834bd Convert onionwrapper from a submodule to a dependency. 2023-03-29 17:01:30 +01:00
akwizgran
ec0a754289 Remove BridgeTest from CI config. 2023-03-29 11:58:38 +01:00
akwizgran
e81fe44ea1 Update onionwrapper. 2023-03-28 18:09:43 +01:00
akwizgran
e399b9196a Merge branch 'tor-plugin-refactoring' into 'master'
Refactor Tor plugin to separate out reusable code

See merge request briar/briar!1786
2023-03-28 16:42:17 +00:00
akwizgran
aadbd3a662 Fix dependencies for headless jar tasks. 2023-03-28 17:41:22 +01:00
akwizgran
f4fd65aee4 Remove jtorctl dependency. 2023-03-28 17:28:15 +01:00
akwizgran
61e7d2ebf9 Move Tor wrapper to library. 2023-03-28 17:18:05 +01:00
akwizgran
06dd8c65aa Fix parsing of bootstrap percentage. 2023-03-28 15:44:25 +01:00
akwizgran
2f351b318e Move CircumventionProvider classes to wrapper package. 2023-03-28 15:40:48 +01:00
akwizgran
a468af94db Add bootstrap percentage and HS desc uploads to observer interface. 2023-03-28 11:31:20 +01:00
akwizgran
49f10e7e82 Move wake lock code to dont-kill-me-lib. 2023-03-28 10:58:45 +01:00
akwizgran
01b1741e83 Factor out Tor wrapper from plugin 2023-03-27 12:02:05 +01:00
akwizgran
b7003a3587 Update translations. 2023-03-20 10:59:32 +00:00
akwizgran
3dbf327937 Merge branch 'backport-os-check-algorithm' into 'master'
Backport OS-check logic from Compose Multiplatform

See merge request briar/briar!1785
2023-03-10 16:28:33 +00:00
akwizgran
462f57c966 Upgrade handshake protocol to new key agreement method. 2023-03-10 16:05:59 +00:00
akwizgran
8d20c5d8b8 Reify RecordPredicate for easier testing. 2023-03-10 15:15:29 +00:00
Sebastian Kürten
73d806f8b9 Backport OS-check logic from Compose Multiplatform 2023-03-09 17:03:08 +01:00
akwizgran
f1ae57b213 Merge branch 'mailbox-fix' into 'master'
Fix mailbox integration tests

See merge request briar/briar!1784
2023-03-09 15:42:22 +00:00
Torsten Grote
cae9efb4bf Fix integration tests by using dynamic webserver port of mailbox 2023-03-09 12:29:48 -03:00
Torsten Grote
39ac737015 Merge branch 'no-personalized-learning' into 'master'
Set "no personalized learning" flag for all text input

See merge request briar/briar!1783
2023-03-09 14:14:11 +00:00
akwizgran
edd3310d03 Set "no personalized learning" flag for all text input. 2023-03-09 10:52:46 +00:00
akwizgran
a09d88daa8 Add Slovak to list of available languages. 2023-03-09 09:53:43 +00:00
akwizgran
3dc984659d Update translations. 2023-03-09 09:41:02 +00:00
akwizgran
f580525734 Require obsolete Bluetooth permission on API 32 (and counting). 2023-03-06 17:46:34 +00:00
akwizgran
fbf0f63ff7 Merge branch 'introduction-manager-txn' into 'master'
Transactional versions for introduction manager and private group invitation manager

See merge request briar/briar!1781
2023-03-06 12:08:34 +00:00
ialokim
ee9234e12e transactional versions for GroupInvitationManager 2023-03-05 22:10:50 +01:00
akwizgran
2657e2bc08 Merge branch '2245-toast-name-wrong' into 'master'
Remove wrong name from "Contact already exists"

Closes #2245

See merge request briar/briar!1780
2023-02-27 14:26:27 +00:00
Torsten Grote
3c40c11dfb remove wrong name from "Contact already exists" 2023-02-27 10:43:12 -03:00
akwizgran
3bdbabf38a Merge branch 'no-longer-use-deprecated-double-valueof' into 'master'
No longer use deprecated Double.valueOf()

See merge request briar/briar!1779
2023-02-27 12:45:01 +00:00
Sebastian Kürten
a378c24af8 No longer use deprecated Double.valueOf() 2023-02-27 12:22:27 +01:00
ialokim
b09ea495e7 add transactional versions to introductionManager and privateGroupManager 2023-02-24 18:43:08 +01:00
akwizgran
070165f608 Bump version numbers for 1.4.23 release. 2023-02-24 14:04:57 +00:00
Torsten Grote
445f174275 Merge branch 'update-tor-bridges' into 'master'
Update Tor bridges

See merge request briar/briar!1778
2023-02-24 13:28:27 +00:00
akwizgran
ea5af72878 Add some non-default bridges. 2023-02-24 12:31:22 +00:00
akwizgran
ecf2e75424 Remove some bridges not known to Onionoo. 2023-02-24 12:30:24 +00:00
akwizgran
feebd89029 Remove some failing bridges. 2023-02-24 12:23:37 +00:00
akwizgran
cf723f8002 Merge branch 'dont-unpack-tor' into 'master'
Upgrade tor, obfs4proxy, snoflake and convert tor to regular dependencies in bramble-java

See merge request briar/briar!1775
2023-02-24 12:13:31 +00:00
akwizgran
b8e743021c Update translations. 2023-02-24 12:11:58 +00:00
Sebastian Kürten
b785b6c10f Upgrade tor 2023-02-24 13:05:46 +01:00
Sebastian Kürten
26ec200f50 Convert tor to regular dependencies 2023-02-24 12:51:50 +01:00
akwizgran
82efb0d044 Upgrade Tor, obfs4 and snowflake; use new artifact layout. 2023-02-23 16:25:08 +01:00
akwizgran
4ac4ba13d4 Merge branch 'split-app' into 'master'
Split out APP for check_reproducibility CI job

See merge request briar/briar!1777
2023-02-22 17:06:31 +00:00
Torsten Grote
0844cd3547 Split out APP for check_reproducibility CI job 2023-02-21 16:14:02 -03:00
Torsten Grote
69e6648ded Merge branch '2415-check-bt-socket-streams-not-null' into 'master'
Check that BluetoothSocket's input and output streams aren't null

Closes #2415

See merge request briar/briar!1776
2023-02-21 13:38:49 +00:00
akwizgran
518aeb38b9 Check that BluetoothSocket's input and output streams aren't null. 2023-02-21 13:29:35 +00:00
akwizgran
7e5e61fc05 Merge branch 'dont-package-all-snowflake-architectures-into-headless-jars' into 'master'
Don't package all snowflake architectures into headless jars

See merge request briar/briar!1774
2023-02-21 11:34:04 +00:00
Sebastian Kürten
6ecb44bcaa Don't package all snowflake architectures into headless jars 2023-02-21 09:38:24 +01:00
akwizgran
f02bbebf6c Bump version numbers for 1.4.22 release. 2023-02-20 17:29:41 +00:00
akwizgran
b8612715f8 Merge branch 'check_repro' into 'master'
Fix variable substitution for check_reproducibility

See merge request briar/briar!1773
2023-02-20 17:26:25 +00:00
Torsten Grote
b86ddfa22f Fix variable substitution for check_reproducibility 2023-02-20 14:08:19 -03:00
akwizgran
0dd4d86f4a Bump version numbers for 1.4.21 release. 2023-02-20 16:00:45 +00:00
akwizgran
17e0829f42 Update translations. 2023-02-20 16:00:05 +00:00
Torsten Grote
938d8b71a0 Merge branch 'bdf-cleanup' into 'master'
Clean up some BDF quirks

See merge request briar/briar!1772
2023-02-20 14:15:47 +00:00
akwizgran
1b808584b6 Replace some more longs with ints. 2023-02-20 13:53:40 +00:00
akwizgran
36db5b48ef Remove methods for manually reading lists and dictionaries. 2023-02-20 13:05:38 +00:00
akwizgran
ccd6ed9ff0 Add fast path for writing BdfDictionaries. 2023-02-20 11:56:13 +00:00
akwizgran
0ced10b3a9 Use getInt() in a couple more places. 2023-02-20 11:33:48 +00:00
akwizgran
98064e9efe Remove BdfWriter methods for manually constructing lists and dicts. 2023-02-18 17:36:02 +00:00
akwizgran
63172ef2e4 Add 32-bit int methods to BdfList and BdfDictionary.
We use these a lot so it's useful to have built-in support.

Also refactor BdfList and BdfDictionary so the getters that take default values behave like the other getters. This simplifies the semantics and allows duplicated code to be removed.

Add comprehensive tests for BdfList and BdfDictionary.
2023-02-18 17:36:02 +00:00
akwizgran
7a854e70cb Add BdfReader methods for 32-bit ints.
We use these a lot so it's convenient to have built-in support.

Also make BdfReaderImpl and BdfWriterImpl final to enable compiler optimisations.
2023-02-18 17:36:02 +00:00
akwizgran
ac8a4db457 Add support for reading and writing BDF in canonical form.
Existing transport property updates may not be in canonical form, so we need to parse them leniently.
2023-02-18 17:36:02 +00:00
akwizgran
5a09530670 Reject invalid UTF-8 instead of ignoring it. 2023-02-18 17:10:57 +00:00
akwizgran
4fe91bacc6 Merge branch 'sync-record-reader-tests' into 'master'
Add some tests for sync record reader

See merge request briar/briar!1771
2023-02-17 17:38:04 +00:00
akwizgran
7f70a1519b Make message fields local. 2023-02-17 17:28:10 +00:00
akwizgran
c92ee0458e Add some tests for sync record reader. 2023-02-17 17:19:59 +00:00
akwizgran
10b1fe756d Merge branch 'reproduce-headless' into 'master'
Check reproducibility of headless releases

See merge request briar/briar!1769
2023-02-13 16:21:50 +00:00
Torsten Grote
1a2a250be0 Check reproducibility of headless releases 2023-02-10 16:43:01 -03:00
akwizgran
a621b8077e Merge branch 'update-reproducer-release-tag' into 'master'
Update briar-reproducer release tag

See merge request briar/briar!1768
2023-02-10 14:17:15 +00:00
akwizgran
19084d4060 Merge branch 'mailbox-version-mismatch' into 'master'
Show mailbox version issues before connection failures

See merge request briar/briar!1767
2023-02-10 13:57:36 +00:00
akwizgran
2f73ee1b57 Update briar-reproducer release tag. 2023-02-10 13:54:44 +00:00
Torsten Grote
45fa12c0b3 Show mailbox version issues before connection failures 2023-02-09 13:10:02 -03:00
akwizgran
4253bbaaf5 Update translations. 2023-02-06 12:40:04 +00:00
akwizgran
8c2e58796b Merge branch 'mailbox-convert-qr' into 'master'
Add convenience method for converting mailbox pairing text into QR code payload

See merge request briar/briar!1766
2023-02-03 14:34:04 +00:00
Torsten Grote
3f13e7e9c3 Add convenience method for converting mailbox pairing text into QR code payload 2023-02-03 11:18:25 -03:00
akwizgran
421a93b9a6 Merge branch 'rss-from-file' into 'master'
Allow to import RSS feeds from a file

See merge request briar/briar!1765
2023-01-31 13:17:21 +00:00
Torsten Grote
8a088638db Don't show success fragment for RSS file import 2023-01-31 09:57:51 -03:00
Torsten Grote
a888c5f632 Allow to import RSS feeds from a file 2023-01-30 15:31:25 -03:00
Torsten Grote
0b94814620 Merge branch 'remove-migration-code' into 'master'
Remove various bits of code whose migration periods have passed

See merge request briar/briar!1750
2023-01-30 13:59:02 +00:00
akwizgran
e82e11acfa Merge branch '2384-mailbox-problem-notification' into 'master'
Clear mailbox problem notification after unlinking

Closes #2384

See merge request briar/briar!1764
2023-01-27 15:09:27 +00:00
Torsten Grote
795461d9a8 Clear mailbox problem notification after unlinking 2023-01-27 11:49:01 -03:00
Torsten Grote
7b8d01cfe0 Merge branch '1822-rss-feeds-backend' into 'master'
Resolve "Import RSS feeds shared by other apps"

See merge request briar/briar!1763
2023-01-25 11:39:34 +00:00
akwizgran
abd04ee7f5 Add tests for feed serialisation/deserialisation. 2023-01-24 17:27:52 +00:00
akwizgran
cc5365eaf0 Remove redundant comparison from test. 2023-01-24 17:27:34 +00:00
akwizgran
6b20b03698 Bump version numbers for 1.4.20 release. 2023-01-24 15:51:48 +00:00
akwizgran
9da7fbf4f6 Update translations. 2023-01-24 15:51:26 +00:00
akwizgran
f64f442fcf Merge branch 'add-comment-for-is-connected' into 'master'
Add comment about NetworkInfo#isConnected()

See merge request briar/briar!1762
2023-01-24 15:25:52 +00:00
akwizgran
6eda2f6d13 AnimalSniffer doesn't allow StandardCharsets in tests. 2023-01-24 14:50:40 +00:00
akwizgran
6faa095dfb FeedMatcher interface doesn't need to be public. 2023-01-24 14:48:55 +00:00
akwizgran
4007fca668 Add integration tests for importing an RSS feed from a file. 2023-01-24 14:15:03 +00:00
akwizgran
28a747f7f3 Add method for adding an RSS feed from an input stream. 2023-01-24 13:57:44 +00:00
Sebastian Kürten
fd2d5c9173 Add comment about NetworkInfo#isConnected() 2023-01-24 14:48:03 +01:00
akwizgran
8f7bb9d26b Don't overwrite the list of feeds after fetching. 2023-01-24 13:28:22 +00:00
akwizgran
dc220200b6 Match newly added RSS feeds to existing feeds. 2023-01-24 12:43:14 +00:00
Torsten Grote
0cea137d75 Merge branch 'update-tor-bridges' into 'master'
Update Tor bridges

See merge request briar/briar!1761
2023-01-23 15:06:28 +00:00
akwizgran
2eef34f424 Use new transaction wrappers. 2023-01-23 13:02:16 +00:00
akwizgran
a68fff9dd2 Merge branch 'tor-0.4.7.13' into 'master'
Upgrade Tor to 0.4.7.13

See merge request briar/briar!1760
2023-01-23 12:11:32 +00:00
akwizgran
ddc8f4a7d7 Add three non-default obfs4 bridges. 2023-01-20 16:12:47 +00:00
akwizgran
f961b6a80b Remove three failing bridges. 2023-01-20 16:11:11 +00:00
akwizgran
93439d9c17 Update translations. 2023-01-20 15:50:28 +00:00
akwizgran
f3ee884816 Upgrade Tor to 0.4.7.13. 2023-01-20 15:34:23 +00:00
akwizgran
8ca22043cf Merge branch '1897-sharing-status' into 'master'
Introduce SharingStatus to report more fine-grained status

Closes #1897

See merge request briar/briar!1758
2023-01-20 14:33:32 +00:00
Torsten Grote
9353b78da8 Clarify sharing state docs 2023-01-20 11:13:35 -03:00
Torsten Grote
429bbe1275 Introduce more sharing states 2023-01-20 11:13:35 -03:00
Torsten Grote
c5fb1416bd Update JavaDoc for SharingState change 2023-01-20 11:13:34 -03:00
Torsten Grote
e52cbd896e Introduce SharingStatus to report more fine-grained status 2023-01-20 11:13:34 -03:00
akwizgran
ab1b8784b7 Merge branch '90-clickable-links' into 'master'
Resolve "Handle Hyperlinks (Clickable Links)"

Closes #90

See merge request briar/briar!1757
2023-01-20 13:47:08 +00:00
akwizgran
55a4daa92f Merge branch 'progressbar-remove-contact' into 'master'
Show progress bar while removing contact

See merge request briar/briar!1759
2023-01-20 13:44:29 +00:00
akwizgran
e52250f1e4 Don't sort list of RSS feeds in UI. 2023-01-18 15:04:38 +00:00
akwizgran
33d01aac8c Add matcher for matching an imported feed against existing feeds. 2023-01-18 15:04:38 +00:00
akwizgran
b920382e44 Store additional properties of RSS feed in metadata. 2023-01-18 15:04:38 +00:00
akwizgran
1a2f85f701 Small code cleanups for feed manager, don't fetch new feeds twice. 2023-01-18 15:04:33 +00:00
Airplane Mode
186bcc0b47 Show progress bar while removing contact 2023-01-16 23:56:26 +00:00
Torsten Grote
8b9140f477 Merge branch 'tor-0.4.7.12' into 'master'
Upgrade Tor to 0.4.7.12

See merge request briar/briar!1755
2023-01-13 16:25:42 +00:00
Katelyn Dickey
f959c32935 Remove autoLink attribute which was causing warnings to show twice, and highlight links in comments before a blog is expanded 2023-01-05 17:20:40 -05:00
akwizgran
1c060bc6db Upgrade Tor to 0.4.7.12. 2023-01-04 17:51:46 +00:00
Katelyn Dickey
5e44e4d308 Add clickable links to blog comments 2023-01-03 20:52:36 -05:00
Katelyn Dickey
75d5dec45f Add clickable links to notices/requests 2023-01-03 18:38:13 -05:00
Katelyn Dickey
d825227eb5 Add clickable links to threads (forums/groups) 2023-01-03 18:38:07 -05:00
Katelyn Dickey
967dd1f18d Add clickable links for conversations 2023-01-03 18:37:40 -05:00
akwizgran
4a4147b563 Bump version numbers for 1.4.19 release. 2022-12-30 11:15:32 +00:00
akwizgran
08b72af647 Update translations. 2022-12-30 11:07:38 +00:00
akwizgran
528e090c6f Merge branch '2409-require-obsolete-bluetooth-permission' into 'master'
Require obsolete BLUETOOTH permission on API 31

Closes #2409

See merge request briar/briar!1754
2022-12-30 10:56:29 +00:00
akwizgran
652f9e5705 Require obsolete BLUETOOTH permission on API 31.
This is a workaround for a platform bug on Xiaomi/Redmi/POCO devices that still checks for the obsolete permission.
2022-12-28 14:12:30 +00:00
akwizgran
6a91ec7a6b Merge branch '2407-bluetooth-permission' into 'master'
Always check Bluetooth permission when trying to get own address

Closes #2407

See merge request briar/briar!1753
2022-12-28 11:07:31 +00:00
akwizgran
c3a9eff96b Always check Bluetooth permission when trying to get own address. 2022-12-22 17:46:12 +00:00
akwizgran
bd05d893eb Merge branch '2397-wrong-type-of-qr-code' into 'master'
Tweak text for unknown QR code type

See merge request briar/briar!1752
2022-12-21 12:29:48 +00:00
akwizgran
6965bc0acd Tweak text for unknown QR code type. 2022-12-21 12:19:31 +00:00
akwizgran
c6e9554026 Merge branch '2397-wrong-type-of-qr-code' into 'master'
Show appropriate error message if user scans wrong kind of QR code

Closes #2397

See merge request briar/briar!1748
2022-12-19 15:43:16 +00:00
akwizgran
ab8734e373 Show relevant message when contact QR code has unknown format. 2022-12-19 10:24:58 +00:00
akwizgran
267956b36c Restore javadoc for qrCodeTooOld flag. 2022-12-19 10:04:55 +00:00
akwizgran
ec84ddb38b Merge branch '2403-show-progress-while-connecting-to-mailbox' into 'master'
Show progress while connecting to mailbox

Closes #2403

See merge request briar/briar!1747
2022-12-14 12:20:43 +00:00
akwizgran
ba2db48d8e Center text, add margin at bottom to center layout. 2022-12-14 12:03:06 +00:00
akwizgran
186f61f771 Set width of text views to 0dp so margins are applied. 2022-12-12 16:14:34 +00:00
akwizgran
47971517cd Bump version numbers for 1.4.18 release. 2022-12-12 14:03:52 +00:00
akwizgran
8db182d7e5 Update translations. 2022-12-12 14:03:01 +00:00
akwizgran
d44a609d0c Merge branch '2405-bonded-devices' into 'master'
Don't try to get bonded Bluetooth devices on API 31+

See merge request briar/briar!1751
2022-12-12 13:58:21 +00:00
akwizgran
0a1892d39f Merge branch 'do-not-crash-when-tor-crashes' into 'master'
Don't crash when the Tor process crashes

See merge request briar/briar!1749
2022-12-12 11:04:52 +00:00
akwizgran
9b092da37a Don't try to get bonded Bluetooth devices on API 31+. 2022-12-07 18:38:36 +00:00
akwizgran
7a3ffcbae6 Remove various bits of code whose migration periods have passed. 2022-12-07 17:47:02 +00:00
akwizgran
852e2c29e3 Don't crash when the Tor process crashes. 2022-12-07 17:28:33 +00:00
akwizgran
1b087d59d4 Merge branch '2400-outline-buttons' into 'master'
Use outlined button style

Closes #2400

See merge request briar/briar!1746
2022-12-07 16:54:34 +00:00
akwizgran
30ce8651b5 Fix ripple effect for outlined buttons on API 21+. 2022-12-07 15:50:56 +00:00
akwizgran
80a8ee4de9 Fix button inheritance. 2022-12-07 11:16:34 +00:00
akwizgran
354f3bc1cf Use chain so that margins are enforced. 2022-12-07 11:13:42 +00:00
akwizgran
1e6b018ff4 Add corner radius and increase top inset. 2022-12-07 11:03:46 +00:00
akwizgran
eba489bb98 Merge branch 'project-dependencies' into 'master'
Refactor dependencies to satisfy Android Studio's linter

See merge request briar/briar!1745
2022-12-05 14:54:12 +00:00
akwizgran
2bfdcaaa42 Declare dependencies for custom jar tasks. 2022-12-02 18:05:28 +00:00
akwizgran
c2e71ef52f Remove configuration: default, make transitive dependencies explicit. 2022-12-02 17:43:52 +00:00
akwizgran
9ee8fe74ba Export bramble/briar-api as API of bramble/briar-core. 2022-12-02 15:53:23 +00:00
akwizgran
95d8783852 Show appropriate error message if contact QR code is scanned. 2022-12-02 14:27:42 +00:00
akwizgran
b4f3604584 Show appropriate error message if mailbox QR code is scanned. 2022-12-02 13:35:00 +00:00
akwizgran
badccac90c Factor out recognition of QR code format. 2022-12-02 13:35:00 +00:00
akwizgran
1b8d1a5a8d Update test expectations. 2022-11-30 17:30:33 +00:00
akwizgran
2fe57d2597 Show progress while connecting to mailbox. 2022-11-30 17:17:08 +00:00
akwizgran
904d5b2ce2 Remove unused dimension. 2022-11-30 10:58:44 +00:00
akwizgran
1911b3dd97 Make OfflineFragment suitable for small screens. 2022-11-30 10:44:39 +00:00
akwizgran
bd430a1009 Use outlined button style for secondary actions. 2022-11-30 10:33:11 +00:00
akwizgran
c16d0e8f45 Refactor dependencies to satisfy Android Studio's linter.
If an Android module depends on another module's default configuration, Android Studio's linter won't recognise references to classes in the other module. Instead, the Android module must depend on the other module without specifying a configuration. This entails some changes in the handling of transitive dependencies, and the other module must include its main classes in its testOutput artifact so the Android module's tests can use them.
2022-11-29 13:35:29 +00:00
akwizgran
847273c558 Merge branch 'transactions-forum' into 'master'
Add transactional versions to functions related to forums

See merge request briar/briar!1743
2022-11-23 17:47:59 +00:00
ialokim
b9bac8b6a5 add transactional versions to functions related to forums 2022-11-23 18:37:07 +01:00
akwizgran
c855967d56 Bump version numbers for 1.4.17 release. 2022-11-14 10:41:58 +00:00
Torsten Grote
bae97e3312 Merge branch 'unpack-tor-binaries-earlier' into 'master'
Unpack Tor binaries earlier to avoid issues with task order

See merge request briar/briar!1742
2022-11-11 18:21:31 +00:00
akwizgran
f1be3031a7 Unpack Tor binaries earlier to avoid issues with task order. 2022-11-11 15:28:21 +00:00
akwizgran
3173486b3b Bump version numbers for 1.4.16 release. 2022-11-10 14:55:11 +00:00
akwizgran
c445b21d58 Update translations. 2022-11-10 14:54:30 +00:00
akwizgran
9a16cf6e54 Update translations. 2022-11-07 17:52:57 +00:00
akwizgran
a22990c1ed Merge branch 'illustration-revert' into 'master'
Don't change icons for thinner versions

See merge request briar/briar!1740
2022-11-07 13:56:42 +00:00
Torsten Grote
8262fa183b Revert "Replace illustration for mailbox success"
This reverts commit 65509137
2022-11-07 10:05:09 -03:00
akwizgran
c3f3c6211d Merge branch 'mailbox-integration-tests' into 'master'
First integration test for mailbox with two contacts

See merge request briar/briar!1725
2022-11-07 12:58:18 +00:00
Torsten Grote
0c40f39a90 Revert "Replace illustration for error fragment"
This reverts commit dab8d731
2022-11-07 09:53:19 -03:00
Torsten Grote
20b9aa86f7 revert icon changes 2022-11-07 09:53:19 -03:00
Torsten Grote
a00c920382 Merge branch 'update-play-store-translations' into 'master'
Update Play Store translations and config

See merge request briar/briar!1739
2022-11-04 17:36:08 +00:00
akwizgran
e40d6552bc Merge branch 'fix-fastlane-metadata' into 'master'
Execute Transifex for fastlane metadata from correct directory

See merge request briar/briar!1738
2022-11-04 17:09:36 +00:00
Torsten Grote
5e1564de6c don't insist on 2 uploaded messages in case Bob deletes one of them quickly 2022-11-04 13:53:58 -03:00
Torsten Grote
155daae8d0 Execute Transifex for fastlane metadata from correct directory 2022-11-04 13:19:23 -03:00
Torsten Grote
6680abf925 Make MailboxIntegrationTest a bit more thorough
by checking, after adding the contact to the mailbox but before creating the message, that the first file containing the mailbox update gets uploaded. Then after creating the message, the second file should be uploaded.
2022-11-04 12:01:00 -03:00
akwizgran
9bbfea525a Merge branch '2370-fix-readme-for-headless-jar' into 'master'
Update instructions on how to build and run briar-headless

Closes #2370

See merge request briar/briar!1726
2022-11-04 13:01:53 +00:00
akwizgran
979ef077b3 Update Play Store translations and config. 2022-11-04 12:51:49 +00:00
Torsten Grote
b7e1a987fc Don't depend on briar for mailbox integration tests
Use transport properties instead of sending private messages
2022-11-03 10:57:06 -03:00
Torsten Grote
a705caa5fa Add better logging for integration tests by injecting a ThreadFactory that can set thread names 2022-11-02 13:25:30 -03:00
akwizgran
441b28fede Merge branch 'remove-jcenter' into 'master'
Remove jcenter repository from gradle files

See merge request briar/briar!1736
2022-11-01 13:18:17 +00:00
Torsten Grote
9c95534f39 Merge branch 'merge-redundant-strings' into 'master'
Merge redundant strings

See merge request briar/briar!1737
2022-11-01 13:17:04 +00:00
Torsten Grote
57015c36b2 Re-format witness.gradle to make it easier to see what changed 2022-11-01 09:57:48 -03:00
akwizgran
a2815c75a3 Merge redundant strings. 2022-11-01 12:53:52 +00:00
Torsten Grote
9ce82af856 Merge branch '348-add-hint-to-scan-both-qr-codes' into 'master'
Add hints that both users need to scan each other's QR codes/add each other's links

See merge request briar/briar!1734
2022-11-01 12:49:39 +00:00
Torsten Grote
4b792ff040 Remove jcenter repo from gradle files 2022-11-01 09:48:39 -03:00
Torsten Grote
904355b0a6 Replace khttp test library with a fork that is available on maven central 2022-11-01 09:48:38 -03:00
Torsten Grote
02f2fdd4a1 Vendorize TrustedIntents library and upgrade screengrab 2022-11-01 09:48:38 -03:00
akwizgran
9f039ff0b8 Address review feedback. 2022-11-01 12:23:26 +00:00
akwizgran
ba83290fcd Add a hint that both parties need to add each other's links. 2022-11-01 12:23:26 +00:00
Torsten Grote
05f84000b3 Merge branch 'testdatacreator-featureflags' into 'master'
Prevent crash in TestDataCreator if blogs or forums are not enabled in core

Closes briar-desktop#420

See merge request briar/briar!1735
2022-11-01 12:18:35 +00:00
akwizgran
7302bf9d7a Add a hint that both parties need to scan each other's QR codes. 2022-11-01 12:05:28 +00:00
akwizgran
8c269541c3 Merge branch 'illustration-revamp' into 'master'
Illustration revamp

See merge request briar/briar!1722
2022-11-01 11:50:29 +00:00
Torsten Grote
324ca1b50b Address review feedback 2022-10-31 18:16:27 -03:00
akwizgran
79730484c0 Merge branch 'android-12' 2022-10-31 13:56:21 +00:00
akwizgran
86fb648dae Merge branch 'client-version-update-events' into 'master'
Send ClientVersionUpdatedEvent for each client state change, not only on version updates

See merge request briar/briar!1724
2022-10-31 12:36:25 +00:00
Torsten Grote
52809d8f2d Add permission rationale for camera and Bluetooth combined 2022-10-27 10:47:06 -03:00
Torsten Grote
0a906998fe Address review feedback 2022-10-27 10:47:06 -03:00
Torsten Grote
4a65bc1726 Update some libraries 2022-10-27 10:43:30 -03:00
Torsten Grote
f395ab1cb5 Disable our splash screen on Android 11+
in order to avoid two splash screens from being shown.
2022-10-27 10:42:41 -03:00
Torsten Grote
e6c051fee4 Require location for hotspot on Android 12+
This seems to be necessary. Without the location turned on, the hotspot does not start showing a p2p error.
2022-10-27 10:42:41 -03:00
Torsten Grote
e76701f988 Add current AppStandbyBucket to BriarReportCollector 2022-10-27 10:42:41 -03:00
Torsten Grote
e6616a8c36 Exclude all files from D2D transfers 2022-10-27 10:42:40 -03:00
Torsten Grote
824a9e1124 Handle new BLUETOOTH_SCAN and BLUETOOTH_CONNECT permission
We need to have those permissions before doing things like accessing the Bluetooth address. So we force-disable the Bluetooth plugin if the permission is not granted. The UI then forces the permission before allowing to enable the plugin.
2022-10-27 10:42:40 -03:00
Torsten Grote
113793045f Set pending intents to be immutable 2022-10-27 10:42:40 -03:00
Torsten Grote
c04937b1fa Do export only activities that need to react to external intents
For some reason SettingsActivity does not need to be exported for it to be launched from system app settings.

androidx.test.ext:junit needed to be upgraded because it somehow brought in an activity without exported attribute
2022-10-27 10:42:40 -03:00
Torsten Grote
e8994d503e Bump targetSdk to 31 (Android 12) 2022-10-27 10:42:38 -03:00
ialokim
768bb6fc64 send ClientVersionUpdatedEvent for each client state change, not only on version updates 2022-10-27 11:45:46 +02:00
Torsten Grote
645eba7fe7 Replace illustration for add contact nearby error 2022-10-25 15:49:04 -03:00
Torsten Grote
c76ed41958 Replace illustration for share app offline intro 2022-10-25 15:49:04 -03:00
Torsten Grote
4a2c1113c1 Replace illustration for crash 2022-10-25 15:49:04 -03:00
Torsten Grote
b6f78a8667 Replace illustration for connecting via Bluetooth 2022-10-25 15:49:03 -03:00
ialokim
53c7c81c0f prevent crash in testDataCreator when blogs or forums are not enabled in core 2022-10-25 10:47:03 +02:00
Torsten Grote
6dd250a1ed Merge branch 'only-retry-bridges-that-have-failed' into 'master'
Speed up BridgeTest by only retrying bridges that have failed

See merge request briar/briar!1732
2022-10-21 16:46:22 +00:00
akwizgran
87df641b5d Bump version numbers for 1.4.15 release. 2022-10-21 17:18:01 +01:00
akwizgran
a56a70a947 Merge branch 'update-bridges' into 'master'
Update bridges

See merge request briar/briar!1731
2022-10-21 16:16:26 +00:00
Torsten Grote
2e2c720241 Replace illustration for transfer data onboarding 2022-10-21 12:25:19 -03:00
Torsten Grote
7e3cf8f162 Replace illustration for mailbox problem 2022-10-21 12:25:19 -03:00
Torsten Grote
dab8d731fa Replace illustration for error fragment 2022-10-21 12:25:19 -03:00
Torsten Grote
65509137b6 Replace illustration for mailbox success 2022-10-21 12:25:19 -03:00
Torsten Grote
48ab5f4966 Replace illustration for mailbox download 2022-10-21 12:25:19 -03:00
Torsten Grote
a37447d3e8 Replace illustration for mailbox onboarding 2022-10-21 12:25:18 -03:00
Torsten Grote
5d1d0fb12a Replace illustration for adding contacts nearby 2022-10-21 12:25:18 -03:00
Torsten Grote
790818623f Replace illustration for adding a nickname for pending contact 2022-10-21 12:25:18 -03:00
Torsten Grote
d46a227cfc Add new illustration for adding contact remotely 2022-10-21 12:25:18 -03:00
Torsten Grote
e986d4b214 Replace empty state images with new illustrations 2022-10-21 12:25:18 -03:00
Torsten Grote
7bcffdf0d1 Replace illustration for sending data from removable drive 2022-10-21 12:25:18 -03:00
Torsten Grote
f4dd3c4f06 Replace illustration for receiving data from removable drive 2022-10-21 12:25:17 -03:00
Torsten Grote
f42cf00c35 Fix BriarButton rendering in AS EditMode
loses the style, but at least there's a preview now
2022-10-21 12:25:17 -03:00
Torsten Grote
38c347552b Add UiUtils for hiding illustrations on small screens 2022-10-21 12:25:17 -03:00
Torsten Grote
bab6ec70f5 Factor out mailbox constants into a MailboxConfig
so that we can change them for integration tests via the new ModularMailboxModule that now also includes the UrlProvider
2022-10-21 12:22:57 -03:00
akwizgran
8db25738e2 Speed up BridgeTest by only retrying bridges that have failed. 2022-10-21 16:02:44 +01:00
Torsten Grote
28f770df89 Always run mailbox tests when changing them 2022-10-21 10:01:32 -03:00
Torsten Grote
a720501fde First integration test for mailbox with two contacts
one private message gets send via mailbox from one contact to the other
2022-10-21 10:01:32 -03:00
Torsten Grote
648911b3ed clean up mailbox integration tests 2022-10-21 10:01:31 -03:00
akwizgran
3767aeb8b2 Add some non-default and vanilla bridges. 2022-10-21 13:41:13 +01:00
akwizgran
6344e29c29 Remove some failing bridges. 2022-10-21 13:34:32 +01:00
Torsten Grote
3734e36782 Merge branch 'obfs4proxy-0.0.14-tor1' into 'master'
Upgrade obfs4proxy to 0.0.14-tor1 and enable uTLS for meek-lite

See merge request briar/briar!1730
2022-10-21 12:03:49 +00:00
akwizgran
48ac5e2bc5 Upgrade obfs4proxy to 0.0.14-tor1 and enable uTLS for meek-lite. 2022-10-21 12:33:31 +01:00
akwizgran
404e30bb0f Bump version numbers for 1.4.14 release. 2022-10-20 15:25:58 +01:00
Torsten Grote
6a5024e8a2 Merge branch 'update-meek-bridge' into 'master'
Update meek bridge

See merge request briar/briar!1729
2022-10-20 14:24:23 +00:00
akwizgran
f19c636ddb Update meek bridge. 2022-10-20 11:20:45 +01:00
akwizgran
45833a2ec0 Bump version numbers for 1.4.13 release. 2022-10-19 18:02:22 +01:00
Torsten Grote
55efb5f41d Merge branch 'snowflake-utls' into 'master'
Use uTLS with Chrome profile for Snowflake

See merge request briar/briar!1728
2022-10-19 17:00:33 +00:00
akwizgran
6ec0fba5a2 Update translations. 2022-10-19 17:58:05 +01:00
akwizgran
1eb39eeea8 Use uTLS with Chrome profile for Snowflake. 2022-10-19 17:41:07 +01:00
akwizgran
bc9c4c9e3f Merge branch 'add-test-lan-tcp-plugin-factory' into 'master'
Add TestLanTcpPluginFactory

See merge request briar/briar!1723
2022-10-18 11:17:43 +00:00
Sebastian Kürten
ab6c925a9c Update instructions on how to build and run briar-headless 2022-10-14 16:39:44 +02:00
Sebastian Kürten
3844d33015 Add TestLanTcpPluginFactory
This factory provides a LanTcpPlugin that can connect to its own
address, useful for testing.
2022-10-06 12:07:07 +02:00
Torsten Grote
718d95f3d5 Merge branch 'use-mailbox-main' into 'master'
Use mailbox main branch for integration tests

See merge request briar/briar!1721
2022-10-03 14:38:32 +00:00
Sebastian Kürten
fa425bdc53 Use mailbox main branch for integration tests 2022-10-03 15:44:25 +02:00
Torsten Grote
d441618ea1 Merge branch 'fix-imports-null-safety' into 'master'
Fix imports for null-safety annotations

See merge request briar/briar!1720
2022-10-03 13:38:58 +00:00
Sebastian Kürten
df86f2f258 Fix imports for null-safety annotations 2022-10-03 15:25:35 +02:00
Torsten Grote
2a2c054959 Merge branch '2343-mailbox-as-submodule' into 'master'
End-to-end integration tests for communication via mailbox

Closes #2343

See merge request briar/briar!1699
2022-10-03 13:11:18 +00:00
akwizgran
ad9092f414 Merge branch '2358-unlink-dialog-blank' into 'master'
Re-show mailbox unpaired dialog after screen-rotation

Closes #2358

See merge request briar/briar!1718
2022-09-30 12:01:35 +00:00
akwizgran
78ed21b493 Merge branch '2367-mailbox-intro-duplicate' into 'master'
Don't re-add mailbox intro fragment after activity got destroyed

Closes #2367

See merge request briar/briar!1719
2022-09-30 09:10:51 +00:00
Torsten Grote
abb4d43f14 Don't re-add mailbox intro fragment after activity got destroyed 2022-09-29 16:43:28 -03:00
Torsten Grote
c049c9c370 re-show mailbox unpaired dialog after screen-rotation 2022-09-29 14:52:30 -03:00
Torsten Grote
a0de0a40aa Merge branch 'socks-library' into 'master'
Use SOCKS socket library

See merge request briar/briar!1717
2022-09-29 16:26:17 +00:00
Torsten Grote
73d957434b Merge branch 'null-safety-library' into 'master'
Use null safety library

See merge request briar/briar!1716
2022-09-29 13:23:19 +00:00
akwizgran
03adfd850b Use SOCKS socket library. 2022-09-29 13:36:52 +01:00
akwizgran
6c1232bfaa Update dependency checksums. 2022-09-29 13:33:54 +01:00
akwizgran
e4e7d84bde Use null safety library. 2022-09-29 13:08:02 +01:00
Torsten Grote
d4e5e3577b Merge branch '2366-tor-not-running-exception' into 'master'
No longer crash when the Tor process crashes

Closes #2366

See merge request briar/briar!1715
2022-09-28 17:04:04 +00:00
Sebastian Kürten
7be83a56a2 Address review feedback 2022-09-28 15:34:16 +02:00
Sebastian Kürten
867703c774 Upgrade mailbox-lib and refactor to match new API 2022-09-28 11:33:57 +02:00
akwizgran
adf172bf25 No longer crash when the Tor process crashes.
We have enough information about this bug now.
2022-09-27 15:20:45 +01:00
Sebastian Kürten
f38f8afc5c Clean up mailbox-integrations-tests/build.gradle 2022-09-22 19:05:01 +02:00
Sebastian Kürten
8be04b3c20 Remove TestIoModule 2022-09-22 18:08:08 +02:00
Sebastian Kürten
459b97c1d4 Integration tests for mailbox using mailbox-lib as submodule 2022-09-22 18:08:03 +02:00
1435 changed files with 21745 additions and 12448 deletions

View File

@@ -5,6 +5,9 @@ stages:
- optional_tests
- check_reproducibility
variables:
GIT_SUBMODULE_STRATEGY: recursive
workflow:
# when to create a CI pipeline
rules:
@@ -32,6 +35,7 @@ test:
extends: .base-test
stage: test
script:
- git submodule update
- ./gradlew -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew -Djava.security.egd=file:/dev/urandom assembleOfficialDebug :briar-headless:linuxJars
- ./gradlew -Djava.security.egd=file:/dev/urandom compileOfficialDebugAndroidTestSources compileScreenshotDebugAndroidTestSources check
@@ -79,42 +83,24 @@ android test:
test_reproducible:
stage: check_reproducibility
script:
- "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"
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[APP]='briar' -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
- "curl -X POST -F token=${RELEASE_JAR_CHECK_TOKEN} -F ref=main -F variables[APP]='briar-headless' -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/307/trigger/pipeline"
only:
- tags
.optional_tests:
mailbox integration test:
stage: optional_tests
extends: .base-test
bridge test:
extends: .optional_tests
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- changes:
- mailbox-integration-tests/**/*
when: on_success
allow_failure: false
- if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: true
script:
- OPTIONAL_TESTS=org.briarproject.bramble.plugin.tor.BridgeTest ./gradlew --info bramble-java:test --tests BridgeTest
timeout: 4h
mailbox integration test:
extends: .optional_tests
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
- if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: true # TODO figure out how not to allow failure while leaving this optional
script:
# start mailbox
- cd /opt && git clone --depth 1 https://code.briarproject.org/briar/briar-mailbox.git briar-mailbox
- cd briar-mailbox
- mkdir -p /root/.local/share # create directory that mailbox (currently) expects to exist
- ./gradlew run --args="--debug --setup-token 54686973206973206120736574757020746f6b656e20666f722042726961722e" &
# run mailbox integration test once mailbox has started
- cd "$CI_PROJECT_DIR"
- bramble-core/src/test/bash/wait-for-mailbox.sh
- OPTIONAL_TESTS=org.briarproject.bramble.mailbox.MailboxIntegrationTest ./gradlew --info bramble-core:test --tests MailboxIntegrationTest
- (cd briar-mailbox; git fetch; git reset --hard origin/main)
- MAILBOX_INTEGRATION_TESTS=true ./gradlew --info mailbox-integration-tests:test

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "briar-mailbox"]
path = briar-mailbox
url = https://code.briarproject.org/briar/briar-mailbox.git

View File

@@ -28,18 +28,11 @@
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>

View File

@@ -1,21 +1,22 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BridgeTest" type="GradleRunConfiguration" factoryName="Gradle">
<configuration default="false" name="All tests in mailbox-integration-tests" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
<entry key="MAILBOX_INTEGRATION_TESTS" value="true" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--tests &quot;org.briarproject.bramble.plugin.tor.BridgeTest&quot;" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-java:test" />
<option value=":mailbox-integration-tests:test" />
<option value=":mailbox-integration-tests:cleanTest" />
</list>
</option>
<option name="vmOptions" value="" />
@@ -25,4 +26,4 @@
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>
</component>

View File

@@ -1,7 +1,7 @@
# Briar
Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate.
Unlike traditional messaging tools such as email, Twitter or Telegram, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices.
Unlike traditional messaging apps, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices.
If the Internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping information flowing in a crisis. If the Internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
@@ -14,14 +14,16 @@ You can also [download the APK file](https://briarproject.org/apk) directly from
our site.
## Useful links
[briarproject.org](https://briarproject.org/)
[Project website](https://briarproject.org/)
[Source code](https://code.briarproject.org/briar/briar/tree/master)
[Manual](https://briarproject.org/manual/)
[User manual](https://briarproject.org/manual/)
[Wiki](https://code.briarproject.org/briar/briar/-/wikis/home)
[Privacy policy](https://briarproject.org/privacy)
## Reproducible builds
We provide [docker images](https://code.briarproject.org/briar/briar-reproducer#briar-reproducer)
@@ -33,5 +35,5 @@ for reproduction.
## Donate
[![Donate using Liberapay](https://briarproject.org/img/liberapay.svg)](https://liberapay.com/Briar/donate) [![Flattr this](https://briarproject.org/img/flattr-badge-large.png "Flattr this")](https://flattr.com/t/592836/)
[![Donate using Liberapay](https://briarproject.org/img/liberapay.svg)](https://liberapay.com/Briar/donate)
Bitcoin and BCH: 1NZCKkUCtJV2U2Y9hDb9uq8S7ksFCFGR6K

View File

@@ -1,25 +1,24 @@
import com.android.build.gradle.tasks.MergeResources
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply from: 'witness.gradle'
android {
compileSdkVersion 30
buildToolsVersion '30.0.3'
compileSdkVersion 33
buildToolsVersion '33.0.0'
packagingOptions {
doNotStrip '**/*.so'
}
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10412
versionName "1.4.12"
minSdkVersion 21
targetSdkVersion 33
versionCode 10510
versionName "1.5.10"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments disableAnalytics: 'true'
}
compileOptions {
@@ -41,8 +40,19 @@ configurations {
}
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
api 'org.briarproject:dont-kill-me-lib:0.2.7'
// In theory this dependency shouldn't be needed, but without it Android Studio's linter will
// complain about unresolved symbols for bramble-api test classes in bramble-android tests,
// even though the bramble-api test classes are provided by the testImplementation dependency
// below and the compiler can find them
implementation project(':bramble-api')
implementation project(':bramble-core')
implementation 'androidx.annotation:annotation:1.5.0'
implementation "org.briarproject:onionwrapper-android:$onionwrapper_version"
tor "org.briarproject:tor-android:$tor_version"
tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version"
tor "org.briarproject:snowflake-android:$snowflake_version"
@@ -52,61 +62,33 @@ dependencies {
compileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-imposters:$jmock_version"
}
def torBinariesDir = 'src/main/res/raw'
def torLibsDir = 'src/main/jniLibs'
task cleanTorBinaries {
outputs.dir torLibsDir
doLast {
delete fileTree(torBinariesDir) { include '*.zip' }
delete fileTree(torLibsDir) { include '**/*.so' }
delete fileTree(torLibsDir)
}
}
clean.dependsOn cleanTorBinaries
task unpackTorBinaries {
outputs.dir torLibsDir
doLast {
configurations.tor.each { outer ->
zipTree(outer).each { inner ->
if (inner.name.endsWith('_arm_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'armeabi-v7a/lib$1.so'
}
} else if (inner.name.endsWith('_arm64_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'arm64-v8a/lib$1.so'
}
} else if (inner.name.endsWith('_x86_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'x86/lib$1.so'
}
} else if (inner.name.endsWith('_x86_64_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'x86_64/lib$1.so'
}
}
}
copy {
from configurations.tor.collect { zipTree(it) }
into torLibsDir
}
}
dependsOn cleanTorBinaries
}
tasks.withType(MergeResources) {
inputs.dir torBinariesDir
inputs.dir torLibsDir
dependsOn unpackTorBinaries
}
preBuild.dependsOn unpackTorBinaries

View File

@@ -1,15 +1,28 @@
<manifest
package="org.briarproject.bramble"
xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.briarproject.bramble">
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- The BLUETOOTH permission was supposed to be removed in API 31 but is still needed on some Xiaomi/Redmi/POCO devices running API 31 and Nubia devices running API 32 -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="31" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="false"

View File

@@ -8,7 +8,9 @@ import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.system.AndroidSystemModule;
import org.briarproject.bramble.system.AndroidTaskSchedulerModule;
import org.briarproject.bramble.system.AndroidWakeLockModule;
import org.briarproject.bramble.system.AndroidWakefulIoExecutorModule;
import org.briarproject.bramble.system.DefaultThreadFactoryModule;
import dagger.Module;
@@ -18,6 +20,8 @@ import dagger.Module;
AndroidSystemModule.class,
AndroidTaskSchedulerModule.class,
AndroidWakefulIoExecutorModule.class,
AndroidWakeLockModule.class,
DefaultThreadFactoryModule.class,
CircumventionModule.class,
DnsModule.class,
ReportingModule.class,

View File

@@ -20,7 +20,6 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
@@ -105,15 +104,11 @@ class AndroidAccountManager extends AccountManagerImpl
}
files.add(appContext.getFilesDir());
addIfNotNull(files, appContext.getExternalCacheDir());
if (SDK_INT >= 19) {
for (File file : appContext.getExternalCacheDirs()) {
addIfNotNull(files, file);
}
for (File file : appContext.getExternalCacheDirs()) {
addIfNotNull(files, file);
}
if (SDK_INT >= 21) {
for (File file : appContext.getExternalMediaDirs()) {
addIfNotNull(files, file);
}
for (File file : appContext.getExternalMediaDirs()) {
addIfNotNull(files, file);
}
// Clear the cache directory but don't delete it
File cacheDir = appContext.getCacheDir();

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.system;
import android.content.Intent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface AlarmListener {

View File

@@ -1,19 +0,0 @@
package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface AndroidWakeLock {
/**
* Acquires the wake lock. This has no effect if the wake lock has already
* been acquired.
*/
void acquire();
/**
* Releases the wake lock. This has no effect if the wake lock has already
* been released.
*/
void release();
}

View File

@@ -1,38 +0,0 @@
package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.concurrent.Executor;
@NotNullByDefault
public interface AndroidWakeLockManager {
/**
* Creates a wake lock with the given tag. The tag is only used for
* logging; the underlying OS wake lock will use its own tag.
*/
AndroidWakeLock createWakeLock(String tag);
/**
* Runs the given task while holding a wake lock.
*/
void runWakefully(Runnable r, String tag);
/**
* Submits the given task to the given executor while holding a wake lock.
* The lock is released when the task completes, or if an exception is
* thrown while submitting or running the task.
*/
void executeWakefully(Runnable r, Executor executor, String tag);
/**
* Starts a dedicated thread to run the given task asynchronously. A wake
* lock is acquired before starting the thread and released when the task
* completes, or if an exception is thrown while starting the thread or
* running the task.
* <p>
* This method should only be used for lifecycle management tasks that
* can't be run on an executor.
*/
void executeWakefully(Runnable r, String tag);
}

View File

@@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
@@ -16,10 +17,17 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import androidx.annotation.RequiresApi;
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.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED;
import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@@ -57,6 +65,12 @@ class AndroidBatteryManager implements BatteryManager, Service {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
filter.addAction(ACTION_POWER_SAVE_MODE_CHANGED);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
if (SDK_INT >= 33) {
filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED);
filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
}
appContext.registerReceiver(batteryReceiver, filter);
}
@@ -76,6 +90,33 @@ class AndroidBatteryManager implements BatteryManager, Service {
eventBus.broadcast(new BatteryEvent(true));
else if (ACTION_POWER_DISCONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(false));
else if (SDK_INT >= 23 &&
ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action) &&
LOG.isLoggable(INFO)) {
LOG.info("Device idle mode changed to: " +
getPowerManager(ctx).isDeviceIdleMode());
} else if (SDK_INT >= 23 &&
ACTION_POWER_SAVE_MODE_CHANGED.equals(action) &&
LOG.isLoggable(INFO)) {
LOG.info("Power save mode changed to: " +
getPowerManager(ctx).isPowerSaveMode());
} else if (SDK_INT >= 33 && LOG.isLoggable(INFO) &&
ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED.equals(action)) {
PowerManager powerManager =
ctx.getSystemService(PowerManager.class);
LOG.info("Low power standby now is: " +
powerManager.isLowPowerStandbyEnabled());
} else if (SDK_INT >= 33 && LOG.isLoggable(INFO) &&
ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(action)) {
PowerManager powerManager = getPowerManager(ctx);
LOG.info("Light idle mode now is: " +
powerManager.isDeviceLightIdleMode());
}
}
}
@RequiresApi(api = 23)
private PowerManager getPowerManager(Context ctx) {
return ctx.getSystemService(PowerManager.class);
}
}

View File

@@ -21,9 +21,9 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.network.NetworkStatus;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -55,8 +55,8 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -118,6 +118,11 @@ class AndroidNetworkManager implements NetworkManager, Service {
try {
NetworkInfo net = connectivityManager.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected();
// Research into Android's behavior to check network connectivity
// (https://code.briarproject.org/briar/public-mesh-research/-/issues/19)
// has shown that NetworkInfo#isConnected() returns true if the device
// is connected to any Wifi, independent of whether any specific IP
// address can be reached using it or any domain names can be resolved.
boolean wifi = false, ipv6Only = false;
if (connected) {
wifi = net.getType() == TYPE_WIFI;

View File

@@ -2,11 +2,11 @@ package org.briarproject.bramble.plugin.bluetooth;
import android.bluetooth.BluetoothSocket;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.plugin.bluetooth;
import android.annotation.SuppressLint;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -10,8 +11,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException;
@@ -20,6 +19,8 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import java.io.IOException;
import java.security.SecureRandom;
@@ -49,16 +50,17 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.shuffle;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@SuppressLint("MissingPermission")
class AndroidBluetoothPlugin extends
AbstractBluetoothPlugin<BluetoothSocket, BluetoothServerSocket> {
@@ -97,6 +99,11 @@ class AndroidBluetoothPlugin extends
this.clock = clock;
}
@Override
protected boolean isBluetoothAccessible() {
return hasBtConnectPermission(app);
}
@Override
public void start() throws PluginException {
super.start();
@@ -247,7 +254,7 @@ class AndroidBluetoothPlugin extends
} else if (ACTION_FOUND.equals(action)) {
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
// Ignore Bluetooth LE devices
if (SDK_INT < 18 || d.getType() != DEVICE_TYPE_LE) {
if (d.getType() != DEVICE_TYPE_LE) {
String address = d.getAddress();
if (LOG.isLoggable(INFO))
LOG.info("Discovered " +

View File

@@ -3,10 +3,10 @@ package org.briarproject.bramble.plugin.bluetooth;
import android.app.Application;
import android.bluetooth.BluetoothSocket;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
@@ -14,9 +14,9 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.nullsafety.NotNullByDefault;
import java.security.SecureRandom;
import java.util.concurrent.Executor;

View File

@@ -2,12 +2,12 @@ package org.briarproject.bramble.plugin.bluetooth;
import android.bluetooth.BluetoothSocket;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLock;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidWakeLock;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.io.InputStream;
@@ -33,8 +33,10 @@ class AndroidBluetoothTransportConnection
super(plugin);
this.connectionLimiter = connectionLimiter;
this.socket = socket;
in = timeoutMonitor.createTimeoutInputStream(
socket.getInputStream(), plugin.getMaxIdleTime() * 2);
InputStream socketIn = socket.getInputStream();
if (socketIn == null) throw new IOException();
in = timeoutMonitor.createTimeoutInputStream(socketIn,
plugin.getMaxIdleTime() * 2L);
wakeLock = wakeLockManager.createWakeLock("BluetoothConnection");
wakeLock.acquire();
String address = socket.getRemoteDevice().getAddress();
@@ -48,7 +50,9 @@ class AndroidBluetoothTransportConnection
@Override
protected OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
OutputStream socketOut = socket.getOutputStream();
if (socketOut == null) throw new IOException();
return socketOut;
}
@Override

View File

@@ -3,9 +3,9 @@ package org.briarproject.bramble.plugin.file;
import android.app.Application;
import android.net.Uri;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -2,11 +2,11 @@ package org.briarproject.bramble.plugin.file;
import android.app.Application;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.plugin.tcp;
import android.annotation.TargetApi;
import android.app.Application;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
@@ -14,10 +13,10 @@ import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.net.InetAddress;
@@ -37,19 +36,18 @@ import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.WIFI_SERVICE;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.emptyList;
import static java.util.Collections.list;
import static java.util.Collections.singletonList;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.DEFAULT_PREF_PLUGIN_ENABLE;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin {
@@ -118,7 +116,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
// If there's no wifi IPv4 address, we might be a client on an
// IPv6-only wifi network. We can only detect this on API 21+
if (wifi == null) {
return SDK_INT >= 21 ? getWifiClientIpv6Address() : null;
return getWifiClientIpv6Address();
}
// Use the wifi IPv4 address to determine which interface's IPv6
// address we should return (if the interface has a suitable address)
@@ -172,7 +170,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
* Returns a link-local IPv6 address for the wifi client interface, or null
* if there's no such interface or it doesn't have a suitable address.
*/
@TargetApi(21)
@Nullable
private InetAddress getWifiClientIpv6Address() {
// https://issuetracker.google.com/issues/175055271
@@ -204,6 +201,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
@Nullable
private InetAddress getIpv6AddressForInterface(InetAddress ipv4) {
try {
// We may get an NPE from getByInetAddress() on Android 11
NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4);
if (iface == null) return null;
for (InetAddress addr : list(iface.getInetAddresses())) {
@@ -211,7 +209,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
// No suitable address
return null;
} catch (SocketException e) {
} catch (SocketException | NullPointerException e) {
logException(LOG, WARNING, e);
return null;
}
@@ -234,7 +232,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
// On API 21 and later, a socket that is not created with the wifi
// network's socket factory may try to connect via another network
private SocketFactory getSocketFactory() {
if (SDK_INT < 21) return SocketFactory.getDefault();
// https://issuetracker.google.com/issues/175055271
try {
for (Network net : connectivityManager.getAllNetworks()) {
@@ -302,7 +299,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
// If there's no wifi IPv4 address, we might be a client on an
// IPv6-only wifi network. We can only detect this on API 21+
if (wifi == null && SDK_INT >= 21) {
if (wifi == null) {
InetAddress ipv6 = getWifiClientIpv6Address();
if (ipv6 != null) return new Pair<>(ipv6, false);
}

View File

@@ -4,7 +4,6 @@ import android.app.Application;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
@@ -12,6 +11,7 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.concurrent.Executor;

View File

@@ -1,238 +0,0 @@
package org.briarproject.bramble.plugin.tor;
import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.AndroidWakeLock;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.AndroidUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.net.SocketFactory;
import androidx.annotation.ChecksSdkIntAtLeast;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidTorPlugin extends TorPlugin {
private static final List<String> LIBRARY_ARCHITECTURES =
asList("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
private static final String TOR_LIB_NAME = "libtor.so";
private static final String OBFS4_LIB_NAME = "libobfs4proxy.so";
private static final String SNOWFLAKE_LIB_NAME = "libsnowflake.so";
private static final Logger LOG =
getLogger(AndroidTorPlugin.class.getName());
private final Application app;
private final AndroidWakeLock wakeLock;
private final File torLib, obfs4Lib, snowflakeLib;
AndroidTorPlugin(Executor ioExecutor,
Executor wakefulIoExecutor,
Application app,
NetworkManager networkManager,
LocationUtils locationUtils,
SocketFactory torSocketFactory,
Clock clock,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback,
String architecture,
long maxLatency,
int maxIdleTime,
File torDirectory,
int torSocksPort,
int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, maxLatency,
maxIdleTime, torDirectory, torSocksPort, torControlPort);
this.app = app;
wakeLock = wakeLockManager.createWakeLock("TorPlugin");
String nativeLibDir = app.getApplicationInfo().nativeLibraryDir;
torLib = new File(nativeLibDir, TOR_LIB_NAME);
obfs4Lib = new File(nativeLibDir, OBFS4_LIB_NAME);
snowflakeLib = new File(nativeLibDir, SNOWFLAKE_LIB_NAME);
}
@Override
protected int getProcessId() {
return android.os.Process.myPid();
}
@Override
protected long getLastUpdateTime() {
try {
PackageManager pm = app.getPackageManager();
PackageInfo pi = pm.getPackageInfo(app.getPackageName(), 0);
return pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new AssertionError(e);
}
}
@Override
protected void enableNetwork(boolean enable) throws IOException {
if (enable) wakeLock.acquire();
super.enableNetwork(enable);
if (!enable) wakeLock.release();
}
@Override
@ChecksSdkIntAtLeast(api = 25)
protected boolean canVerifyLetsEncryptCerts() {
return SDK_INT >= 25;
}
@Override
public void stop() {
super.stop();
wakeLock.release();
}
@Override
protected File getTorExecutableFile() {
return torLib.exists() ? torLib : super.getTorExecutableFile();
}
@Override
protected File getObfs4ExecutableFile() {
return obfs4Lib.exists() ? obfs4Lib : super.getObfs4ExecutableFile();
}
@Override
protected File getSnowflakeExecutableFile() {
return snowflakeLib.exists()
? snowflakeLib : super.getSnowflakeExecutableFile();
}
@Override
protected void installTorExecutable() throws IOException {
installExecutable(super.getTorExecutableFile(), torLib, TOR_LIB_NAME);
}
@Override
protected void installObfs4Executable() throws IOException {
installExecutable(super.getObfs4ExecutableFile(), obfs4Lib,
OBFS4_LIB_NAME);
}
@Override
protected void installSnowflakeExecutable() throws IOException {
installExecutable(super.getSnowflakeExecutableFile(), snowflakeLib,
SNOWFLAKE_LIB_NAME);
}
private void installExecutable(File extracted, File lib, String libName)
throws IOException {
if (lib.exists()) {
// If an older version left behind a binary, delete it
if (extracted.exists()) {
if (extracted.delete()) LOG.info("Deleted old binary");
else LOG.info("Failed to delete old binary");
}
} else if (SDK_INT < 29) {
// The binary wasn't extracted at install time. Try to extract it
extractLibraryFromApk(libName, extracted);
} else {
// No point extracting the binary, we won't be allowed to execute it
throw new FileNotFoundException(lib.getAbsolutePath());
}
}
private void extractLibraryFromApk(String libName, File dest)
throws IOException {
File sourceDir = new File(app.getApplicationInfo().sourceDir);
if (sourceDir.isFile()) {
// Look for other APK files in the same directory, if we're allowed
File parent = sourceDir.getParentFile();
if (parent != null) sourceDir = parent;
}
List<String> libPaths = getSupportedLibraryPaths(libName);
for (File apk : findApkFiles(sourceDir)) {
ZipInputStream zin = new ZipInputStream(new FileInputStream(apk));
for (ZipEntry e = zin.getNextEntry(); e != null;
e = zin.getNextEntry()) {
if (libPaths.contains(e.getName())) {
if (LOG.isLoggable(INFO)) {
LOG.info("Extracting " + e.getName()
+ " from " + apk.getAbsolutePath());
}
extract(zin, dest); // Zip input stream will be closed
return;
}
}
zin.close();
}
throw new FileNotFoundException(libName);
}
/**
* Returns all files with the extension .apk or .APK under the given root.
*/
private List<File> findApkFiles(File root) {
List<File> files = new ArrayList<>();
findApkFiles(root, files);
return files;
}
private void findApkFiles(File f, List<File> files) {
if (f.isFile() && f.getName().toLowerCase().endsWith(".apk")) {
files.add(f);
} else if (f.isDirectory()) {
File[] children = f.listFiles();
if (children != null) {
for (File child : children) findApkFiles(child, files);
}
}
}
/**
* Returns the paths at which libraries with the given name would be found
* inside an APK file, for all architectures supported by the device, in
* order of preference.
*/
private List<String> getSupportedLibraryPaths(String libName) {
List<String> architectures = new ArrayList<>();
for (String abi : AndroidUtils.getSupportedArchitectures()) {
if (LIBRARY_ARCHITECTURES.contains(abi)) {
architectures.add("lib/" + abi + "/" + libName);
}
}
return architectures;
}
}

View File

@@ -2,23 +2,26 @@ package org.briarproject.bramble.plugin.tor;
import android.app.Application;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.nullsafety.NotNullByDefault;
import org.briarproject.onionwrapper.AndroidTorWrapper;
import org.briarproject.onionwrapper.CircumventionProvider;
import org.briarproject.onionwrapper.LocationUtils;
import org.briarproject.onionwrapper.TorWrapper;
import java.io.File;
import java.util.concurrent.Executor;
@@ -39,13 +42,13 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
@Inject
AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@EventExecutor Executor eventExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
NetworkManager networkManager,
LocationUtils locationUtils,
EventBus eventBus,
SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager,
Clock clock,
@@ -55,8 +58,8 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
@TorControlPort int torControlPort,
Application app,
AndroidWakeLockManager wakeLockManager) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
eventBus, torSocketFactory, backoffFactory, resourceProvider,
super(ioExecutor, eventExecutor, wakefulIoExecutor, networkManager,
locationUtils, eventBus, torSocketFactory, backoffFactory,
circumventionProvider, batteryManager, clock, crypto,
torDirectory, torSocksPort, torControlPort);
this.app = app;
@@ -79,12 +82,13 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
TorPlugin createPluginInstance(Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback,
String architecture) {
return new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, wakeLockManager,
backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort);
TorWrapper tor = new AndroidTorWrapper(app, wakeLockManager,
ioExecutor, eventExecutor, architecture, torDirectory,
torSocksPort, torControlPort);
return new TorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, tor, callback, MAX_LATENCY,
MAX_IDLE_TIME);
}
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
interface AlarmConstants {

View File

@@ -1,72 +0,0 @@
package org.briarproject.bramble.system;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.LocationUtils;
import java.util.Locale;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.content.Context.TELEPHONY_SERVICE;
@NotNullByDefault
class AndroidLocationUtils implements LocationUtils {
private static final Logger LOG =
Logger.getLogger(AndroidLocationUtils.class.getName());
private final Context appContext;
@Inject
AndroidLocationUtils(Application app) {
appContext = app.getApplicationContext();
}
/**
* This guesses the current country from the first of these sources that
* succeeds (also in order of likelihood of being correct):
*
* <ul>
* <li>Phone network. This works even when no SIM card is inserted, or a
* foreign SIM card is inserted.</li>
* <li>SIM card. This is only an heuristic and assumes the user is not
* roaming.</li>
* <li>User locale. This is an even worse heuristic.</li>
* </ul>
*
* Note: this is very similar to <a href="https://android.googlesource.com/platform/frameworks/base/+/cd92588%5E/location/java/android/location/CountryDetector.java">
* this API</a> except it seems that Google doesn't want us to use it for
* some reason - both that class and {@code Context.COUNTRY_CODE} are
* annotated {@code @hide}.
*/
@Override
@SuppressLint("DefaultLocale")
public String getCurrentCountry() {
String countryCode = getCountryFromPhoneNetwork();
if (!TextUtils.isEmpty(countryCode)) return countryCode.toUpperCase();
LOG.info("Falling back to SIM card country");
countryCode = getCountryFromSimCard();
if (!TextUtils.isEmpty(countryCode)) return countryCode.toUpperCase();
LOG.info("Falling back to user-defined locale");
return Locale.getDefault().getCountry();
}
private String getCountryFromPhoneNetwork() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm == null ? "" : tm.getNetworkCountryIso();
}
private String getCountryFromSimCard() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm == null ? "" : tm.getSimCountryIso();
}
}

View File

@@ -4,8 +4,8 @@ import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.InputStream;

View File

@@ -6,28 +6,31 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Build;
import android.os.Parcel;
import android.os.StrictMode;
import android.provider.Settings;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Set;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.os.Build.FINGERPRINT;
import static android.os.Build.SERIAL;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Process.myPid;
import static android.os.Process.myTid;
import static android.os.Process.myUid;
import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable
@NotNullByDefault
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
private static final int SEED_LENGTH = 32;
private final Context appContext;
@Inject
@@ -39,22 +42,27 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
@Override
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
super.writeToEntropyPool(out);
out.writeInt(android.os.Process.myPid());
out.writeInt(android.os.Process.myTid());
out.writeInt(android.os.Process.myUid());
if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT);
if (Build.SERIAL != null) out.writeUTF(Build.SERIAL);
out.writeInt(myPid());
out.writeInt(myTid());
out.writeInt(myUid());
if (FINGERPRINT != null) out.writeUTF(FINGERPRINT);
if (SERIAL != null) out.writeUTF(SERIAL);
ContentResolver contentResolver = appContext.getContentResolver();
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
if (id != null) out.writeUTF(id);
Parcel parcel = Parcel.obtain();
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) {
for (BluetoothDevice device : bt.getBondedDevices())
parcel.writeParcelable(device, 0);
// On API 31 and higher we need permission to access bonded devices
if (SDK_INT < 31) {
Parcel parcel = Parcel.obtain();
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) {
@SuppressLint("MissingPermission")
Set<BluetoothDevice> deviceSet = bt.getBondedDevices();
for (BluetoothDevice device : deviceSet)
parcel.writeParcelable(device, 0);
}
out.write(parcel.marshall());
parcel.recycle();
}
out.write(parcel.marshall());
parcel.recycle();
}
@Override
@@ -62,27 +70,6 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
// Silence strict mode
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites();
super.writeSeed();
if (SDK_INT <= 18) applyOpenSslFix();
StrictMode.setThreadPolicy(tp);
}
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private void applyOpenSslFix() {
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
SEED_LENGTH);
try {
// Seed the OpenSSL PRNG
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, (Object) seed);
// Mix the output of the Linux PRNG into the OpenSSL PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
if (bytesRead != 1024) throw new IOException();
} catch (Exception e) {
throw new SecurityException(e);
}
}
}

View File

@@ -1,12 +1,14 @@
package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.onionwrapper.AndroidLocationUtilsFactory;
import org.briarproject.onionwrapper.LocationUtils;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
@@ -46,8 +48,9 @@ public class AndroidSystemModule {
}
@Provides
LocationUtils provideLocationUtils(AndroidLocationUtils locationUtils) {
return locationUtils;
@Singleton
LocationUtils provideLocationUtils(Application app) {
return AndroidLocationUtilsFactory.createAndroidLocationUtils(app);
}
@Provides
@@ -69,11 +72,4 @@ public class AndroidSystemModule {
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
return provider;
}
@Provides
@Singleton
AndroidWakeLockManager provideWakeLockManager(
AndroidWakeLockManagerImpl wakeLockManager) {
return wakeLockManager;
}
}

View File

@@ -8,13 +8,13 @@ import android.content.Intent;
import android.os.Process;
import android.os.SystemClock;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.Cancellable;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AlarmListener;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.system.Wakeful;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.ArrayList;
import java.util.List;
@@ -41,6 +41,7 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.system.AlarmConstants.EXTRA_PID;
import static org.briarproject.bramble.system.AlarmConstants.REQUEST_ALARM;
import static org.briarproject.bramble.util.AndroidUtils.getImmutableFlags;
@ThreadSafe
@NotNullByDefault
@@ -199,7 +200,7 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
Intent i = new Intent(app, AlarmReceiver.class);
i.putExtra(EXTRA_PID, android.os.Process.myPid());
return PendingIntent.getBroadcast(app, REQUEST_ALARM, i,
FLAG_CANCEL_CURRENT);
getImmutableFlags(FLAG_CANCEL_CURRENT));
}
private class ScheduledTask

View File

@@ -2,9 +2,9 @@ package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.system.AlarmListener;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.TaskScheduler;
import java.util.concurrent.ScheduledExecutorService;

View File

@@ -1,74 +0,0 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AndroidWakeLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.FINE;
import static java.util.logging.Logger.getLogger;
/**
* A wrapper around a {@link SharedWakeLock} that provides the more convenient
* semantics of {@link AndroidWakeLock} (i.e. calls to acquire() and release()
* don't need to be balanced).
*/
@ThreadSafe
@NotNullByDefault
class AndroidWakeLockImpl implements AndroidWakeLock {
private static final Logger LOG =
getLogger(AndroidWakeLockImpl.class.getName());
private static final AtomicInteger INSTANCE_ID = new AtomicInteger(0);
private final SharedWakeLock sharedWakeLock;
private final String tag;
private final Object lock = new Object();
@GuardedBy("lock")
private boolean held = false;
AndroidWakeLockImpl(SharedWakeLock sharedWakeLock, String tag) {
this.sharedWakeLock = sharedWakeLock;
this.tag = tag + "_" + INSTANCE_ID.getAndIncrement();
}
@Override
public void acquire() {
synchronized (lock) {
if (held) {
if (LOG.isLoggable(FINE)) {
LOG.fine(tag + " already acquired");
}
} else {
if (LOG.isLoggable(FINE)) {
LOG.fine(tag + " acquiring shared wake lock");
}
held = true;
sharedWakeLock.acquire();
}
}
}
@Override
public void release() {
synchronized (lock) {
if (held) {
if (LOG.isLoggable(FINE)) {
LOG.fine(tag + " releasing shared wake lock");
}
held = false;
sharedWakeLock.release();
} else {
if (LOG.isLoggable(FINE)) {
LOG.fine(tag + " already released");
}
}
}
}
}

View File

@@ -1,125 +0,0 @@
package org.briarproject.bramble.system;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.PowerManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AndroidWakeLock;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@NotNullByDefault
class AndroidWakeLockManagerImpl implements AndroidWakeLockManager {
/**
* How often to replace the wake lock.
*/
private static final long LOCK_DURATION_MS = MINUTES.toMillis(1);
/**
* Automatically release the lock this many milliseconds after it's due
* to have been replaced and released.
*/
private static final long SAFETY_MARGIN_MS = SECONDS.toMillis(30);
private final SharedWakeLock sharedWakeLock;
@Inject
AndroidWakeLockManagerImpl(Application app,
ScheduledExecutorService scheduledExecutorService) {
PowerManager powerManager = (PowerManager)
requireNonNull(app.getSystemService(POWER_SERVICE));
String tag = getWakeLockTag(app);
sharedWakeLock = new RenewableWakeLock(powerManager,
scheduledExecutorService, PARTIAL_WAKE_LOCK, tag,
LOCK_DURATION_MS, SAFETY_MARGIN_MS);
}
@Override
public AndroidWakeLock createWakeLock(String tag) {
return new AndroidWakeLockImpl(sharedWakeLock, tag);
}
@Override
public void runWakefully(Runnable r, String tag) {
AndroidWakeLock wakeLock = createWakeLock(tag);
wakeLock.acquire();
try {
r.run();
} finally {
wakeLock.release();
}
}
@Override
public void executeWakefully(Runnable r, Executor executor, String tag) {
AndroidWakeLock wakeLock = createWakeLock(tag);
wakeLock.acquire();
try {
executor.execute(() -> {
try {
r.run();
} finally {
// Release the wake lock if the task throws an exception
wakeLock.release();
}
});
} catch (Exception e) {
// Release the wake lock if the executor throws an exception when
// we submit the task (in which case the release() call above won't
// happen)
wakeLock.release();
throw e;
}
}
@Override
public void executeWakefully(Runnable r, String tag) {
AndroidWakeLock wakeLock = createWakeLock(tag);
wakeLock.acquire();
try {
new Thread(() -> {
try {
r.run();
} finally {
wakeLock.release();
}
}).start();
} catch (Exception e) {
wakeLock.release();
throw e;
}
}
private String getWakeLockTag(Context ctx) {
PackageManager pm = ctx.getPackageManager();
if (isInstalled(pm, "com.huawei.powergenie")) {
return "LocationManagerService";
} else if (isInstalled(pm, "com.evenwell.PowerMonitor")) {
return "AudioIn";
}
return ctx.getPackageName();
}
private boolean isInstalled(PackageManager pm, String packageName) {
try {
pm.getPackageInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManagerFactory;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidWakeLockModule {
@Provides
@Singleton
AndroidWakeLockManager provideWakeLockManager(Application app,
ScheduledExecutorService scheduledExecutorService) {
return AndroidWakeLockManagerFactory.createAndroidWakeLockManager(app,
scheduledExecutorService);
}
}

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.system;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import java.util.concurrent.Executor;

View File

@@ -1,130 +0,0 @@
package org.briarproject.bramble.system;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@ThreadSafe
@NotNullByDefault
class RenewableWakeLock implements SharedWakeLock {
private static final Logger LOG =
getLogger(RenewableWakeLock.class.getName());
private final PowerManager powerManager;
private final ScheduledExecutorService scheduledExecutorService;
private final int levelAndFlags;
private final String tag;
private final long durationMs, safetyMarginMs;
private final Object lock = new Object();
@GuardedBy("lock")
@Nullable
private WakeLock wakeLock;
@GuardedBy("lock")
@Nullable
private Future<?> future;
@GuardedBy("lock")
private int refCount = 0;
@GuardedBy("lock")
private long acquired = 0;
RenewableWakeLock(PowerManager powerManager,
ScheduledExecutorService scheduledExecutorService,
int levelAndFlags,
String tag,
long durationMs,
long safetyMarginMs) {
this.powerManager = powerManager;
this.scheduledExecutorService = scheduledExecutorService;
this.levelAndFlags = levelAndFlags;
this.tag = tag;
this.durationMs = durationMs;
this.safetyMarginMs = safetyMarginMs;
}
@Override
public void acquire() {
synchronized (lock) {
refCount++;
if (refCount == 1) {
if (LOG.isLoggable(INFO)) {
LOG.info("Acquiring wake lock " + tag);
}
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
// We do our own reference counting so we can replace the lock
// TODO: Check whether using a ref-counted wake lock affects
// power management apps
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + safetyMarginMs);
future = scheduledExecutorService.schedule(this::renew,
durationMs, MILLISECONDS);
acquired = android.os.SystemClock.elapsedRealtime();
} else if (LOG.isLoggable(FINE)) {
LOG.fine("Wake lock " + tag + " has " + refCount + " holders");
}
}
}
private void renew() {
if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag);
synchronized (lock) {
if (wakeLock == null) {
LOG.info("Already released");
return;
}
if (LOG.isLoggable(FINE)) {
LOG.fine("Wake lock " + tag + " has " + refCount + " holders");
}
long now = android.os.SystemClock.elapsedRealtime();
long expiry = acquired + durationMs + safetyMarginMs;
if (now > expiry && LOG.isLoggable(WARNING)) {
LOG.warning("Wake lock expired " + (now - expiry) + " ms ago");
}
WakeLock oldWakeLock = wakeLock;
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + safetyMarginMs);
oldWakeLock.release();
future = scheduledExecutorService.schedule(this::renew, durationMs,
MILLISECONDS);
acquired = now;
}
}
@Override
public void release() {
synchronized (lock) {
refCount--;
if (refCount == 0) {
if (LOG.isLoggable(INFO)) {
LOG.info("Releasing wake lock " + tag);
}
requireNonNull(future).cancel(false);
future = null;
requireNonNull(wakeLock).release();
wakeLock = null;
acquired = 0;
} else if (LOG.isLoggable(FINE)) {
LOG.fine("Wake lock " + tag + " has " + refCount + " holders");
}
}
}
}

View File

@@ -1,22 +0,0 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AndroidWakeLock;
@NotNullByDefault
interface SharedWakeLock {
/**
* Acquires the wake lock. This increments the wake lock's reference count,
* so unlike {@link AndroidWakeLock#acquire()} every call to this method
* must be followed by a balancing call to {@link #release()}.
*/
void acquire();
/**
* Releases the wake lock. This decrements the wake lock's reference count,
* so unlike {@link AndroidWakeLock#release()} every call to this method
* must follow a balancing call to {@link #acquire()}.
*/
void release();
}

View File

@@ -8,25 +8,25 @@ import android.os.Looper;
import android.provider.Settings;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
import javax.annotation.Nullable;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Context.MODE_PRIVATE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
import static java.lang.Runtime.getRuntime;
import static android.os.Process.myPid;
import static android.os.Process.myUid;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@NotNullByDefault
public class AndroidUtils {
@@ -38,14 +38,12 @@ public class AndroidUtils {
private static final String STORED_LOGCAT = "dev-logcat";
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
if (SDK_INT >= 21) {
abis.addAll(asList(Build.SUPPORTED_ABIS));
} else {
abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
}
return abis;
return asList(Build.SUPPORTED_ABIS);
}
public static boolean hasBtConnectPermission(Context ctx) {
return SDK_INT < 31 || ctx.checkPermission(BLUETOOTH_CONNECT, myPid(),
myUid()) == PERMISSION_GRANTED;
}
public static String getBluetoothAddress(Context ctx,
@@ -55,6 +53,9 @@ public class AndroidUtils {
public static Pair<String, String> getBluetoothAddressAndMethod(Context ctx,
BluetoothAdapter adapter) {
// If we don't have permission to access the adapter's address, let
// the caller know we can't find it
if (!hasBtConnectPermission(ctx)) return new Pair<>("", "");
// Return the adapter's address if it's valid and not fake
@SuppressLint("HardwareIds")
String address = adapter.getAddress();
@@ -62,10 +63,17 @@ public class AndroidUtils {
return new Pair<>(address, "adapter");
}
// Return the address from settings if it's valid and not fake
address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address");
if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings");
if (SDK_INT < 33) {
try {
address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address");
if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings");
}
} catch (SecurityException e) {
// Some custom ROMs throw this exception on SDK_INT < 33.
// Fall through
}
}
// Try to get the address via reflection
address = getBluetoothAddressByReflection(adapter);
@@ -123,20 +131,14 @@ public class AndroidUtils {
return new String[] {"image/jpeg", "image/png", "image/gif"};
}
@Nullable
public static String getSystemProperty(String propName) {
try {
Process p = getRuntime().exec("getprop " + propName);
Scanner s = new Scanner(p.getInputStream());
String line = s.nextLine();
s.close();
return line;
} catch (SecurityException | IOException e) {
return null;
}
}
public static boolean isUiThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
public static int getImmutableFlags(int flags) {
if (SDK_INT >= 23) {
return FLAG_IMMUTABLE | flags;
}
return flags;
}
}

View File

@@ -87,6 +87,10 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
File potatoFile = new File(potatoDir, "file");
File filesDir = new File(testDir, "filesDir");
File externalCacheDir = new File(testDir, "externalCacheDir");
File externalCacheDir1 = new File(testDir, "externalCacheDir1");
File externalCacheDir2 = new File(testDir, "externalCacheDir2");
File externalMediaDir1 = new File(testDir, "externalMediaDir1");
File externalMediaDir2 = new File(testDir, "externalMediaDir2");
context.checking(new Expectations() {{
oneOf(prefs).edit();
@@ -109,6 +113,12 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(cacheDir));
oneOf(app).getExternalCacheDir();
will(returnValue(externalCacheDir));
oneOf(app).getExternalCacheDirs();
will(returnValue(
new File[] {externalCacheDir1, externalCacheDir2}));
oneOf(app).getExternalMediaDirs();
will(returnValue(
new File[] {externalMediaDir1, externalMediaDir2}));
}});
assertTrue(dbDir.mkdirs());
@@ -125,6 +135,10 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertTrue(potatoFile.createNewFile());
assertTrue(filesDir.mkdirs());
assertTrue(externalCacheDir.mkdirs());
assertTrue(externalCacheDir1.mkdirs());
assertTrue(externalCacheDir2.mkdirs());
assertTrue(externalMediaDir1.mkdirs());
assertTrue(externalMediaDir2.mkdirs());
accountManager.deleteAccount();
@@ -142,6 +156,10 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(potatoFile.exists());
assertFalse(filesDir.exists());
assertFalse(externalCacheDir.exists());
assertFalse(externalCacheDir1.exists());
assertFalse(externalCacheDir2.exists());
assertFalse(externalMediaDir1.exists());
assertFalse(externalMediaDir2.exists());
}
@After

View File

@@ -1,165 +1,67 @@
dependencyVerification {
verify = [
'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7',
'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15',
'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9',
'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397',
'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e',
'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46',
'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d',
'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178',
'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb',
'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5',
'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc',
'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea',
'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4',
'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983',
'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec',
'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26',
'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396',
'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d',
'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31',
'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f',
'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233',
'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6',
'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb',
'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162',
'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152',
'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140',
'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615',
'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
'com.thoughtworks.qdox:qdox:1.12.1:qdox-1.12.1.jar:21fba22f830e9268f07cf4ab2d99e8181abbdcb0cb91ee0228eb3cb918dcdd1d',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-io:commons-io:2.4:commons-io-2.4.jar:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d',
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.apache.ant:ant-antlr:1.10.9:ant-antlr-1.10.9.jar:7623dc9d0f20ea713290c6bf1a23f4c059447aef7ff9f5b2be75960f3f028d2e',
'org.apache.ant:ant-junit:1.10.9:ant-junit-1.10.9.jar:960bdc8827954d62206ba42d0a68a7ee4476175ba47bb113e17e77cce7394630',
'org.apache.ant:ant-launcher:1.10.9:ant-launcher-1.10.9.jar:fcce891f57f3be72149ff96ac2a80574165b3e0839866b95d24528f3027d50c1',
'org.apache.ant:ant:1.10.9:ant-1.10.9.jar:0715478af585ea80a18985613ebecdc7922122d45b2c3c970ff9b352cddb75fc',
'org.apache.commons:commons-compress:1.20:commons-compress-1.20.jar:0aeb625c948c697ea7b205156e112363b59ed5e2551212cd4e460bdb72c7c06e',
'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.14:obfs4proxy-android-0.0.14.jar:ad9b1ee4757b05867a19e993147bbb018bddd1f26ce3da746d5f037d5991a8c8',
'org.briarproject:snowflake-android:2.3.1:snowflake-android-2.3.1.jar:1f83c9a070f87b7074af13627709a8b5aced5460104be7166af736b1bb73c293',
'org.briarproject:tor-android:0.4.5.14:tor-android-0.4.5.14.jar:7cf1beaa6c1db51fc8fac263aba9624ef289c3db29772509efcbc59f7057330a',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',
'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793',
'org.codehaus.groovy:groovy-astbuilder:3.0.7:groovy-astbuilder-3.0.7.jar:b290451eb1583666e906c41f7d14747b4cc96363c99c478b244634fd5dfc9013',
'org.codehaus.groovy:groovy-cli-picocli:3.0.7:groovy-cli-picocli-3.0.7.jar:71b4bd11fb30a9c7b5618e22122c9c5141958fb27f4dcf0068b6f715088f6916',
'org.codehaus.groovy:groovy-console:3.0.7:groovy-console-3.0.7.jar:0541b358b6b8e5363215026736168fccfec1d91bac678d066fa77349eeeaa5dd',
'org.codehaus.groovy:groovy-datetime:3.0.7:groovy-datetime-3.0.7.jar:b9823d14b1a4f94236ae2f8a471701aab17e093e1b33402b91550b5c8dd88f04',
'org.codehaus.groovy:groovy-docgenerator:3.0.7:groovy-docgenerator-3.0.7.jar:bf53f7a11c9eb1e278e1b8ed2714c741bcf781235c803ad3ba1555f2614573f3',
'org.codehaus.groovy:groovy-groovydoc:3.0.7:groovy-groovydoc-3.0.7.jar:86b24dfc23c005066ab83927cdb54177f06c9531773f2e2d2ecc9a131f7c2677',
'org.codehaus.groovy:groovy-groovysh:3.0.7:groovy-groovysh-3.0.7.jar:5c40e78cbc09726aedd1c75fab112d245d665d6294870f9119e6cd3013ed14ab',
'org.codehaus.groovy:groovy-jmx:3.0.7:groovy-jmx-3.0.7.jar:0a89f3007884eb156751937d93382038b83d39c7c2f0ab156ebf251a7251f2ab',
'org.codehaus.groovy:groovy-json:3.0.7:groovy-json-3.0.7.jar:df1f0ee475e3fc93a6a0d17548294e160cca5de6d9d36817a7be1fbe650de03b',
'org.codehaus.groovy:groovy-jsr223:3.0.7:groovy-jsr223-3.0.7.jar:1dbd969595332416193baa660fbb45743d19696eaa25fe98e591a2739e13517e',
'org.codehaus.groovy:groovy-macro:3.0.7:groovy-macro-3.0.7.jar:c6cc06df526b39e2c359e2435f0071594c5a1c7babafaa6c184fdd8fa931531f',
'org.codehaus.groovy:groovy-nio:3.0.7:groovy-nio-3.0.7.jar:db54c577882b294cd8c975ec5451596441baf54781319c61627dca0e0c2361ef',
'org.codehaus.groovy:groovy-servlet:3.0.7:groovy-servlet-3.0.7.jar:5b6a909bf501c209adfb6205b9e740649609074455fd979bf9da4853e6ff9a39',
'org.codehaus.groovy:groovy-sql:3.0.7:groovy-sql-3.0.7.jar:252bb6c74e1a9f41756ad4fbd3b0d2eddc93bb61109961dd1952a37bf2d57a64',
'org.codehaus.groovy:groovy-swing:3.0.7:groovy-swing-3.0.7.jar:bd942032d9328d54c6679c49a41f6caa0d4a0039ebe598493b8a647730d98cff',
'org.codehaus.groovy:groovy-templates:3.0.7:groovy-templates-3.0.7.jar:f119e07f650ef186ae5a4b944f9e30915b14311bad47c94a6b32de8d4f69bc80',
'org.codehaus.groovy:groovy-test-junit5:3.0.7:groovy-test-junit5-3.0.7.jar:c16eeea07b8e396891e266d7ba9388b24ac804237ffdd9a792b0d08969bad014',
'org.codehaus.groovy:groovy-test:3.0.7:groovy-test-3.0.7.jar:f71afd7c25d43017f89ea47e6de6daec971d159047dae083c1513a8422d44b90',
'org.codehaus.groovy:groovy-testng:3.0.7:groovy-testng-3.0.7.jar:713d5f2231bbb5712aefd362151b9ffd884aeb7ef2e773315cc54259cbdd063d',
'org.codehaus.groovy:groovy-xml:3.0.7:groovy-xml-3.0.7.jar:8a62e7c9ddece3e82676c4bef2f2c100f459602cd1fb6a14e94187bf863e97ff',
'org.codehaus.groovy:groovy:3.0.7:groovy-3.0.7.jar:51d1777e8dd1f00e60ea56e00d8a354ff5aab1f00fc8464ae8d39d71867e401f',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f',
'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0',
'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea',
'org.jacoco:org.jacoco.report:0.8.3:org.jacoco.report-0.8.3.jar:aae08fa4ff043c807b8876cdb2d8705eb8449a55efce461baa6c09da245088c1',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
'org.jetbrains.kotlin:kotlin-reflect:1.4.32:kotlin-reflect-1.4.32.jar:dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10:kotlin-stdlib-common-1.7.10.jar:19f102efe9629f8eabc63853ad15c533e47c47f91fca09285c5bde86e59f91d4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.10:kotlin-stdlib-1.7.10.jar:e771fe74250a943e8f6346713201ff1d8cb95c3a5d1a91a22b65a9e04f6a8901',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182',
'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
]
verify = [
'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:dont-kill-me-lib:0.2.7:dont-kill-me-lib-0.2.7.aar:8a9540941fd927e1c127096a7a9b4aa61ce2f2965d2e24f849be92f9e57213c4',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:obfs4proxy-android:0.0.14-tor2:obfs4proxy-android-0.0.14-tor2.jar:a0a93770d6760ce57d9dbd31cc7177687374e00c3361dac22ab75e3b6e0f289e',
'org.briarproject:onionwrapper-android:0.1.0:onionwrapper-android-0.1.0.aar:d761854dac454616b3e0ca099b2cd17060365ce4316afe495cc7ae86b6c81d15',
'org.briarproject:onionwrapper-core:0.1.0:onionwrapper-core-0.1.0.jar:3e6631771b891c959403f6145de034c6f9816e7d067808d534f954eef9a1ca35',
'org.briarproject:snowflake-android:2.9.1:snowflake-android-2.9.1.jar:8d6195637edbe3717d205c2e524e9d3cb742b90fc67b10565d16262af134e489',
'org.briarproject:tor-android:0.4.8.9-1:tor-android-0.4.8.9-1.jar:8fbaaf0cb1663abd12852b7fc51a804534b7e7d865b4dec3fc4e9ec0e79f3ad5',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jacoco:org.jacoco.agent:0.8.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143',
'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605',
'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c',
'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0:kotlin-stdlib-common-1.8.0.jar:78ef93b59e603cc0fe51def9bd4c037b07cbace3b3b7806d1a490a42bc1f4cb2',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0:kotlin-stdlib-jdk7-1.8.0.jar:4c889d1d9803f5f2eb6c1592a6b7e62369ac7660c9eee15aba16fec059163666',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlin:kotlin-stdlib:1.8.0:kotlin-stdlib-1.8.0.jar:c77bef8774640b9fb9d6e217459ff220dae59878beb7d2e4b430506feffc654e',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34',
'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c',
'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
]
}

View File

@@ -7,8 +7,11 @@ apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies {
implementation "com.google.dagger:dagger:$dagger_version"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
api 'org.briarproject:null-safety:0.1'
api 'com.google.code.findbugs:jsr305:3.0.2'
api 'javax.inject:javax.inject:1'
api "com.google.dagger:dagger:$dagger_version"
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
testImplementation "junit:junit:$junit_version"
@@ -23,7 +26,7 @@ configurations {
testOutput.extendsFrom(testCompile)
}
task jarTest(type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
from sourceSets.test.output, sourceSets.main.output
classifier = 'test'
}
artifacts {

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Arrays;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Consumer<T> {

View File

@@ -11,8 +11,6 @@ public interface FeatureFlags {
boolean shouldEnableDisappearingMessages();
boolean shouldEnableMailbox();
boolean shouldEnablePrivateGroupsInCore();
boolean shouldEnableForumsInCore();

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Collections;
import java.util.HashMap;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Nameable {

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Predicate<T> {

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.ThreadSafe;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.lang.ref.WeakReference;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.DecryptionException;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;

View File

@@ -3,9 +3,9 @@ package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Collection;

View File

@@ -5,9 +5,9 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.nullsafety.NotNullByDefault;
/**
* The CleanupManager is responsible for tracking the cleanup deadlines of

View File

@@ -1,8 +1,8 @@
package org.briarproject.bramble.api.cleanup.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -8,10 +8,10 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,8 +1,8 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Collection;
import java.util.Collections;

View File

@@ -4,18 +4,19 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext;
import org.briarproject.bramble.api.sync.validation.MessageValidator;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@Immutable
@@ -23,17 +24,30 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
public abstract class BdfMessageValidator implements MessageValidator {
protected static final Logger LOG =
Logger.getLogger(BdfMessageValidator.class.getName());
getLogger(BdfMessageValidator.class.getName());
protected final ClientHelper clientHelper;
protected final MetadataEncoder metadataEncoder;
protected final Clock clock;
protected final boolean canonical;
/**
* Transitional alternative to
* {@link #BdfMessageValidator(ClientHelper, MetadataEncoder, Clock)} that
* accepts messages in non-canonical form, for backward compatibility.
*/
@Deprecated
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
MetadataEncoder metadataEncoder, Clock clock, boolean canonical) {
this.clientHelper = clientHelper;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
this.canonical = canonical;
}
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
this(clientHelper, metadataEncoder, clock, true);
}
protected abstract BdfMessageContext validateMessage(Message m, Group g,
@@ -49,7 +63,7 @@ public abstract class BdfMessageValidator implements MessageValidator {
"Timestamp is too far in the future");
}
try {
BdfList bodyList = clientHelper.toList(m.getBody());
BdfList bodyList = clientHelper.toList(m, canonical);
BdfMessageContext result = validateMessage(m, g, bodyList);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());

View File

@@ -11,12 +11,12 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import java.util.Collection;
@@ -49,6 +49,18 @@ public interface ClientHelper {
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
FormatException;
/**
* Transitional alternative to
* {@link #getMessageAsList(Transaction, MessageId)} that allows the
* message to be in non-canonical form, for backward compatibility.
*
* @param canonical True if the message must be in canonical form (a
* {@link FormatException} will be thrown if it's not.
*/
@Deprecated
BdfList getMessageAsList(Transaction txn, MessageId m, boolean canonical)
throws DbException, FormatException;
BdfDictionary getGroupMetadataAsDictionary(GroupId g) throws DbException,
FormatException;
@@ -106,6 +118,16 @@ public interface ClientHelper {
BdfList toList(Message m) throws FormatException;
/**
* Transitional alternative to {@link #toList(Message)} that allows the
* message to be in non-canonical form, for backward compatibility.
*
* @param canonical True if the message must be in canonical form (a
* {@link FormatException} will be thrown if it's not.
*/
@Deprecated
BdfList toList(Message m, boolean canonical) throws FormatException;
BdfList toList(Author a);
byte[] sign(String label, BdfList toSign, PrivateKey privateKey)

View File

@@ -2,9 +2,9 @@ package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ContactGroupFactory {

View File

@@ -2,12 +2,12 @@ package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.sync.OutgoingSessionRecord;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ConnectionManager {

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
@@ -12,6 +11,7 @@ import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionClosedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionOpenedEvent;
import org.briarproject.bramble.api.sync.Priority;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Collection;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
/**
* A duplex sync connection that can be closed by interrupting its outgoing

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

View File

@@ -3,8 +3,8 @@ package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

View File

@@ -12,7 +12,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import java.util.Collection;

View File

@@ -2,8 +2,8 @@ package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.ThreadSafe;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
@@ -54,6 +54,38 @@ public interface CryptoComponent {
KeyPair ourKeyPair, byte[]... inputs)
throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
* <p>
* Do not use this method for new protocols. The shared secret can be
* re-derived using the ephemeral public keys and both static private
* keys, so keys derived from the shared secret should not be used if
* forward secrecy is required. Use {@link #deriveSharedSecret(String,
* PublicKey, PublicKey, KeyPair, KeyPair, boolean, byte[]...)} instead.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
* <p>
*
* @param label A namespaced label indicating the purpose of this shared
* secret, to prevent it from being repurposed or colliding with a shared
* secret derived for another purpose
* @param theirStaticPublicKey The static public key of the remote party
* @param theirEphemeralPublicKey The ephemeral public key of the remote
* party
* @param ourStaticKeyPair The static key pair of the local party
* @param ourEphemeralKeyPair The ephemeral key pair of the local party
* @param alice True if the local party is Alice
* @param inputs Additional inputs that will be included in the
* derivation of the shared secret
* @return The shared secret
*/
@Deprecated
SecretKey deriveSharedSecretBadly(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs)
throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
*

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public class DecryptionException extends Exception {

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
/**
* Interface for strengthening a password-based key, for example by using a

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface PasswordStrengthEstimator {

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
/**
* The private half of a public/private {@link KeyPair}.

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
/**
* The public half of a public/private {@link KeyPair}.

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.InputStream;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.OutputStream;

View File

@@ -10,8 +10,29 @@ import java.util.TreeMap;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
/**
* A BDF dictionary contains zero or more key-value pairs, where the keys
* are strings and the values are BDF objects, which may be primitive types
* (null, boolean, integer, float, string, raw) or nested containers (list,
* dictionary).
* <p>
* Note that a BDF integer has the same range as a Java long, while a BDF
* float has the same range as a Java double. Method names in this class
* correspond to the Java types.
* <p>
* The getX() methods throw {@link FormatException} if the specified key is
* absent, the value is null, or the value does not have the requested type.
* <p>
* The getOptionalX() methods return null if the specified key is absent or
* the value is null, or throw {@link FormatException} if the value does not
* have the requested type.
* <p>
* The getX() methods that take a default value return the default value if
* the specified key is absent or the value is null, or throw
* {@link FormatException} if the value does not have the requested type.
*/
@NotThreadSafe
public class BdfDictionary extends TreeMap<String, Object> {
public final class BdfDictionary extends TreeMap<String, Object> {
public static final Object NULL_VALUE = new Object();
@@ -39,9 +60,9 @@ public class BdfDictionary extends TreeMap<String, Object> {
}
public Boolean getBoolean(String key) throws FormatException {
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
throw new FormatException();
Boolean value = getOptionalBoolean(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -52,19 +73,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Boolean getBoolean(String key, Boolean defaultValue) {
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
public Boolean getBoolean(String key, Boolean defaultValue)
throws FormatException {
Boolean value = getOptionalBoolean(key);
return value == null ? defaultValue : value;
}
public Long getLong(String key) throws FormatException {
Object o = get(key);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
throw new FormatException();
Long value = getOptionalLong(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -78,20 +96,69 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Long getLong(String key, Long defaultValue) {
Object o = get(key);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
return defaultValue;
public Long getLong(String key, Long defaultValue) throws FormatException {
Long value = getOptionalLong(key);
return value == null ? defaultValue : value;
}
/**
* Returns the integer with the specified key.
* <p>
* This method should be used in preference to
* <code>getLong(key).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if there is no value at the specified key,
* or if the value is null or cannot be represented as a Java int.
*/
public Integer getInt(String key) throws FormatException {
Integer value = getOptionalInt(key);
if (value == null) throw new FormatException();
return value;
}
/**
* Returns the integer with the specified key, or null if the key is
* absent or the value is null.
* <p>
* This method should be used in preference to
* <code>getOptionalLong(key).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the value at the specified key is not null
* and cannot be represented as a Java int.
*/
@Nullable
public Integer getOptionalInt(String key) throws FormatException {
Long value = getOptionalLong(key);
if (value == null) return null;
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
throw new FormatException();
}
return value.intValue();
}
/**
* Returns the integer with the specified key, or the given default
* value if the key is absent or the value is null.
* <p>
* This method should be used in preference to
* <code>getLong(key, defaultValue).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the value at the specified key is not null
* and cannot be represented as a Java int.
*/
public Integer getInt(String key, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(key);
return value == null ? defaultValue : value;
}
public Double getDouble(String key) throws FormatException {
Object o = get(key);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
throw new FormatException();
Double value = getOptionalDouble(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -103,17 +170,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Double getDouble(String key, Double defaultValue) {
Object o = get(key);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
return defaultValue;
public Double getDouble(String key, Double defaultValue)
throws FormatException {
Double value = getOptionalDouble(key);
return value == null ? defaultValue : value;
}
public String getString(String key) throws FormatException {
Object o = get(key);
if (o instanceof String) return (String) o;
throw new FormatException();
String value = getOptionalString(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -124,17 +190,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public String getString(String key, String defaultValue) {
Object o = get(key);
if (o instanceof String) return (String) o;
return defaultValue;
public String getString(String key, String defaultValue)
throws FormatException {
String value = getOptionalString(key);
return value == null ? defaultValue : value;
}
public byte[] getRaw(String key) throws FormatException {
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
throw new FormatException();
byte[] value = getOptionalRaw(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -146,17 +211,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public byte[] getRaw(String key, byte[] defaultValue) {
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
return defaultValue;
public byte[] getRaw(String key, byte[] defaultValue)
throws FormatException {
byte[] value = getOptionalRaw(key);
return value == null ? defaultValue : value;
}
public BdfList getList(String key) throws FormatException {
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
throw new FormatException();
BdfList value = getOptionalList(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -167,16 +231,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public BdfList getList(String key, BdfList defaultValue) {
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
public BdfList getList(String key, BdfList defaultValue)
throws FormatException {
BdfList value = getOptionalList(key);
return value == null ? defaultValue : value;
}
public BdfDictionary getDictionary(String key) throws FormatException {
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
throw new FormatException();
BdfDictionary value = getOptionalDictionary(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -188,9 +252,9 @@ public class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) {
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue)
throws FormatException {
BdfDictionary value = getOptionalDictionary(key);
return value == null ? defaultValue : value;
}
}

View File

@@ -1,11 +1,16 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
/**
* A convenience class for building {@link BdfDictionary BdfDictionaries}
* via the {@link BdfDictionary#of(Entry[]) factory method}. Entries in
* BdfDictionaries do not have to be BdfEntries.
*/
@Immutable
@NotNullByDefault
public class BdfEntry implements Entry<String, Object>, Comparable<BdfEntry> {

View File

@@ -12,8 +12,31 @@ import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
/**
* A BDF list contains zero or more BDF objects, which may be primitive types
* (null, boolean, integer, float, string, raw) or nested containers (list,
* dictionary).
* <p>
* Note that a BDF integer has the same range as a Java long, while a BDF
* float has the same range as a Java double. Method names in this class
* correspond to the Java types.
* <p>
* The getX() methods throw {@link FormatException} if the object at the
* specified index is null or does not have the requested type.
* <p>
* The getOptionalX() methods return null if the object at the specified
* index is null, or throw {@link FormatException} if the object does not
* have the requested type.
* <p>
* The getX() methods that take a default value return the default value if
* the object at the specified index is null, or throw
* {@link FormatException} if the object does not have the requested type.
* <p>
* All of the getters throw {@link FormatException} if the specified index is
* out of range.
*/
@NotThreadSafe
public class BdfList extends ArrayList<Object> {
public final class BdfList extends ArrayList<Object> {
/**
* Factory method for constructing lists inline.
@@ -33,15 +56,15 @@ public class BdfList extends ArrayList<Object> {
super(items);
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isInRange(int index) {
return index >= 0 && index < size();
}
public Boolean getBoolean(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
throw new FormatException();
Boolean value = getOptionalBoolean(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -53,21 +76,16 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Boolean getBoolean(int index, Boolean defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
public Boolean getBoolean(int index, Boolean defaultValue)
throws FormatException {
Boolean value = getOptionalBoolean(index);
return value == null ? defaultValue : value;
}
public Long getLong(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
throw new FormatException();
Long value = getOptionalLong(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -82,22 +100,70 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Long getLong(int index, Long defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
return defaultValue;
public Long getLong(int index, Long defaultValue) throws FormatException {
Long value = getOptionalLong(index);
return value == null ? defaultValue : value;
}
/**
* Returns the integer at the specified index.
* <p>
* This method should be used in preference to
* <code>getLong(index).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the
* value at the specified index is null or cannot be represented as a
* Java int.
*/
public Integer getInt(int index) throws FormatException {
Integer value = getOptionalInt(index);
if (value == null) throw new FormatException();
return value;
}
/**
* Returns the integer at the specified index, or null if the object at
* the specified index is null.
* <p>
* This method should be used in preference to
* <code>getOptionalLong(index).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the value
* at the specified index cannot be represented as a Java int.
*/
@Nullable
public Integer getOptionalInt(int index) throws FormatException {
Long value = getOptionalLong(index);
if (value == null) return null;
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
throw new FormatException();
}
return value.intValue();
}
/**
* Returns the integer at the specified index, or the given default value
* if the object at the specified index is null.
* <p>
* This method should be used in preference to
* <code>getLong(index, defaultValue).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the value
* at the specified index cannot be represented as a Java int.
*/
public Integer getInt(int index, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(index);
return value == null ? defaultValue : value;
}
public Double getDouble(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
throw new FormatException();
Double value = getOptionalDouble(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -110,19 +176,16 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Double getDouble(int index, Double defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
return defaultValue;
public Double getDouble(int index, Double defaultValue)
throws FormatException {
Double value = getOptionalDouble(index);
return value == null ? defaultValue : value;
}
public String getString(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof String) return (String) o;
throw new FormatException();
String value = getOptionalString(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -134,19 +197,16 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public String getString(int index, String defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof String) return (String) o;
return defaultValue;
public String getString(int index, String defaultValue)
throws FormatException {
String value = getOptionalString(index);
return value == null ? defaultValue : value;
}
public byte[] getRaw(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
throw new FormatException();
byte[] value = getOptionalRaw(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -159,19 +219,16 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public byte[] getRaw(int index, byte[] defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
return defaultValue;
public byte[] getRaw(int index, byte[] defaultValue)
throws FormatException {
byte[] value = getOptionalRaw(index);
return value == null ? defaultValue : value;
}
public BdfList getList(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
throw new FormatException();
BdfList value = getOptionalList(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -183,18 +240,16 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public BdfList getList(int index, BdfList defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
public BdfList getList(int index, BdfList defaultValue)
throws FormatException {
BdfList value = getOptionalList(index);
return value == null ? defaultValue : value;
}
public BdfDictionary getDictionary(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
throw new FormatException();
BdfDictionary value = getOptionalDictionary(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
@@ -207,10 +262,9 @@ public class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue)
throws FormatException {
BdfDictionary value = getOptionalDictionary(index);
return value == null ? defaultValue : value;
}
}

View File

@@ -1,76 +1,178 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
/**
* An interface for reading BDF objects from an input stream.
* <p>
* The readX() methods throw {@link FormatException} if the data is not in
* canonical form, but the hasX() and skipX() methods do not check for
* canonical form.
*/
@NotNullByDefault
public interface BdfReader {
int DEFAULT_NESTED_LIMIT = 5;
int DEFAULT_MAX_BUFFER_SIZE = 64 * 1024;
/**
* Returns true if the reader has reached the end of its input stream.
*/
boolean eof() throws IOException;
/**
* Closes the reader's input stream.
*/
void close() throws IOException;
/**
* Returns true if the next object in the input is a BDF null.
*/
boolean hasNull() throws IOException;
/**
* Reads a BDF null from the input.
*/
void readNull() throws IOException;
/**
* Skips over a BDF null.
*/
void skipNull() throws IOException;
/**
* Returns true if the next object in the input is a BDF boolean.
*/
boolean hasBoolean() throws IOException;
/**
* Reads a BDF boolean from the input and returns it.
*/
boolean readBoolean() throws IOException;
/**
* Skips over a BDF boolean.
*/
void skipBoolean() throws IOException;
/**
* Returns true if the next object in the input is a BDF integer, which
* has the same range as a Java long.
*/
boolean hasLong() throws IOException;
/**
* Reads a BDF integer from the input and returns it as a Java long.
*/
long readLong() throws IOException;
/**
* Skips over a BDF integer.
*/
void skipLong() throws IOException;
/**
* Returns true if the next object in the input is a BDF integer and the
* value would fit within the range of a Java int.
*/
boolean hasInt() throws IOException;
/**
* Reads a BDF integer from the input and returns it as a Java int.
*
* @throws FormatException if the value exceeds the range of a Java int.
*/
int readInt() throws IOException;
/**
* Skips over a BDF integer.
*
* @throws FormatException if the value exceeds the range of a Java int.
*/
void skipInt() throws IOException;
/**
* Returns true if the next object in the input is a BDF float, which has
* the same range as a Java double.
*/
boolean hasDouble() throws IOException;
/**
* Reads a BDF float from the input and returns it as a Java double.
*/
double readDouble() throws IOException;
/**
* Skips over a BDF float.
*/
void skipDouble() throws IOException;
/**
* Returns true if the next object in the input is a BDF string.
*/
boolean hasString() throws IOException;
/**
* Reads a BDF string from the input.
*
* @throws IOException If the string is not valid UTF-8.
*/
String readString() throws IOException;
/**
* Skips over a BDF string without checking whether it is valid UTF-8.
*/
void skipString() throws IOException;
/**
* Returns true if the next object in the input is a BDF raw.
*/
boolean hasRaw() throws IOException;
/**
* Reads a BDF raw from the input and returns it as a byte array.
*/
byte[] readRaw() throws IOException;
/**
* Skips over a BDF raw.
*/
void skipRaw() throws IOException;
/**
* Returns true if the next object in the input is a BDF list.
*/
boolean hasList() throws IOException;
/**
* Reads a BDF list from the input and returns it. The list's contents
* are parsed and validated.
*/
BdfList readList() throws IOException;
void readListStart() throws IOException;
boolean hasListEnd() throws IOException;
void readListEnd() throws IOException;
/**
* Skips over a BDF list. The list's contents are parsed (to determine
* their length) but not validated.
*/
void skipList() throws IOException;
/**
* Returns true if the next object in the input is a BDF dictionary.
*/
boolean hasDictionary() throws IOException;
/**
* Reads a BDF dictionary from the input and returns it. The dictionary's
* contents are parsed and validated.
*/
BdfDictionary readDictionary() throws IOException;
void readDictionaryStart() throws IOException;
boolean hasDictionaryEnd() throws IOException;
void readDictionaryEnd() throws IOException;
/**
* Skips over a BDF dictionary. The dictionary's contents are parsed
* (to determine their length) but not validated.
*/
void skipDictionary() throws IOException;
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.InputStream;
@@ -9,6 +9,14 @@ public interface BdfReaderFactory {
BdfReader createReader(InputStream in);
/**
* Transitional alternative to {@link #createReader(InputStream)} that
* can create a reader that accepts non-canonical input, for backward
* compatibility.
*/
@Deprecated
BdfReader createReader(InputStream in, boolean canonical);
BdfReader createReader(InputStream in, int nestedLimit,
int maxBufferSize);
int maxBufferSize, boolean canonical);
}

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.util.List;
import java.util.Map;

View File

@@ -1,36 +1,74 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
/**
* An interface for writing BDF objects to an output stream. The BDF output
* is in canonical form, ie integers and length fields are represented using
* the minimum number of bytes and dictionary keys are unique and sorted in
* lexicographic order.
*/
public interface BdfWriter {
/**
* Flushes the writer's output stream.
*/
void flush() throws IOException;
/**
* Closes the writer's output stream.
*/
void close() throws IOException;
/**
* Writes a BDF null to the output stream.
*/
void writeNull() throws IOException;
/**
* Writes a BDF boolean to the output stream.
*/
void writeBoolean(boolean b) throws IOException;
/**
* Writes a BDF integer (which has the same range as a Java long) to the
* output stream.
*/
void writeLong(long l) throws IOException;
/**
* Writes a BDF float (which has the same range as a Java double) to the
* output stream.
*/
void writeDouble(double d) throws IOException;
/**
* Writes a BDF string (which uses UTF-8 encoding) to the output stream.
*/
void writeString(String s) throws IOException;
/**
* Writes a BDF raw to the output stream.
*/
void writeRaw(byte[] b) throws IOException;
/**
* Writes a BDF list to the output stream.
*
* @throws FormatException if the contents of the given collection cannot
* be represented as (nested) BDF objects.
*/
void writeList(Collection<?> c) throws IOException;
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
/**
* Writes a BDF dictionary to the output stream.
*
* @throws FormatException if the contents of the given map cannot be
* represented as (nested) BDF objects.
*/
void writeDictionary(Map<?, ?> m) throws IOException;
void writeDictionaryStart() throws IOException;
void writeDictionaryEnd() throws IOException;
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.OutputStream;

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